summaryrefslogtreecommitdiff
path: root/js/tf-backend-cpu.js
diff options
context:
space:
mode:
authorFuwn <[email protected]>2025-12-01 18:16:09 -0800
committerGitHub <[email protected]>2025-12-01 18:16:09 -0800
commit6c81abf8b182ce677b74cf2c570281ffea7f63f8 (patch)
treec8d289dc53d26b27dac63980fbf332ea97c178d6 /js/tf-backend-cpu.js
downloadrysk-6c81abf8b182ce677b74cf2c570281ffea7f63f8.tar.xz
rysk-6c81abf8b182ce677b74cf2c570281ffea7f63f8.zip
Add files via upload
Diffstat (limited to 'js/tf-backend-cpu.js')
-rw-r--r--js/tf-backend-cpu.js9526
1 files changed, 9526 insertions, 0 deletions
diff --git a/js/tf-backend-cpu.js b/js/tf-backend-cpu.js
new file mode 100644
index 0000000..539d2c5
--- /dev/null
+++ b/js/tf-backend-cpu.js
@@ -0,0 +1,9526 @@
+/**
+ * @license
+ * Copyright 2021 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@tensorflow/tfjs-core'), require('seedrandom')) :
+ typeof define === 'function' && define.amd ? define(['exports', '@tensorflow/tfjs-core', 'seedrandom'], factory) :
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.tf = global.tf || {}, global.tf, global.seedrandom));
+}(this, (function (exports, tfjsCore, seedrandom) { 'use strict';
+
+ function _interopNamespace(e) {
+ if (e && e.__esModule) return e;
+ var n = Object.create(null);
+ if (e) {
+ Object.keys(e).forEach(function (k) {
+ if (k !== 'default') {
+ var d = Object.getOwnPropertyDescriptor(e, k);
+ Object.defineProperty(n, k, d.get ? d : {
+ enumerable: true,
+ get: function () {
+ return e[k];
+ }
+ });
+ }
+ });
+ }
+ n['default'] = e;
+ return n;
+ }
+
+ var seedrandom__namespace = /*#__PURE__*/_interopNamespace(seedrandom);
+
+ /*! *****************************************************************************
+ Copyright (c) Microsoft Corporation.
+
+ Permission to use, copy, modify, and/or distribute this software for any
+ purpose with or without fee is hereby granted.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ PERFORMANCE OF THIS SOFTWARE.
+ ***************************************************************************** */
+ /* global Reflect, Promise */
+ var extendStatics = function (d, b) {
+ extendStatics = Object.setPrototypeOf ||
+ ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
+ function (d, b) { for (var p in b)
+ if (b.hasOwnProperty(p))
+ d[p] = b[p]; };
+ return extendStatics(d, b);
+ };
+ function __extends(d, b) {
+ extendStatics(d, b);
+ function __() { this.constructor = d; }
+ d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+ }
+ function __awaiter(thisArg, _arguments, P, generator) {
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try {
+ step(generator.next(value));
+ }
+ catch (e) {
+ reject(e);
+ } }
+ function rejected(value) { try {
+ step(generator["throw"](value));
+ }
+ catch (e) {
+ reject(e);
+ } }
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
+ }
+ function __generator(thisArg, body) {
+ var _ = { label: 0, sent: function () { if (t[0] & 1)
+ throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function () { return this; }), g;
+ function verb(n) { return function (v) { return step([n, v]); }; }
+ function step(op) {
+ if (f)
+ throw new TypeError("Generator is already executing.");
+ while (_)
+ try {
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done)
+ return t;
+ if (y = 0, t)
+ op = [op[0] & 2, t.value];
+ switch (op[0]) {
+ case 0:
+ case 1:
+ t = op;
+ break;
+ case 4:
+ _.label++;
+ return { value: op[1], done: false };
+ case 5:
+ _.label++;
+ y = op[1];
+ op = [0];
+ continue;
+ case 7:
+ op = _.ops.pop();
+ _.trys.pop();
+ continue;
+ default:
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
+ _ = 0;
+ continue;
+ }
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) {
+ _.label = op[1];
+ break;
+ }
+ if (op[0] === 6 && _.label < t[1]) {
+ _.label = t[1];
+ t = op;
+ break;
+ }
+ if (t && _.label < t[2]) {
+ _.label = t[2];
+ _.ops.push(op);
+ break;
+ }
+ if (t[2])
+ _.ops.pop();
+ _.trys.pop();
+ continue;
+ }
+ op = body.call(thisArg, _);
+ }
+ catch (e) {
+ op = [6, e];
+ y = 0;
+ }
+ finally {
+ f = t = 0;
+ }
+ if (op[0] & 5)
+ throw op[1];
+ return { value: op[0] ? op[1] : void 0, done: true };
+ }
+ }
+ function __values(o) {
+ var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
+ if (m)
+ return m.call(o);
+ if (o && typeof o.length === "number")
+ return {
+ next: function () {
+ if (o && i >= o.length)
+ o = void 0;
+ return { value: o && o[i++], done: !o };
+ }
+ };
+ throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
+ }
+ function __read(o, n) {
+ var m = typeof Symbol === "function" && o[Symbol.iterator];
+ if (!m)
+ return o;
+ var i = m.call(o), r, ar = [], e;
+ try {
+ while ((n === void 0 || n-- > 0) && !(r = i.next()).done)
+ ar.push(r.value);
+ }
+ catch (error) {
+ e = { error: error };
+ }
+ finally {
+ try {
+ if (r && !r.done && (m = i["return"]))
+ m.call(i);
+ }
+ finally {
+ if (e)
+ throw e.error;
+ }
+ }
+ return ar;
+ }
+ function __spread() {
+ for (var ar = [], i = 0; i < arguments.length; i++)
+ ar = ar.concat(__read(arguments[i]));
+ return ar;
+ }
+
+ /**
+ * @license
+ * Copyright 2019 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ function assertNotComplex(tensor, opName) {
+ if (!Array.isArray(tensor)) {
+ tensor = [tensor];
+ }
+ tensor.forEach(function (t) {
+ if (t != null) {
+ tfjsCore.util.assert(t.dtype !== 'complex64', function () { return opName + " does not support complex64 tensors in the CPU backend."; });
+ }
+ });
+ }
+
+ var whereImpl = tfjsCore.kernel_impls.whereImpl;
+ var MathBackendCPU = /** @class */ (function (_super) {
+ __extends(MathBackendCPU, _super);
+ function MathBackendCPU() {
+ var _this = _super.call(this) || this;
+ _this.blockSize = 48;
+ _this.firstUse = true;
+ _this.data = new tfjsCore.DataStorage(_this, tfjsCore.engine());
+ return _this;
+ }
+ MathBackendCPU.prototype.nextDataId = function () {
+ return MathBackendCPU.nextDataId++;
+ };
+ MathBackendCPU.prototype.write = function (values, shape, dtype) {
+ if (this.firstUse) {
+ this.firstUse = false;
+ if (tfjsCore.env().get('IS_NODE')) {
+ tfjsCore.backend_util.warn('\n============================\n' +
+ 'Hi there 👋. Looks like you are running TensorFlow.js in ' +
+ 'Node.js. To speed things up dramatically, install our node ' +
+ 'backend, which binds to TensorFlow C++, by running ' +
+ 'npm i @tensorflow/tfjs-node, ' +
+ 'or npm i @tensorflow/tfjs-node-gpu if you have CUDA. ' +
+ 'Then call require(\'@tensorflow/tfjs-node\'); (-gpu ' +
+ 'suffix for CUDA) at the start of your program. ' +
+ 'Visit https://github.com/tensorflow/tfjs-node for more details.' +
+ '\n============================');
+ }
+ }
+ var dataId = { id: this.nextDataId() };
+ this.data.set(dataId, { values: values, dtype: dtype, refCount: 1 });
+ return dataId;
+ };
+ /**
+ * Create a data bucket in cpu backend.
+ * @param shape Shape of the `TensorInfo`.
+ * @param dtype DType of the `TensorInfo`.
+ * @param values The value of the `TensorInfo` stored as a flattened array.
+ */
+ MathBackendCPU.prototype.makeTensorInfo = function (shape, dtype, values) {
+ var outId;
+ if (dtype === 'string' && values != null && values.length > 0 &&
+ tfjsCore.util.isString(values[0])) {
+ var encodedValues = values.map(function (d) { return tfjsCore.util.encodeString(d); });
+ outId = this.write(encodedValues, shape, dtype);
+ }
+ else {
+ outId = this.write(values, shape, dtype);
+ }
+ return { dataId: outId, shape: shape, dtype: dtype };
+ };
+ /** Return refCount of a `TensorData`. */
+ MathBackendCPU.prototype.refCount = function (dataId) {
+ if (this.data.has(dataId)) {
+ var tensorData = this.data.get(dataId);
+ return tensorData.refCount;
+ }
+ return 0;
+ };
+ /** Increase refCount of a `TensorData`. */
+ MathBackendCPU.prototype.incRef = function (dataId) {
+ var tensorData = this.data.get(dataId);
+ tensorData.refCount++;
+ };
+ /** Decrease refCount of a `TensorData`. */
+ MathBackendCPU.prototype.decRef = function (dataId) {
+ if (this.data.has(dataId)) {
+ var tensorData = this.data.get(dataId);
+ tensorData.refCount--;
+ }
+ };
+ MathBackendCPU.prototype.move = function (dataId, values, shape, dtype, refCount) {
+ this.data.set(dataId, { values: values, dtype: dtype, refCount: refCount });
+ };
+ MathBackendCPU.prototype.numDataIds = function () {
+ return this.data.numDataIds();
+ };
+ MathBackendCPU.prototype.read = function (dataId) {
+ return __awaiter(this, void 0, void 0, function () {
+ return __generator(this, function (_b) {
+ return [2 /*return*/, this.readSync(dataId)];
+ });
+ });
+ };
+ MathBackendCPU.prototype.readSync = function (dataId) {
+ var _b = this.data.get(dataId), dtype = _b.dtype, complexTensorInfos = _b.complexTensorInfos;
+ if (dtype === 'complex64') {
+ var realValues = this.readSync(complexTensorInfos.real.dataId);
+ var imagValues = this.readSync(complexTensorInfos.imag.dataId);
+ return tfjsCore.backend_util.mergeRealAndImagArrays(realValues, imagValues);
+ }
+ return this.data.get(dataId).values;
+ };
+ MathBackendCPU.prototype.bufferSync = function (t) {
+ var data = this.readSync(t.dataId);
+ var decodedData = data;
+ if (t.dtype === 'string') {
+ try {
+ // Decode the bytes into string.
+ decodedData = data.map(function (d) { return tfjsCore.util.decodeString(d); });
+ }
+ catch (_a) {
+ throw new Error('Failed to decode encoded string bytes into utf-8');
+ }
+ }
+ return tfjsCore.buffer(t.shape, t.dtype, decodedData);
+ };
+ MathBackendCPU.prototype.makeOutput = function (values, shape, dtype) {
+ var dataId = this.write(values, shape, dtype);
+ return tfjsCore.engine().makeTensorFromDataId(dataId, shape, dtype, this);
+ };
+ /**
+ * Dispose the memory if the dataId has 0 refCount. Return true if the memory
+ * is released or memory is not managed in this backend, false if memory is
+ * not cleared.
+ * @param dataId
+ * @oaram force Optional, remove the data regardless of refCount
+ */
+ MathBackendCPU.prototype.disposeData = function (dataId, force) {
+ if (force === void 0) { force = false; }
+ if (this.data.has(dataId)) {
+ this.data.get(dataId).refCount--;
+ if (!force && this.data.get(dataId).refCount > 0) {
+ return false;
+ }
+ var complexTensorInfos = this.data.get(dataId).complexTensorInfos;
+ if (complexTensorInfos != null) {
+ this.disposeData(complexTensorInfos.real.dataId, true);
+ this.disposeData(complexTensorInfos.imag.dataId, true);
+ }
+ this.data.delete(dataId);
+ }
+ return true;
+ };
+ MathBackendCPU.prototype.disposeIntermediateTensorInfo = function (tensorInfo) {
+ this.disposeData(tensorInfo.dataId);
+ };
+ MathBackendCPU.prototype.time = function (f) {
+ return __awaiter(this, void 0, void 0, function () {
+ var start, kernelMs;
+ return __generator(this, function (_b) {
+ start = tfjsCore.util.now();
+ f();
+ kernelMs = tfjsCore.util.now() - start;
+ return [2 /*return*/, { kernelMs: kernelMs }];
+ });
+ });
+ };
+ MathBackendCPU.prototype.memory = function () {
+ return {
+ // Unreliable due to automatic gc. The numbers above are cumulative.
+ unreliable: true,
+ reasons: ['The reported memory is an upper bound. Due to automatic garbage ' +
+ 'collection, the true allocated memory may be less.']
+ };
+ };
+ MathBackendCPU.prototype.where = function (condition) {
+ assertNotComplex([condition], 'where');
+ var condVals = this.readSync(condition.dataId);
+ return whereImpl(condition.shape, condVals);
+ };
+ MathBackendCPU.prototype.dispose = function () { };
+ MathBackendCPU.prototype.floatPrecision = function () {
+ return 32;
+ };
+ /** Returns the smallest representable number. */
+ MathBackendCPU.prototype.epsilon = function () {
+ return _super.prototype.epsilon.call(this);
+ };
+ return MathBackendCPU;
+ }(tfjsCore.KernelBackend));
+ MathBackendCPU.nextDataId = 0;
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ function simpleAbsImpl(vals) {
+ var resultValues = new Float32Array(vals.length);
+ for (var i = 0; i < vals.length; ++i) {
+ resultValues[i] = Math.abs(vals[i]);
+ }
+ return resultValues;
+ }
+ var abs = function (args) {
+ var x = args.inputs.x;
+ var cpuBackend = args.backend;
+ assertNotComplex(x, 'abs');
+ var resultValues = new Float32Array(tfjsCore.util.sizeFromShape(x.shape));
+ var values = cpuBackend.data.get(x.dataId).values;
+ resultValues = simpleAbsImpl(values);
+ return cpuBackend.makeOutput(resultValues, x.shape, x.dtype);
+ };
+ var absConfig = {
+ kernelName: tfjsCore.Abs,
+ backendName: 'cpu',
+ kernelFunc: abs,
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ /**
+ * Template that creates implementation for binary ops. Supports broadcast.
+ */
+ function createSimpleBinaryKernelImpl(op) {
+ return function (aShape, bShape, aVals, bVals, dtype) {
+ var newShape = tfjsCore.backend_util.assertAndGetBroadcastShape(aShape, bShape);
+ var resultRank = newShape.length;
+ var resultStrides = tfjsCore.util.computeStrides(newShape);
+ var resultSize = tfjsCore.util.sizeFromShape(newShape);
+ var result = tfjsCore.util.getTypedArrayFromDType(dtype, resultSize);
+ var aRank = aShape.length;
+ var bRank = bShape.length;
+ var aStrides = tfjsCore.util.computeStrides(aShape);
+ var bStrides = tfjsCore.util.computeStrides(bShape);
+ var aBroadcastDims = tfjsCore.backend_util.getBroadcastDims(aShape, newShape);
+ var bBroadcastDims = tfjsCore.backend_util.getBroadcastDims(bShape, newShape);
+ if (aBroadcastDims.length + bBroadcastDims.length === 0) {
+ for (var i = 0; i < result.length; ++i) {
+ result[i] = op(aVals[i % aVals.length], bVals[i % bVals.length]);
+ }
+ }
+ else {
+ var _loop_1 = function (i) {
+ var loc = tfjsCore.util.indexToLoc(i, resultRank, resultStrides);
+ var aLoc = loc.slice(-aRank);
+ aBroadcastDims.forEach(function (d) { return aLoc[d] = 0; });
+ var aIndex = tfjsCore.util.locToIndex(aLoc, aRank, aStrides);
+ var bLoc = loc.slice(-bRank);
+ bBroadcastDims.forEach(function (d) { return bLoc[d] = 0; });
+ var bIndex = tfjsCore.util.locToIndex(bLoc, bRank, bStrides);
+ result[i] = op(aVals[aIndex], bVals[bIndex]);
+ };
+ for (var i = 0; i < result.length; ++i) {
+ _loop_1(i);
+ }
+ }
+ return [result, newShape];
+ };
+ }
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ function complex(args) {
+ var inputs = args.inputs, backend = args.backend;
+ var real = inputs.real, imag = inputs.imag;
+ var realVals = backend.data.get(real.dataId).values;
+ var imagVals = backend.data.get(imag.dataId).values;
+ var complexInfo = backend.makeTensorInfo(real.shape, 'complex64');
+ var complex = backend.data.get(complexInfo.dataId);
+ // The complex tensor owns the underlying real and imag tensorInfos, only the
+ // complex tensor tracks refCount, when complexData is disposed the
+ // underlying tensorData will be disposed.
+ complex.complexTensorInfos = {
+ real: backend.makeTensorInfo(real.shape, 'float32', realVals),
+ imag: backend.makeTensorInfo(imag.shape, 'float32', imagVals)
+ };
+ return complexInfo;
+ }
+ var complexConfig = {
+ kernelName: tfjsCore.Complex,
+ backendName: 'cpu',
+ kernelFunc: complex
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ /**
+ * Generates a tensorInfo with all zeros value.
+ * @param backend cpu backend.
+ * @param shape Shape for the zeros tensor.
+ * @param dtype Optional. If set, the result has this dtype.
+ */
+ function zeros(backend, shape, dtype) {
+ if (dtype === void 0) { dtype = 'float32'; }
+ if (dtype === 'complex64') {
+ var real = zeros(backend, shape, 'float32');
+ var imag = zeros(backend, shape, 'float32');
+ return complex({ inputs: { real: real, imag: imag }, backend: backend });
+ }
+ var values = tfjsCore.util.makeZerosTypedArray(tfjsCore.util.sizeFromShape(shape), dtype);
+ return backend.makeTensorInfo(shape, dtype, values);
+ }
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ function identity(args) {
+ var inputs = args.inputs, backend = args.backend;
+ var x = inputs.x;
+ backend.incRef(x.dataId);
+ return { dataId: x.dataId, shape: x.shape, dtype: x.dtype };
+ }
+ var identityConfig = {
+ kernelName: tfjsCore.Identity,
+ backendName: 'cpu',
+ kernelFunc: identity
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ function real(args) {
+ var inputs = args.inputs, backend = args.backend;
+ var input = inputs.input;
+ var real = backend.data.get(input.dataId).complexTensorInfos.real;
+ var realVal = backend.data.get(real.dataId).values;
+ // When complex tensor is disposed, its underlying parts will be disposed too.
+ // Make new tensor out of the real value of the complex. This makes sure the
+ // value is still accessible even if complex tensor is disposed.
+ return backend.makeTensorInfo(real.shape, real.dtype, realVal);
+ }
+ var realConfig = {
+ kernelName: tfjsCore.Real,
+ backendName: 'cpu',
+ kernelFunc: real
+ };
+
+ function cast(args) {
+ var inputs = args.inputs, backend = args.backend, attrs = args.attrs;
+ var x = inputs.x;
+ var dtype = attrs.dtype;
+ // Casting to complex64.
+ if (dtype === 'complex64') {
+ if (x.dtype === 'complex64') {
+ return identity({ inputs: { x: x }, backend: backend });
+ }
+ var zerosTensorInfo = zeros(backend, x.shape, x.dtype);
+ var floatX = cast({ inputs: { x: x }, backend: backend, attrs: { dtype: 'float32' } });
+ var result = complex({ inputs: { real: floatX, imag: zerosTensorInfo }, backend: backend });
+ backend.disposeIntermediateTensorInfo(zerosTensorInfo);
+ backend.disposeIntermediateTensorInfo(floatX);
+ return result;
+ }
+ // Casting from complex64
+ if (x.dtype === 'complex64') {
+ var realPart = real({ inputs: { input: x }, backend: backend });
+ var result = cast({ inputs: { x: realPart }, backend: backend, attrs: { dtype: dtype } });
+ backend.disposeIntermediateTensorInfo(realPart);
+ return result;
+ }
+ if (!tfjsCore.util.hasEncodingLoss(x.dtype, dtype)) {
+ // We don't change the underlying data, since we cast to higher
+ // precision.
+ var result = identity({ inputs: { x: x }, backend: backend });
+ return { dataId: result.dataId, shape: result.shape, dtype: dtype };
+ }
+ if (dtype === 'int32') {
+ var values = backend.data.get(x.dataId).values;
+ var resultValues = Int32Array.from(values);
+ return backend.makeTensorInfo(x.shape, 'int32', resultValues);
+ }
+ if (dtype === 'bool') {
+ // This is essentially the result of notEqual(x, 0). We avoid using
+ // kernel notEqual to avoid circular dependency, i.e. binary_utils ->
+ // cast -> notEqual -> binary_utils.
+ var xVals = backend.data.get(x.dataId).values;
+ var zero = tfjsCore.util.toTypedArray([0], x.dtype);
+ var _a = __read(createSimpleBinaryKernelImpl(function (a, b) { return (a !== b) ? 1 : 0; })(x.shape, [], xVals, zero, 'bool'), 2), resultData = _a[0], resultShape = _a[1];
+ return backend.makeTensorInfo(resultShape, 'bool', resultData);
+ }
+ throw new Error("Error in Cast: failed to cast " + x.dtype + " to " + dtype);
+ }
+ var castConfig = {
+ kernelName: tfjsCore.Cast,
+ backendName: 'cpu',
+ kernelFunc: cast
+ };
+
+ /**
+ * Template that creates a `KernelFunc` for binary ops.
+ * @param name Kernel name.
+ * @param binaryKernelImpl A `SimpleBinaryKernelImpl` for the kernel.
+ * @param binaryKernelComplexImpl Optional. If exists, represents a
+ * `ComplexBinaryKernelImpl` for the kernel, will be used when input dtype
+ * is `complex64`.
+ * @param dtype Optional. If set, the result has this dtype. Otherwise, the
+ * result has the same dtype as the first input. This is mainly used in
+ * comparison kernels, such as Equal, Less, Greater, etc.
+ */
+ function binaryKernelFunc(name, simpleImpl, complexImpl, dtype) {
+ if (complexImpl == null) {
+ return function (_a) {
+ var inputs = _a.inputs, backend = _a.backend;
+ var a = inputs.a, b = inputs.b;
+ var cpuBackend = backend;
+ assertNotComplex([a, b], name);
+ var aVals = cpuBackend.data.get(a.dataId).values;
+ var bVals = cpuBackend.data.get(b.dataId).values;
+ var decodedAVals = a.dtype === 'string' ?
+ // tslint:disable-next-line: no-any
+ tfjsCore.backend_util.fromUint8ToStringArray(aVals) :
+ aVals;
+ var decodedBVals = a.dtype === 'string' ?
+ // tslint:disable-next-line: no-any
+ tfjsCore.backend_util.fromUint8ToStringArray(bVals) :
+ bVals;
+ var $dtype = dtype || a.dtype;
+ var _b = __read(simpleImpl(a.shape, b.shape, decodedAVals, decodedBVals, $dtype), 2), resultData = _b[0], resultShape = _b[1];
+ return cpuBackend.makeTensorInfo(resultShape, $dtype, resultData);
+ };
+ }
+ return function (_a) {
+ var inputs = _a.inputs, backend = _a.backend;
+ var a = inputs.a, b = inputs.b;
+ var cpuBackend = backend;
+ if (a.dtype === 'complex64' || b.dtype === 'complex64') {
+ var $aComplex = cast({ inputs: { x: a }, backend: cpuBackend, attrs: { dtype: 'complex64' } });
+ var $aComplexVals = cpuBackend.data.get($aComplex.dataId);
+ var aReal = $aComplexVals.complexTensorInfos.real;
+ var aImag = $aComplexVals.complexTensorInfos.imag;
+ var aRealVals = cpuBackend.data.get(aReal.dataId).values;
+ var aImagVals = cpuBackend.data.get(aImag.dataId).values;
+ var $bComplex = cast({ inputs: { x: b }, backend: cpuBackend, attrs: { dtype: 'complex64' } });
+ var $bComplexVals = cpuBackend.data.get($bComplex.dataId);
+ var bReal = $bComplexVals.complexTensorInfos.real;
+ var bImag = $bComplexVals.complexTensorInfos.imag;
+ var bRealVals = cpuBackend.data.get(bReal.dataId).values;
+ var bImagVals = cpuBackend.data.get(bImag.dataId).values;
+ var _b = __read(complexImpl(a.shape, b.shape, aRealVals, aImagVals, bRealVals, bImagVals), 3), resultRealData = _b[0], resultImagData = _b[1], resultShape = _b[2];
+ var resultReal = cpuBackend.makeTensorInfo(resultShape, 'float32', resultRealData);
+ var resultImag = cpuBackend.makeTensorInfo(resultShape, 'float32', resultImagData);
+ var result = complex({ inputs: { real: resultReal, imag: resultImag }, backend: cpuBackend });
+ cpuBackend.disposeIntermediateTensorInfo($aComplex);
+ cpuBackend.disposeIntermediateTensorInfo($bComplex);
+ cpuBackend.disposeIntermediateTensorInfo(resultReal);
+ cpuBackend.disposeIntermediateTensorInfo(resultImag);
+ return result;
+ }
+ else {
+ var aVals = cpuBackend.data.get(a.dataId).values;
+ var bVals = cpuBackend.data.get(b.dataId).values;
+ var $dtype = dtype || a.dtype;
+ var _c = __read(simpleImpl(a.shape, b.shape, aVals, bVals, $dtype), 2), resultData = _c[0], resultShape = _c[1];
+ return cpuBackend.makeTensorInfo(resultShape, $dtype, resultData);
+ }
+ };
+ }
+ /**
+ * Template that creates the complex type implementation for binary ops.
+ * Supports broadcast.
+ */
+ function createComplexBinaryKernelImpl(op) {
+ return function (aShape, bShape, aRealVals, aImagVals, bRealVals, bImagVals) {
+ var resultShape = tfjsCore.backend_util.assertAndGetBroadcastShape(aShape, bShape);
+ var resultSize = tfjsCore.util.sizeFromShape(resultShape);
+ var resultRank = resultShape.length;
+ var resultStrides = tfjsCore.util.computeStrides(resultShape);
+ var resultRealVals = tfjsCore.util.getTypedArrayFromDType('float32', resultSize);
+ var resultImagVals = tfjsCore.util.getTypedArrayFromDType('float32', resultSize);
+ var aBroadcastDims = tfjsCore.backend_util.getBroadcastDims(aShape, resultShape);
+ var bBroadcastDims = tfjsCore.backend_util.getBroadcastDims(bShape, resultShape);
+ var aVals = tfjsCore.backend_util.mergeRealAndImagArrays(aRealVals, aImagVals);
+ var bVals = tfjsCore.backend_util.mergeRealAndImagArrays(bRealVals, bImagVals);
+ var aRank = aShape.length;
+ var aStrides = tfjsCore.util.computeStrides(aShape);
+ var bRank = bShape.length;
+ var bStrides = tfjsCore.util.computeStrides(bShape);
+ if (aBroadcastDims.length + bBroadcastDims.length === 0) {
+ for (var i = 0; i < resultRealVals.length; i++) {
+ var aIdx = i % aVals.length;
+ var bIdx = i % bVals.length;
+ var result = op(aVals[aIdx * 2], aVals[aIdx * 2 + 1], bVals[bIdx * 2], bVals[bIdx * 2 + 1]);
+ resultRealVals[i] = result.real;
+ resultImagVals[i] = result.imag;
+ }
+ }
+ else {
+ var _loop_1 = function (i) {
+ var loc = tfjsCore.util.indexToLoc(i, resultRank, resultStrides);
+ var aLoc = loc.slice(-aRank);
+ aBroadcastDims.forEach(function (d) { return aLoc[d] = 0; });
+ var aIndex = tfjsCore.util.locToIndex(aLoc, aRank, aStrides);
+ var bLoc = loc.slice(-bRank);
+ bBroadcastDims.forEach(function (d) { return bLoc[d] = 0; });
+ var bIndex = tfjsCore.util.locToIndex(bLoc, bRank, bStrides);
+ var opResult = op(aVals[aIndex * 2], aVals[aIndex * 2 + 1], bVals[bIndex * 2], bVals[bIndex * 2 + 1]);
+ resultRealVals[i] = opResult.real;
+ resultImagVals[i] = opResult.imag;
+ };
+ for (var i = 0; i < resultRealVals.length; i++) {
+ _loop_1(i);
+ }
+ }
+ return [resultRealVals, resultImagVals, resultShape];
+ };
+ }
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ var addImpl = createSimpleBinaryKernelImpl((function (a, b) { return a + b; }));
+ var addComplexImpl = createComplexBinaryKernelImpl((function (aReal, aImag, bReal, bImag) {
+ return { real: aReal + bReal, imag: aImag + bImag };
+ }));
+ var add = binaryKernelFunc(tfjsCore.Add, addImpl, addComplexImpl);
+ var addConfig = {
+ kernelName: tfjsCore.Add,
+ backendName: 'cpu',
+ kernelFunc: add
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ function bincountImpl(xVals, weightsVals, weightsDtype, weightsShape, size) {
+ var weightsSize = tfjsCore.util.sizeFromShape(weightsShape);
+ var outVals = tfjsCore.util.makeZerosTypedArray(size, weightsDtype);
+ for (var i = 0; i < xVals.length; i++) {
+ var value = xVals[i];
+ if (value < 0) {
+ throw new Error('Input x must be non-negative!');
+ }
+ if (value >= size) {
+ continue;
+ }
+ if (weightsSize > 0) {
+ outVals[value] += weightsVals[i];
+ }
+ else {
+ outVals[value] += 1;
+ }
+ }
+ return outVals;
+ }
+ function bincountReduceImpl(xBuf, weightsBuf, size, binaryOutput) {
+ if (binaryOutput === void 0) { binaryOutput = false; }
+ var numRows = xBuf.shape[0];
+ var numCols = xBuf.shape[1];
+ var outBuf = tfjsCore.buffer([numRows, size], weightsBuf.dtype);
+ for (var i = 0; i < numRows; i++) {
+ for (var j = 0; j < numCols; j++) {
+ var value = xBuf.get(i, j);
+ if (value < 0) {
+ throw new Error('Input x must be non-negative!');
+ }
+ if (value >= size) {
+ continue;
+ }
+ if (binaryOutput) {
+ outBuf.set(1, i, value);
+ }
+ else {
+ if (weightsBuf.size > 0) {
+ outBuf.set(outBuf.get(i, value) + weightsBuf.get(i, j), i, value);
+ }
+ else {
+ outBuf.set(outBuf.get(i, value) + 1, i, value);
+ }
+ }
+ }
+ }
+ return outBuf;
+ }
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ /**
+ * Template that creates implementation for unary op.
+ */
+ function createSimpleUnaryImpl(op) {
+ return function (values, dtype, attrs) {
+ var newValues = tfjsCore.util.getTypedArrayFromDType(dtype, values.length);
+ for (var i = 0; i < values.length; ++i) {
+ newValues[i] = op(values[i], attrs);
+ }
+ return newValues;
+ };
+ }
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ /**
+ * Template that creates a `KernelFunc` for unary ops.
+ * @param name Kernel name.
+ * @param op A `SimpleUnaryOperation` for the kernel.
+ * @param dtype Optional. If set, the result has this dtype. Otherwise, the
+ * result has the same dtype as the input. This is mainly used in certain
+ * kernels that return bool type, such as isFinite, isInf, etc.
+ */
+ function unaryKernelFunc(name, op, dtype) {
+ return function (_a) {
+ var inputs = _a.inputs, attrs = _a.attrs, backend = _a.backend;
+ var x = inputs.x;
+ assertNotComplex(x, name);
+ if (x.dtype === 'string' || dtype === 'string') {
+ throw new Error('unaryKernelFunc does not support string input/output');
+ }
+ var cpuBackend = backend;
+ var values = cpuBackend.data.get(x.dataId).values;
+ var xSize = tfjsCore.util.sizeFromShape(x.shape);
+ var $dtype = dtype || x.dtype;
+ var newValues = tfjsCore.util.getArrayFromDType($dtype, xSize);
+ for (var i = 0; i < xSize; ++i) {
+ newValues[i] = op(values[i], attrs);
+ }
+ return cpuBackend.makeTensorInfo(x.shape, $dtype, newValues);
+ };
+ }
+ /**
+ * Template that creates a `KernelFunc` for unary ops from the given
+ * `SimpleUnaryImpl`..
+ * @param name Kernel name.
+ * @param unaryImpl A `SimpleUnaryImpl` that implements the op.
+ * @param dtype Optional. If set, the result has this dtype. Otherwise, the
+ * result has the same dtype as the input. This is mainly used in certain
+ * kernels that return bool type, such as isFinite, isInf, etc.
+ */
+ function unaryKernelFuncFromImpl(name, unaryImpl, dtype) {
+ return function (_a) {
+ var inputs = _a.inputs, attrs = _a.attrs, backend = _a.backend;
+ var x = inputs.x;
+ assertNotComplex(x, name);
+ if (x.dtype === 'string' || dtype === 'string') {
+ throw new Error('unaryKernelFunc does not support string input/output');
+ }
+ var cpuBackend = backend;
+ var values = cpuBackend.data.get(x.dataId).values;
+ var $dtype = dtype || x.dtype;
+ var newValues = unaryImpl(values, $dtype, attrs);
+ return cpuBackend.makeTensorInfo(x.shape, $dtype, newValues);
+ };
+ }
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ var ceilImpl = createSimpleUnaryImpl(function (xi) { return Math.ceil(xi); });
+ var ceil = unaryKernelFuncFromImpl(tfjsCore.Ceil, ceilImpl);
+ var ceilConfig = {
+ kernelName: tfjsCore.Ceil,
+ backendName: 'cpu',
+ kernelFunc: ceil,
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ function concatImpl(inputs, outShape, dtype, simplyConcat) {
+ var outVals = tfjsCore.util.getArrayFromDType(dtype, tfjsCore.util.sizeFromShape(outShape));
+ if (simplyConcat && dtype !== 'string') {
+ // Use built-in TypedArray.set() method for speed.
+ var offset_1 = 0;
+ inputs.forEach(function (input) {
+ var size = tfjsCore.util.sizeFromShape(input.shape);
+ outVals.set(input.vals, offset_1);
+ offset_1 += size;
+ });
+ }
+ else {
+ var colOffset_1 = 0;
+ inputs.forEach(function (input) {
+ var decodedData = dtype === 'string' ?
+ tfjsCore.backend_util.fromUint8ToStringArray(input.vals) :
+ input.vals;
+ var tIdx = 0;
+ for (var row = 0; row < input.shape[0]; ++row) {
+ var resIdx = row * outShape[1] + colOffset_1;
+ for (var col = 0; col < input.shape[1]; ++col) {
+ outVals[resIdx + col] = decodedData[tIdx++];
+ }
+ }
+ colOffset_1 += input.shape[1];
+ });
+ }
+ return outVals;
+ }
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ var equalImpl = createSimpleBinaryKernelImpl(function (a, b) { return (a === b) ? 1 : 0; });
+ var equal = binaryKernelFunc(tfjsCore.Equal, equalImpl, null /* complexImpl */, 'bool');
+ var equalConfig = {
+ kernelName: tfjsCore.Equal,
+ backendName: 'cpu',
+ kernelFunc: equal
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ var expImpl = createSimpleUnaryImpl(function (xi) { return Math.exp(xi); });
+ var exp = unaryKernelFuncFromImpl(tfjsCore.Exp, expImpl, 'float32');
+ var expConfig = {
+ kernelName: tfjsCore.Exp,
+ backendName: 'cpu',
+ kernelFunc: exp,
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ var expm1Impl = createSimpleUnaryImpl(function (xi) { return Math.expm1(xi); });
+ var expm1 = unaryKernelFuncFromImpl(tfjsCore.Expm1, expm1Impl);
+ var expm1Config = {
+ kernelName: tfjsCore.Expm1,
+ backendName: 'cpu',
+ kernelFunc: expm1,
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ var floorImpl = createSimpleUnaryImpl(function (xi) { return Math.floor(xi); });
+ var floor = unaryKernelFuncFromImpl(tfjsCore.Floor, floorImpl);
+ var floorConfig = {
+ kernelName: tfjsCore.Floor,
+ backendName: 'cpu',
+ kernelFunc: floor,
+ };
+
+ function gatherNdImpl(indicesData, paramsBuf, dtype, numSlices, sliceRank, sliceSize, strides, paramsShape, paramsSize) {
+ var outBuf = tfjsCore.buffer([numSlices, sliceSize], dtype);
+ for (var i = 0; i < numSlices; i++) {
+ var index = [];
+ var flattenIndex = 0;
+ for (var j = 0; j < sliceRank; j++) {
+ var dim = indicesData[i * sliceRank + j];
+ flattenIndex += dim * strides[j];
+ index.push(dim);
+ }
+ if (flattenIndex < 0 || flattenIndex >= paramsSize / sliceSize) {
+ throw new Error("Invalid indices: " + index + " does not index into " + paramsShape);
+ }
+ for (var k = 0; k < sliceSize; k++) {
+ outBuf.values[i * sliceSize + k] = paramsBuf.get.apply(paramsBuf, __spread(paramsBuf.indexToLoc(flattenIndex * sliceSize + k)));
+ }
+ }
+ return outBuf;
+ }
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ function gatherV2Impl(xBuf, indicesBuf, flattenOutputShape) {
+ var outBuf = tfjsCore.buffer(flattenOutputShape, xBuf.dtype);
+ for (var i = 0; i < outBuf.size; ++i) {
+ var newLoc = outBuf.indexToLoc(i);
+ var originalLoc = newLoc.slice();
+ var batchIdx = originalLoc[0];
+ var indicesIdx = originalLoc[2];
+ var indicesIndex = indicesBuf.locToIndex([batchIdx, indicesIdx]);
+ originalLoc[2] = indicesBuf.values[indicesIndex];
+ var originalIndex = xBuf.locToIndex(originalLoc);
+ outBuf.values[i] = xBuf.values[originalIndex];
+ }
+ return outBuf;
+ }
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ var greaterImpl = createSimpleBinaryKernelImpl(function (a, b) { return (a > b) ? 1 : 0; });
+ var greater = binaryKernelFunc(tfjsCore.Greater, greaterImpl, null /* complexImpl */, 'bool');
+ var greaterConfig = {
+ kernelName: tfjsCore.Greater,
+ backendName: 'cpu',
+ kernelFunc: greater
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ var greaterEqualImpl = createSimpleBinaryKernelImpl(function (a, b) { return (a >= b) ? 1 : 0; });
+ var greaterEqual = binaryKernelFunc(tfjsCore.GreaterEqual, greaterEqualImpl, null /* complexImpl */, 'bool');
+ var greaterEqualConfig = {
+ kernelName: tfjsCore.GreaterEqual,
+ backendName: 'cpu',
+ kernelFunc: greaterEqual
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ var lessImpl = createSimpleBinaryKernelImpl(function (a, b) { return (a < b) ? 1 : 0; });
+ var less = binaryKernelFunc(tfjsCore.Less, lessImpl, null /* complexImpl */, 'bool');
+ var lessConfig = {
+ kernelName: tfjsCore.Less,
+ backendName: 'cpu',
+ kernelFunc: less
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ var lessEqualImpl = createSimpleBinaryKernelImpl(function (a, b) { return (a <= b) ? 1 : 0; });
+ var lessEqual = binaryKernelFunc(tfjsCore.LessEqual, lessEqualImpl, null /* complexImpl */, 'bool');
+ var lessEqualConfig = {
+ kernelName: tfjsCore.LessEqual,
+ backendName: 'cpu',
+ kernelFunc: lessEqual
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ function linSpaceImpl(start, stop, num) {
+ var step = (stop - start) / (num - 1);
+ var values = tfjsCore.util.makeZerosTypedArray(num, 'float32');
+ values[0] = start;
+ for (var i = 1; i < values.length; i++) {
+ values[i] = values[i - 1] + step;
+ }
+ return values;
+ }
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ var logImpl = createSimpleUnaryImpl(function (xi) { return Math.log(xi); });
+ var log = unaryKernelFuncFromImpl(tfjsCore.Log, logImpl);
+ var logConfig = {
+ kernelName: tfjsCore.Log,
+ backendName: 'cpu',
+ kernelFunc: log,
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ function maxImpl(aVals, reduceSize, outShape, dtype) {
+ var vals = tfjsCore.util.getTypedArrayFromDType(dtype, tfjsCore.util.sizeFromShape(outShape));
+ for (var i = 0; i < vals.length; ++i) {
+ var offset = i * reduceSize;
+ var max = aVals[offset];
+ for (var j = 0; j < reduceSize; ++j) {
+ var value = aVals[offset + j];
+ if (Number.isNaN(value) ||
+ value > max) { // comparison with NaN always return false
+ max = value;
+ }
+ }
+ vals[i] = max;
+ }
+ return vals;
+ }
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ var maximumImpl = createSimpleBinaryKernelImpl((function (aValue, bValue) { return Math.max(aValue, bValue); }));
+ var maximum = binaryKernelFunc(tfjsCore.Maximum, maximumImpl);
+ var maximumConfig = {
+ kernelName: tfjsCore.Maximum,
+ backendName: 'cpu',
+ kernelFunc: maximum
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ var minimumImpl = createSimpleBinaryKernelImpl((function (aValue, bValue) { return Math.min(aValue, bValue); }));
+ var minimum = binaryKernelFunc(tfjsCore.Minimum, minimumImpl);
+ var minimumConfig = {
+ kernelName: tfjsCore.Minimum,
+ backendName: 'cpu',
+ kernelFunc: minimum
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ var multiplyImpl = createSimpleBinaryKernelImpl((function (aValue, bValue) { return aValue * bValue; }));
+ var multiplyComplexImpl = createComplexBinaryKernelImpl((function (aReal, aImag, bReal, bImag) {
+ return {
+ real: aReal * bReal - aImag * bImag,
+ imag: aReal * bImag + aImag * bReal
+ };
+ }));
+ var multiply = binaryKernelFunc(tfjsCore.Multiply, multiplyImpl, multiplyComplexImpl);
+ var multiplyConfig = {
+ kernelName: tfjsCore.Multiply,
+ backendName: 'cpu',
+ kernelFunc: multiply
+ };
+
+ function negImpl(xVals, xShape, xDtype) {
+ var minusOne = tfjsCore.util.createScalarValue(-1, xDtype);
+ return multiplyImpl([], xShape, minusOne, xVals, xDtype);
+ }
+ function neg(args) {
+ var inputs = args.inputs, backend = args.backend;
+ var x = inputs.x;
+ assertNotComplex(x, 'neg');
+ var xVals = backend.data.get(x.dataId).values;
+ var _a = __read(negImpl(xVals, x.shape, x.dtype), 2), res = _a[0], newShape = _a[1];
+ return backend.makeTensorInfo(newShape, x.dtype, res);
+ }
+ var negConfig = {
+ kernelName: tfjsCore.Neg,
+ backendName: 'cpu',
+ kernelFunc: neg
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ var notEqualImpl = createSimpleBinaryKernelImpl((function (a, b) { return (a !== b) ? 1 : 0; }));
+ var notEqual = binaryKernelFunc(tfjsCore.NotEqual, notEqualImpl, null /* complexOp */, 'bool');
+ var notEqualConfig = {
+ kernelName: tfjsCore.NotEqual,
+ backendName: 'cpu',
+ kernelFunc: notEqual
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ function transposeImpl(xVals, xShape, dtype, perm, newShape) {
+ var xRank = xShape.length;
+ var xSize = tfjsCore.util.sizeFromShape(xShape);
+ var xStrides = tfjsCore.util.computeStrides(xShape);
+ var newStrides = tfjsCore.util.computeStrides(newShape);
+ var result = tfjsCore.util.getTypedArrayFromDType(dtype, tfjsCore.util.sizeFromShape(newShape));
+ for (var i = 0; i < xSize; ++i) {
+ var loc = tfjsCore.util.indexToLoc(i, xRank, xStrides);
+ // Permute location.
+ var newLoc = new Array(loc.length);
+ for (var i_1 = 0; i_1 < newLoc.length; i_1++) {
+ newLoc[i_1] = loc[perm[i_1]];
+ }
+ var newIndex = tfjsCore.util.locToIndex(newLoc, xRank, newStrides);
+ result[newIndex] = xVals[i];
+ }
+ return result;
+ }
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ function transpose(args) {
+ var inputs = args.inputs, attrs = args.attrs, backend = args.backend;
+ var x = inputs.x;
+ var perm = attrs.perm;
+ assertNotComplex(x, 'transpose');
+ var xRank = x.shape.length;
+ var newShape = new Array(xRank);
+ for (var i = 0; i < newShape.length; i++) {
+ newShape[i] = x.shape[perm[i]];
+ }
+ var values = backend.data.get(x.dataId).values;
+ var result = transposeImpl(values, x.shape, x.dtype, perm, newShape);
+ var dataId = backend.write(result, newShape, x.dtype);
+ return { dataId: dataId, shape: newShape, dtype: x.dtype };
+ }
+ var transposeConfig = {
+ kernelName: tfjsCore.Transpose,
+ backendName: 'cpu',
+ kernelFunc: transpose
+ };
+
+ function prodImpl(xShape, xDtype, xVals, reductionAxes) {
+ var _a = __read(tfjsCore.backend_util.computeOutAndReduceShapes(xShape, reductionAxes), 2), outShape = _a[0], reduceShape = _a[1];
+ var outDtype = tfjsCore.upcastType(xDtype, 'int32');
+ var outVals = tfjsCore.util.makeZerosTypedArray(tfjsCore.util.sizeFromShape(outShape), outDtype);
+ var reduceSize = tfjsCore.util.sizeFromShape(reduceShape);
+ for (var i = 0; i < outVals.length; ++i) {
+ var offset = i * reduceSize;
+ var prod_1 = 1;
+ for (var j = 0; j < reduceSize; ++j) {
+ prod_1 *= xVals[offset + j];
+ }
+ outVals[i] = prod_1;
+ }
+ return { outVals: outVals, outShape: outShape, outDtype: outDtype };
+ }
+ function prod(args) {
+ var inputs = args.inputs, backend = args.backend, attrs = args.attrs;
+ var x = inputs.x;
+ var axis = attrs.axis, keepDims = attrs.keepDims;
+ assertNotComplex(x, 'prod');
+ var xRank = x.shape.length;
+ var axes = tfjsCore.util.parseAxisParam(axis, x.shape);
+ var permutation = tfjsCore.backend_util.getAxesPermutation(axes, xRank);
+ var reductionAxes = axes;
+ var permutedX = x;
+ var intermediateTensorInfos = [];
+ if (permutation != null) {
+ permutedX = transpose({ inputs: { x: x }, backend: backend, attrs: { perm: permutation } });
+ intermediateTensorInfos.push(permutedX);
+ reductionAxes = tfjsCore.backend_util.getInnerMostAxes(reductionAxes.length, xRank);
+ }
+ var xVals = backend.data.get(permutedX.dataId).values;
+ var _a = prodImpl(permutedX.shape, permutedX.dtype, xVals, reductionAxes), outVals = _a.outVals, outShape = _a.outShape, outDtype = _a.outDtype;
+ var resultShape = outShape;
+ if (keepDims) {
+ resultShape = tfjsCore.backend_util.expandShapeToKeepDim(outShape, axes);
+ }
+ intermediateTensorInfos.forEach(function (t) { return backend.disposeIntermediateTensorInfo(t); });
+ return backend.makeTensorInfo(resultShape, outDtype, outVals);
+ }
+ var prodConfig = {
+ kernelName: tfjsCore.Prod,
+ backendName: 'cpu',
+ kernelFunc: prod
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ function rangeImpl(start, stop, step, dtype) {
+ var sameStartStop = start === stop;
+ var increasingRangeNegativeStep = start < stop && step < 0;
+ var decreasingRangePositiveStep = stop < start && step > 1;
+ if (sameStartStop || increasingRangeNegativeStep ||
+ decreasingRangePositiveStep) {
+ return tfjsCore.util.makeZerosTypedArray(0, dtype);
+ }
+ var numElements = Math.abs(Math.ceil((stop - start) / step));
+ var values = tfjsCore.util.makeZerosTypedArray(numElements, dtype);
+ if (stop < start && step === 1) {
+ // Auto adjust the step's sign if it hasn't been set
+ // (or was set to 1)
+ step = -1;
+ }
+ values[0] = start;
+ for (var i = 1; i < values.length; i++) {
+ values[i] = values[i - 1] + step;
+ }
+ return values;
+ }
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ var rsqrtImpl = createSimpleUnaryImpl(function (xi) { return 1 / Math.sqrt(xi); });
+ var rsqrt = unaryKernelFuncFromImpl(tfjsCore.Rsqrt, rsqrtImpl);
+ var rsqrtConfig = {
+ kernelName: tfjsCore.Rsqrt,
+ backendName: 'cpu',
+ kernelFunc: rsqrt,
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ var sigmoidImpl = createSimpleUnaryImpl(function (xi) { return 1 / (1 + Math.exp(-xi)); });
+ var sigmoid = unaryKernelFunc(tfjsCore.Sigmoid, function (xi) { return 1 / (1 + Math.exp(-xi)); });
+ var sigmoidConfig = {
+ kernelName: tfjsCore.Sigmoid,
+ backendName: 'cpu',
+ kernelFunc: sigmoid,
+ };
+
+ function sliceImpl(vals, begin, size, shape, dtype) {
+ var isContinous = tfjsCore.slice_util.isSliceContinous(shape, begin, size);
+ var length = tfjsCore.util.sizeFromShape(size);
+ var xStrides = tfjsCore.util.computeStrides(shape);
+ if (isContinous) {
+ var flatOffset = tfjsCore.slice_util.computeFlatOffset(begin, xStrides);
+ if (dtype === 'string') {
+ return vals.slice(flatOffset, flatOffset + length);
+ }
+ return vals.subarray(flatOffset, flatOffset + length);
+ }
+ var decodedData = dtype === 'string' ?
+ tfjsCore.backend_util.fromUint8ToStringArray(vals) :
+ vals;
+ var inBuf = tfjsCore.buffer(shape, dtype, decodedData);
+ var outBuf = tfjsCore.buffer(size, dtype);
+ for (var i = 0; i < outBuf.size; ++i) {
+ var outLoc = outBuf.indexToLoc(i);
+ var inLoc = outLoc.map(function (idx, j) { return idx + begin[j]; });
+ outBuf.set.apply(outBuf, __spread([inBuf.get.apply(inBuf, __spread(inLoc))], outLoc));
+ }
+ if (dtype === 'string') {
+ return tfjsCore.backend_util.fromStringArrayToUint8(outBuf.values);
+ }
+ return outBuf.values;
+ }
+ function slice(args) {
+ var inputs = args.inputs, backend = args.backend, attrs = args.attrs;
+ var x = inputs.x;
+ var begin = attrs.begin, size = attrs.size;
+ assertNotComplex(x, 'slice');
+ var _a = __read(tfjsCore.slice_util.parseSliceParams(x, begin, size), 2), $begin = _a[0], $size = _a[1];
+ tfjsCore.slice_util.assertParamsValid(x, $begin, $size);
+ var vals = backend.data.get(x.dataId).values;
+ var outVals = sliceImpl(vals, $begin, $size, x.shape, x.dtype);
+ return backend.makeTensorInfo($size, x.dtype, outVals);
+ }
+ var sliceConfig = {
+ kernelName: tfjsCore.Slice,
+ backendName: 'cpu',
+ kernelFunc: slice
+ };
+
+ /**
+ * @license
+ * Copyright 2021 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ function sparseFillEmptyRowsImpl(indices, indicesShape, indicesDType, values, valuesDType, denseShape, defaultValue) {
+ var indicesCount = indicesShape[0];
+ var denseRows = denseShape[0];
+ var emptyRowIndicator = new Array(denseRows);
+ var reverseIndexMap = new Array(indicesCount);
+ var rank = indicesShape[1];
+ if (denseRows === 0) {
+ if (indicesCount !== 0) {
+ throw new Error(tfjsCore.backend_util.getSparseFillEmptyRowsIndicesDenseShapeMismatch(indicesCount));
+ }
+ var outputIndices = tfjsCore.util.getArrayFromDType(indicesDType, 0);
+ var outputValues = tfjsCore.util.getArrayFromDType(valuesDType, 0);
+ return [
+ outputIndices, [0, rank], outputValues, emptyRowIndicator, reverseIndexMap
+ ];
+ }
+ var rowsAreOrdered = true;
+ var lastIndicesRow = 0;
+ var csrOffset = new Array(denseRows).fill(0);
+ for (var i = 0; i < indicesCount; ++i) {
+ // indices is a 2d tensor with shape of [N, rank]
+ var row = indices[i * rank];
+ if (row < 0) {
+ throw new Error(tfjsCore.backend_util.getSparseFillEmptyRowsNegativeIndexErrorMessage(i, row));
+ }
+ if (row >= denseRows) {
+ throw new Error(tfjsCore.backend_util.getSparseFillEmptyRowsOutOfRangeIndexErrorMessage(i, row, denseRows));
+ }
+ ++csrOffset[row];
+ rowsAreOrdered = rowsAreOrdered && (row >= lastIndicesRow);
+ lastIndicesRow = row;
+ }
+ var allRowsFull = true;
+ for (var row = 0; row < denseRows; ++row) {
+ // csrOffset here describes the number of elements in this dense row
+ var rowEmpty = (csrOffset[row] === 0);
+ emptyRowIndicator[row] = rowEmpty;
+ allRowsFull = allRowsFull && !rowEmpty;
+ // In filled version, each row has at least one element.
+ csrOffset[row] = Math.max(csrOffset[row], 1);
+ // Update csrOffset to represent the number of elements up to and
+ // including denseRows + 1:
+ // csrOffset[0] == #{elements of row 0}
+ // csrOffset[1] == #{elements of row 1} + #{elements of row 0}
+ // ..
+ // csrOffset[i] == starting index for elements in row i + 1.
+ if (row > 0) {
+ csrOffset[row] += csrOffset[row - 1];
+ }
+ }
+ if (allRowsFull && rowsAreOrdered) {
+ var outputIndices = indices;
+ var outputValues = values;
+ for (var i = 0; i < indicesCount; ++i) {
+ reverseIndexMap[i] = i;
+ }
+ return [
+ outputIndices, [indicesCount, rank], outputValues, emptyRowIndicator,
+ reverseIndexMap
+ ];
+ }
+ else {
+ var fullIndicesCount = csrOffset[denseRows - 1];
+ var outputIndices = tfjsCore.util.getArrayFromDType(indicesDType, fullIndicesCount * rank);
+ var outputValues = tfjsCore.util.getArrayFromDType(valuesDType, fullIndicesCount);
+ var filledCount = new Array(denseRows).fill(0);
+ // Fill in values for rows that are not missing
+ for (var i = 0; i < indicesCount; ++i) {
+ // indices is a 2d tensor with shape of [N, rank]
+ var row = indices[i * rank];
+ var offset = filledCount[row];
+ var outputI = ((row === 0) ? 0 : csrOffset[row - 1]) + offset;
+ filledCount[row]++; // Increment the filled count for this row.
+ for (var j = 0; j < rank; ++j) {
+ // indices and outputIndices are 2d tensors with shape of [N, rank]
+ outputIndices[outputI * rank + j] = indices[i * rank + j];
+ }
+ outputValues[outputI] = values[i];
+ // We'll need this reverse index map to backprop correctly.
+ reverseIndexMap[i] = outputI;
+ }
+ // Fill in values for rows that are missing
+ for (var row = 0; row < denseRows; ++row) {
+ var rowCount = filledCount[row];
+ if (rowCount === 0) { // We haven't filled this row
+ var startingIndex = (row === 0) ? 0 : csrOffset[row - 1];
+ // Remaining index values were set to zero already.
+ // Just need to set the row index in the right location.
+ // outputIndices is a 2d tensor with shape of [N, rank]
+ outputIndices[startingIndex * rank + 0] = row;
+ for (var col = 1; col < rank; ++col) {
+ outputIndices[startingIndex * rank + col] = 0;
+ }
+ outputValues[startingIndex] = defaultValue;
+ }
+ }
+ return [
+ outputIndices, [fullIndicesCount, rank], outputValues, emptyRowIndicator,
+ reverseIndexMap
+ ];
+ }
+ }
+
+ /**
+ * @license
+ * Copyright 2021 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ function sparseReshapeImpl(inputIndices, inputIndicesShape, inputDType, inputShape, targetShape) {
+ var denseSize = tfjsCore.util.sizeFromShape(inputShape);
+ var nnz = inputIndicesShape[0];
+ var outputRank = targetShape.length;
+ // Compute the output shape. Determine product of specified dimensions, and
+ // find the index of the unspecified one.
+ var outputShape = [];
+ var product = 1;
+ var unknownIndex = -1;
+ for (var d = 0; d < outputRank; ++d) {
+ var size = targetShape[d];
+ if (size === -1) {
+ if (unknownIndex !== -1) {
+ throw new Error(tfjsCore.backend_util
+ .getSparseReshapeMultipleNegativeOneOutputDimErrorMessage(unknownIndex, d));
+ }
+ unknownIndex = d;
+ outputShape.push(1);
+ }
+ else {
+ if (size < 0) {
+ throw new Error(tfjsCore.backend_util.getSparseReshapeNegativeOutputDimErrorMessage(d, size));
+ }
+ product *= size;
+ outputShape.push(size);
+ }
+ }
+ if (unknownIndex !== -1) {
+ if (product <= 0) {
+ throw new Error(tfjsCore.backend_util.getSparseReshapeEmptyTensorZeroOutputDimErrorMessage());
+ }
+ var missing = Math.trunc(denseSize / product);
+ if (product * missing !== denseSize) {
+ throw new Error(tfjsCore.backend_util.getSparseReshapeInputOutputMultipleErrorMessage(inputShape, outputShape));
+ }
+ outputShape[unknownIndex] = missing;
+ }
+ var outputSize = tfjsCore.util.sizeFromShape(outputShape);
+ if (outputSize !== denseSize) {
+ throw new Error(tfjsCore.backend_util.getSparseReshapeInputOutputMismatchErrorMessage(inputShape, outputShape));
+ }
+ var inputRank = inputShape.length;
+ var inputStrides = [];
+ if (inputRank > 0) {
+ inputStrides[inputRank - 1] = 1;
+ for (var d = inputRank - 2; d >= 0; --d) {
+ inputStrides[d] = inputStrides[d + 1] * inputShape[d + 1];
+ }
+ }
+ var outputStrides = [];
+ if (outputRank > 0) {
+ outputStrides[outputRank - 1] = 1;
+ for (var d = outputRank - 2; d >= 0; --d) {
+ outputStrides[d] = outputStrides[d + 1] * outputShape[d + 1];
+ }
+ }
+ var newIndices = tfjsCore.util.getArrayFromDType(inputDType, nnz * outputRank);
+ for (var i = 0; i < nnz; ++i) {
+ var id = 0;
+ for (var j = 0; j < inputRank; ++j) {
+ // inputIndices is a 2d tensor with shape of [nnz, inputRank]
+ id += inputIndices[i * inputRank + j] * inputStrides[j];
+ }
+ for (var j = 0; j < outputRank; ++j) {
+ // newIndices is a 2d tensor with shape of [nnz, outputRank]
+ newIndices[i * outputRank + j] = Math.trunc(id / outputStrides[j]);
+ id %= outputStrides[j];
+ }
+ }
+ return [newIndices, [nnz, outputRank], outputShape];
+ }
+
+ /**
+ * @license
+ * Copyright 2021 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ function sparseSegmentReductionImpl(input, inputShape, inputDType, indices, segmentIds, isMean, defaultValue) {
+ if (isMean === void 0) { isMean = false; }
+ if (defaultValue === void 0) { defaultValue = 0; }
+ var numIndices = indices.length;
+ // Flatten the array to two dimensions
+ var inputFlat = [inputShape[0], input.length / inputShape[0]];
+ var numCol = inputFlat[1];
+ // Note that the current implementation assumes that segmentIds values are
+ // sorted.
+ var lastSegmentIdPlusOne = numIndices > 0 ? segmentIds[numIndices - 1] + 1 : 0;
+ var outputRows = lastSegmentIdPlusOne;
+ if (outputRows < 0) {
+ throw new Error(tfjsCore.backend_util.getSparseSegmentReductionNegativeSegmentIdsErrorMessage());
+ }
+ var outputShape = inputShape.slice();
+ outputShape[0] = outputRows;
+ var outputLength = outputShape.reduce(function (product, value) { return product * value; }, 1);
+ // Output array is initialized with the value 0 by default.
+ var output = tfjsCore.util.getArrayFromDType(inputDType, outputLength);
+ // Note that we do not initialize the output buffer with a default value, so
+ // we need to explicitly set missing indices to the default value.
+ if (numIndices === 0) {
+ if (outputRows > 0) {
+ output.fill(defaultValue);
+ }
+ return [output, outputShape];
+ }
+ if (outputRows <= 0) {
+ throw new Error(tfjsCore.backend_util.getSparseSegmentReductionNegativeSegmentIdsErrorMessage());
+ }
+ var start = 0, end = 1;
+ // Index from which the output is not initialized.
+ var uninitializedIndex = 0;
+ var outIndex = segmentIds[start];
+ while (true) {
+ // We initialize nextIndex to 0 to avoid may be uninitialized warning
+ var nextIndex = 0;
+ if (end < numIndices) {
+ nextIndex = segmentIds[end];
+ if (outIndex === nextIndex) {
+ ++end;
+ continue;
+ }
+ // We have a new segment here. Verify that the segment ids are growing.
+ if (outIndex >= nextIndex) {
+ throw new Error(tfjsCore.backend_util
+ .getSparseSegmentReductionNonIncreasingSegmentIdsErrorMessage());
+ }
+ }
+ if (outIndex < 0 || outIndex >= outputRows) {
+ throw new Error(tfjsCore.backend_util.getSparseSegmentReductionSegmentIdOutOfRangeErrorMessage(outIndex, outputRows));
+ }
+ // If there is a gap between two indices, we need to set that gap to the
+ // default value.
+ if (outIndex > uninitializedIndex) {
+ output.fill(defaultValue, uninitializedIndex * numCol, outIndex * numCol);
+ }
+ for (var i = start; i < end; ++i) {
+ var index = indices[i];
+ if (index < 0 || index >= inputFlat[0]) {
+ throw new Error(tfjsCore.backend_util.getSparseSegmentReductionIndicesOutOfRangeErrorMessage(i, indices[i], inputFlat[0]));
+ }
+ for (var j = 0; j < numCol; j++) {
+ output[outIndex * numCol + j] += input[index * numCol + j];
+ }
+ }
+ if (isMean) {
+ for (var j = 0; j < numCol; j++) {
+ output[outIndex * numCol + j] /= end - start;
+ }
+ }
+ start = end;
+ ++end;
+ uninitializedIndex = outIndex + 1;
+ outIndex = nextIndex;
+ if (end > numIndices) {
+ break;
+ }
+ }
+ // Fill the gap at the end with the default value.
+ if (uninitializedIndex < outputRows) {
+ output.fill(defaultValue, uninitializedIndex * numCol, outputRows * numCol);
+ }
+ return [output, outputShape];
+ }
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ var sqrtImpl = createSimpleUnaryImpl(function (xi) { return Math.sqrt(xi); });
+ var sqrt = unaryKernelFunc(tfjsCore.Sqrt, function (xi) { return Math.sqrt(xi); });
+ var sqrtConfig = {
+ kernelName: tfjsCore.Sqrt,
+ backendName: 'cpu',
+ kernelFunc: sqrt,
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ var squaredDifferenceImpl = createSimpleBinaryKernelImpl((function (a, b) {
+ var diff = a - b;
+ return diff * diff;
+ }));
+ var squaredDifference = binaryKernelFunc(tfjsCore.SquaredDifference, squaredDifferenceImpl);
+ var squaredDifferenceConfig = {
+ kernelName: tfjsCore.SquaredDifference,
+ backendName: 'cpu',
+ kernelFunc: squaredDifference
+ };
+
+ function stridedSliceImpl(outShape, xBuf, strides, begin) {
+ var outBuf = tfjsCore.buffer(outShape, xBuf.dtype);
+ for (var i = 0; i < outBuf.size; i++) {
+ var loc = outBuf.indexToLoc(i);
+ var newLoc = new Array(loc.length);
+ for (var j = 0; j < newLoc.length; j++) {
+ newLoc[j] = loc[j] * strides[j] + begin[j];
+ }
+ outBuf.set.apply(outBuf, __spread([xBuf.get.apply(xBuf, __spread(newLoc))], loc));
+ }
+ return outBuf;
+ }
+
+ /**
+ * @license
+ * Copyright 2021 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ /**
+ * The StringNGramsOp class creates ngrams from ragged string data.
+ * The constructor contains all attributes related to the operation such as
+ * padding widths and strings, and the compute function can be used to
+ * compute the ngrams for different ragged tensor inputs.
+ */
+ var StringNGramsOp = /** @class */ (function () {
+ function StringNGramsOp(separator, nGramWidths, leftPad, rightPad, padWidth, preserveShortSequences) {
+ this.separator = tfjsCore.util.encodeString(separator);
+ this.nGramWidths = nGramWidths;
+ this.leftPad = tfjsCore.util.encodeString(leftPad);
+ this.rightPad = tfjsCore.util.encodeString(rightPad);
+ this.padWidth = padWidth;
+ this.preserveShort = preserveShortSequences;
+ }
+ StringNGramsOp.prototype.getPadWidth = function (nGramWidth) {
+ // Ngrams can be padded with either a fixed pad width or a dynamic pad
+ // width depending on the 'padWidth' arg, but in no case should the padding
+ // ever be wider than 'nGramWidth' - 1.
+ return Math.min(this.padWidth < 0 ? nGramWidth - 1 : this.padWidth, nGramWidth - 1);
+ };
+ StringNGramsOp.prototype.getNumNGrams = function (length, nGramWidth) {
+ var padWidth = this.getPadWidth(nGramWidth);
+ return Math.max(0, ((length + 2 * padWidth) - nGramWidth) + 1);
+ };
+ StringNGramsOp.prototype.createNGrams = function (data, splitIndex, output, outputStartIndex, numNGrams, nGramWidth) {
+ var _loop_1 = function (nGramIndex) {
+ var padWidth = this_1.getPadWidth(nGramWidth);
+ var leftPadding = Math.max(0, padWidth - nGramIndex);
+ var rightPadding = Math.max(0, padWidth - (numNGrams - (nGramIndex + 1)));
+ var numTokens = nGramWidth - (leftPadding + rightPadding);
+ var dataStartIndex = splitIndex + (leftPadding > 0 ? 0 : nGramIndex - padWidth);
+ // Calculate the total expected size of the nGram so we can reserve the
+ // correct amount of space in the string.
+ var nGramSize = 0;
+ // Size of the left padding.
+ nGramSize += leftPadding * this_1.leftPad.length;
+ // Size of the tokens.
+ for (var n = 0; n < numTokens; ++n) {
+ nGramSize += data[dataStartIndex + n].length;
+ }
+ // Size of the right padding.
+ nGramSize += rightPadding * this_1.rightPad.length;
+ // Size of the separators.
+ var numSeparators = leftPadding + rightPadding + numTokens - 1;
+ nGramSize += numSeparators * this_1.separator.length;
+ // Build the nGram.
+ output[outputStartIndex + nGramIndex] = new Uint8Array(nGramSize);
+ var nGram = output[outputStartIndex + nGramIndex];
+ var nextNGramIndex = 0;
+ var appendToNGram = function (str) { return str.forEach(function (value) { return nGram[nextNGramIndex++] = value; }); };
+ for (var n = 0; n < leftPadding; ++n) {
+ appendToNGram(this_1.leftPad);
+ appendToNGram(this_1.separator);
+ }
+ // Only output first numTokens - 1 pairs of data and separator
+ for (var n = 0; n < numTokens - 1; ++n) {
+ appendToNGram(data[dataStartIndex + n]);
+ appendToNGram(this_1.separator);
+ }
+ // Handle case when there are no tokens or no right padding as these
+ // can result in consecutive separators.
+ if (numTokens > 0) {
+ // If we have tokens, then output last and then pair each separator
+ // with the right padding that follows, to ensure nGram ends either with
+ // the token or with the right pad.
+ appendToNGram(data[dataStartIndex + numTokens - 1]);
+ for (var n = 0; n < rightPadding; ++n) {
+ appendToNGram(this_1.separator);
+ appendToNGram(this_1.rightPad);
+ }
+ }
+ else {
+ // If we don't have tokens, then the last item inserted into the nGram
+ // has been the separator from the left padding loop above. Hence,
+ // output right pad and separator and make sure to finish with a
+ // padding, not a separator.
+ for (var n = 0; n < rightPadding - 1; ++n) {
+ appendToNGram(this_1.rightPad);
+ appendToNGram(this_1.separator);
+ }
+ appendToNGram(this_1.rightPad);
+ }
+ };
+ var this_1 = this;
+ for (var nGramIndex = 0; nGramIndex < numNGrams; ++nGramIndex) {
+ _loop_1(nGramIndex);
+ }
+ };
+ // Data and splits together form the definition of the ragged tensor,
+ // where data is 1 dimensional and contains the values of the tensor
+ // and splits denotes the indices at which each row starts.
+ StringNGramsOp.prototype.compute = function (data, splits) {
+ var _this = this;
+ // Validate that the splits are valid indices into data, only if there are
+ // splits specified.
+ var inputDataSize = data.length;
+ var splitsSize = splits.length;
+ if (splitsSize > 0) {
+ var prevSplit = splits[0];
+ if (prevSplit !== 0) {
+ throw new Error("First split value must be 0, got " + prevSplit);
+ }
+ for (var i = 1; i < splitsSize; ++i) {
+ var validSplits = splits[i] >= prevSplit;
+ validSplits = validSplits && (splits[i] <= inputDataSize);
+ if (!validSplits) {
+ throw new Error("Invalid split value " + splits[i] + ", must be in [" + prevSplit + ", " + inputDataSize + "]");
+ }
+ prevSplit = splits[i];
+ }
+ if (prevSplit !== inputDataSize) {
+ throw new Error("Last split value must be data size. Expected " + inputDataSize + ", got " + prevSplit);
+ }
+ }
+ var numBatchItems = splitsSize - 1;
+ var nGramsSplits = tfjsCore.util.getArrayFromDType('int32', splitsSize);
+ // If there is no data or size, return an empty ragged tensor.
+ if (inputDataSize === 0 || splitsSize === 0) {
+ var empty = new Array(inputDataSize);
+ for (var i = 0; i <= numBatchItems; ++i) {
+ nGramsSplits[i] = 0;
+ }
+ return [empty, nGramsSplits];
+ }
+ nGramsSplits[0] = 0;
+ var _loop_2 = function (i) {
+ var length = splits[i] - splits[i - 1];
+ var numNGrams = 0;
+ this_2.nGramWidths.forEach(function (nGramWidth) {
+ numNGrams += _this.getNumNGrams(length, nGramWidth);
+ });
+ if (this_2.preserveShort && length > 0 && numNGrams === 0) {
+ numNGrams = 1;
+ }
+ nGramsSplits[i] = nGramsSplits[i - 1] + numNGrams;
+ };
+ var this_2 = this;
+ for (var i = 1; i <= numBatchItems; ++i) {
+ _loop_2(i);
+ }
+ var nGrams = new Array(nGramsSplits[numBatchItems]);
+ var _loop_3 = function (i) {
+ var splitIndex = splits[i];
+ var outputStartIdx = nGramsSplits[i];
+ this_3.nGramWidths.forEach(function (nGramWidth) {
+ var length = splits[i + 1] - splits[i];
+ var numNGrams = _this.getNumNGrams(length, nGramWidth);
+ _this.createNGrams(data, splitIndex, nGrams, outputStartIdx, numNGrams, nGramWidth);
+ outputStartIdx += numNGrams;
+ });
+ // If we're preserving short sequences, check to see if no sequence was
+ // generated by comparing the current output start idx to the original
+ // one (nGramSplitsdata). If no ngrams were generated, then they will
+ // be equal (since we increment outputStartIdx by numNGrams every
+ // time we create a set of ngrams.)
+ if (this_3.preserveShort && outputStartIdx === nGramsSplits[i]) {
+ var dataLength = splits[i + 1] - splits[i];
+ // One legitimate reason to not have any ngrams when this.preserveShort
+ // is true is if the sequence itself is empty. In that case, move on.
+ if (dataLength === 0) {
+ return "continue";
+ }
+ // We don't have to worry about dynamic padding sizes here: if padding
+ // was dynamic, every sequence would have had sufficient padding to
+ // generate at least one nGram.
+ var nGramWidth = dataLength + 2 * this_3.padWidth;
+ var numNGrams = 1;
+ this_3.createNGrams(data, splitIndex, nGrams, outputStartIdx, numNGrams, nGramWidth);
+ }
+ };
+ var this_3 = this;
+ for (var i = 0; i < numBatchItems; ++i) {
+ _loop_3(i);
+ }
+ return [nGrams, nGramsSplits];
+ };
+ return StringNGramsOp;
+ }());
+ function stringNGramsImpl(data, dataSplits, separator, nGramWidths, leftPad, rightPad, padWidth, preserveShortSequences) {
+ return new StringNGramsOp(separator, nGramWidths, leftPad, rightPad, padWidth, preserveShortSequences)
+ .compute(data, dataSplits);
+ }
+
+ /**
+ * @license
+ * Copyright 2021 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ function split(str, delimiters, skipEmpty, result) {
+ if (!str.length) {
+ return;
+ }
+ // When the delimiter is empty, the input is split into individual characters.
+ if (delimiters.length === 0) {
+ for (var i = 0; i < str.length; ++i) {
+ result.push(str.subarray(i, i + 1));
+ }
+ return;
+ }
+ // When there is one delimiter, the input is split only at that delimiter.
+ if (delimiters.length === 1) {
+ var delimiter = delimiters[0];
+ var f = str.indexOf(delimiter);
+ while (f !== -1) {
+ var token = str.subarray(0, f);
+ if (!skipEmpty || token.length !== 0) {
+ result.push(token);
+ }
+ str = str.subarray(f + 1);
+ f = str.indexOf(delimiter);
+ }
+ if (!skipEmpty || str.length !== 0) {
+ result.push(str);
+ }
+ return;
+ }
+ // When there are multiple delimiters, the input is split at every instance
+ // one of the delimiters appears.
+ var tokenStart = 0;
+ for (var i = 0; i < str.length + 1; i++) {
+ if ((i === str.length) || (delimiters.indexOf(str[i]) !== -1)) {
+ var token = str.subarray(tokenStart, i);
+ if (!skipEmpty || token.length !== 0) {
+ result.push(token);
+ }
+ tokenStart = i + 1;
+ }
+ }
+ }
+ function stringSplitImpl(input, delimiter, skipEmpty) {
+ var batchSize = input.length;
+ // Empty delimiter means split the input character by character.
+ var tokens = [];
+ var outputSize = 0;
+ var maxNumEntries = 0;
+ var numIndices = new Array(batchSize);
+ for (var i = 0; i < batchSize; ++i) {
+ var prevTokensLength = tokens.length;
+ split(input[i], delimiter, skipEmpty, tokens);
+ var nEntries = tokens.length - prevTokensLength;
+ numIndices[i] = nEntries;
+ outputSize += nEntries;
+ maxNumEntries = Math.max(maxNumEntries, nEntries);
+ }
+ var indices = tfjsCore.util.getArrayFromDType('int32', outputSize * 2);
+ var values = new Array(outputSize);
+ var shape = [batchSize, maxNumEntries];
+ var c = 0;
+ for (var i = 0; i < batchSize; ++i) {
+ for (var j = 0; j < numIndices[i]; ++j) {
+ // indices is a 2d tensor with shape of [outputSize, 2]
+ indices[c * 2] = i;
+ indices[c * 2 + 1] = j;
+ values[c] = tokens[c];
+ ++c;
+ }
+ }
+ return [indices, values, shape];
+ }
+
+ /**
+ * @license
+ * Copyright 2021 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ function stringToHashBucketFastImpl(input, numBuckets) {
+ var output = tfjsCore.util.getArrayFromDType('int32', input.length);
+ for (var i = 0; i < input.length; ++i) {
+ output[i] =
+ tfjsCore.util.fingerPrint64(input[i]).modulo(numBuckets).getLowBitsUnsigned();
+ }
+ return output;
+ }
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ var subImpl = createSimpleBinaryKernelImpl((function (aValue, bValue) { return aValue - bValue; }));
+ var subComplexImpl = createComplexBinaryKernelImpl((function (aReal, aImag, bReal, bImag) {
+ return { real: aReal - bReal, imag: aImag - bImag };
+ }));
+ var sub = binaryKernelFunc(tfjsCore.Sub, subImpl, subComplexImpl);
+ var subConfig = {
+ kernelName: tfjsCore.Sub,
+ backendName: 'cpu',
+ kernelFunc: sub
+ };
+
+ /**
+ * @license
+ * Copyright 2019 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ /**
+ * An implementation of the tile kernel shared between webgl and cpu for string
+ * tensors only.
+ */
+ function tileImpl(xBuf, reps) {
+ var newShape = new Array(xBuf.rank);
+ for (var i = 0; i < newShape.length; i++) {
+ newShape[i] = xBuf.shape[i] * reps[i];
+ }
+ var result = tfjsCore.buffer(newShape, xBuf.dtype);
+ for (var i = 0; i < result.values.length; ++i) {
+ var newLoc = result.indexToLoc(i);
+ var originalLoc = new Array(xBuf.rank);
+ for (var j = 0; j < originalLoc.length; j++) {
+ originalLoc[j] = newLoc[j] % xBuf.shape[j];
+ }
+ var originalIndex = xBuf.locToIndex(originalLoc);
+ result.values[i] = xBuf.values[originalIndex];
+ }
+ return result;
+ }
+
+ var comparePair = function (a, b) {
+ var valueDiff = b.value - a.value;
+ return valueDiff === 0 ? a.index - b.index : valueDiff;
+ };
+ /**
+ * Partitions array where all elements smaller than the (k+1) smallest element
+ * are found to the left of it, and all larger to the right of it.
+ * Based on the Floyd-Rivest Algorithm, ref:
+ * https://en.wikipedia.org/wiki/Floyd%E2%80%93Rivest_algorithm
+ * @param array: Array to partition
+ * @param left: Left index for the interval
+ * @param right: Right index for the interval
+ * @param k: Desired index value, where array[k] is the (k+1)th smallest element
+ * when left = 0
+ */
+ function select$1(array, k, left, right) {
+ if (left === void 0) { left = 0; }
+ if (right === void 0) { right = array.length - 1; }
+ while (right > left) {
+ // Use select recursively to sample a smaller set of size s
+ // the arbitrary constants 600 and 0.5 are used in the original
+ // version to minimize execution time.
+ if (right - left > 600) {
+ var n = right - left + 1;
+ var i_1 = k - left + 1;
+ var z = Math.log(n);
+ var s = 0.5 * Math.exp(2 * z / 3);
+ var sd = 0.5 * Math.sqrt(z * s * (n - s) / n) * Math.sign(i_1 - n / 2);
+ var newLeft = Math.max(left, Math.floor(k - i_1 * s / n + sd));
+ var newRight = Math.min(right, Math.floor(k + (n - i_1) * s / n + sd));
+ select$1(array, k, newLeft, newRight);
+ }
+ // partition the elements between left and right around t
+ var t = array[k];
+ var i = left;
+ var j = right;
+ tfjsCore.util.swap(array, left, k);
+ if (comparePair(array[right], t) > 0) {
+ tfjsCore.util.swap(array, left, right);
+ }
+ while (i < j) {
+ tfjsCore.util.swap(array, i, j);
+ i++;
+ j--;
+ while (comparePair(array[i], t) < 0) {
+ i = i + 1;
+ }
+ while (comparePair(array[j], t) > 0) {
+ j = j - 1;
+ }
+ }
+ if (comparePair(array[left], t) === 0) {
+ tfjsCore.util.swap(array, left, j);
+ }
+ else {
+ j = j + 1;
+ tfjsCore.util.swap(array, j, right);
+ }
+ // Adjust left and right towards the boundaries of the subset
+ // containing the (k - left + 1)th smallest element.
+ if (j <= k) {
+ left = j + 1;
+ }
+ if (k <= j) {
+ right = j - 1;
+ }
+ }
+ }
+ function topKImpl(x, xShape, xDtype, k, sorted) {
+ // Reshape into a 2d tensor [batch, lastDim] and compute topk along lastDim.
+ var lastDim = xShape[xShape.length - 1];
+ var _a = __read([x.length / lastDim, lastDim], 2), batch = _a[0], size = _a[1];
+ var allTopKVals = tfjsCore.util.getTypedArrayFromDType(xDtype, batch * k);
+ var allTopKIndices = tfjsCore.util.getTypedArrayFromDType('int32', batch * k);
+ var _loop_1 = function (b) {
+ var offset = b * size;
+ var vals = x.subarray(offset, offset + size);
+ var valAndInd = new Array(vals.length);
+ vals.forEach(function (value, index) { return valAndInd[index] = { value: value, index: index }; });
+ if (k < valAndInd.length) {
+ select$1(valAndInd, k);
+ valAndInd = valAndInd.slice(0, k);
+ }
+ if (sorted) {
+ valAndInd.sort(comparePair);
+ }
+ var outOffset = b * k;
+ var topKVals = allTopKVals.subarray(outOffset, outOffset + k);
+ var topKIndices = allTopKIndices.subarray(outOffset, outOffset + k);
+ for (var i = 0; i < k; i++) {
+ topKVals[i] = valAndInd[i].value;
+ topKIndices[i] = valAndInd[i].index;
+ }
+ };
+ for (var b = 0; b < batch; b++) {
+ _loop_1(b);
+ }
+ // Reshape back to the original input shape, except that the last
+ // dimension is k.
+ var outputShape = xShape.slice();
+ outputShape[outputShape.length - 1] = k;
+ return [
+ tfjsCore.buffer(outputShape, xDtype, allTopKVals),
+ tfjsCore.buffer(outputShape, 'int32', allTopKIndices)
+ ];
+ }
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ function uniqueImpl(values, axis, shape, dtype) {
+ // Normalize and validate axis.
+ var $axis = tfjsCore.util.parseAxisParam(axis, shape)[0];
+ // Calculate the new shape that is suitable for extracting data along the
+ // given axis.
+ //
+ // The rank is 3.
+ // The size of the 1st dimension is the size of all the axes < the given axis.
+ // The size of the 2nd dimension is the same as the size of the given axis.
+ // The size of the 3rd dimension is the size of all the axes > the given axis.
+ //
+ // For example, for a 4D tensor with shape=[2, 3, 5, 4] and axis=2, the
+ // newShape would be: [2*3, 5, 4].
+ //
+ // Note that this is not the final output shape. This will be the shape for an
+ // intermediate TensorBuffer (see inputBuffer below) to allow us to extract
+ // values along the given axis. To demonstrate how it works, consider the
+ // following example:
+ //
+ // Input: a 3D tensor, with shape [1, 2, 3]
+ // [
+ // [
+ // [1,2,3],
+ // [4,5,6]
+ // ]
+ // ]
+ // Axis: 2 (the last axis).
+ // Along axis 2, we expect to extract 3 tensors: [1,4], [2,5], [3,6].
+ //
+ // For this example, newShape would be: [2, 3, 1], where 2 is calculated from
+ // 1*2. The re-shaped data would look like:
+ //
+ // [
+ // [
+ // [1], [2], [3]
+ // ],
+ // [
+ // [4], [5], [6]
+ // ]
+ // ]
+ //
+ // Then, we can construct a 3-level nested loop by the following dimension
+ // order to extract the values along the axis (dimension1):
+ // i: dimension1 // 0,1,2 (newShape[1])
+ // m: dimension0 // 0,1 (newShape[0])
+ // n: dimension2 // 0 (newShape[2])
+ //
+ // m, i, n
+ // ---------
+ // Iteration 0: data at [0, 0, 0] => "1"
+ // Iteration 1: data at [1, 0, 0] => "4"
+ // We got [1,4].
+ // Iteration 2: data at [0, 1, 0] => "2"
+ // Iteration 3: data at [1, 1, 0] => "5"
+ // We got [2,5].
+ // Iteration 4: data at [0, 2, 0] => "3"
+ // Iteration 5: data at [1, 2, 0] => "6"
+ // We got [3,6].
+ var newShape = [1, shape[0], 1];
+ for (var i = 0; i < $axis; i++) {
+ newShape[0] *= shape[i];
+ }
+ newShape[1] = shape[$axis];
+ for (var i = $axis + 1; i < shape.length; i++) {
+ newShape[2] *= shape[i];
+ }
+ // A map from unique elements (their string representations) to their values
+ // in "indices" (below).
+ var uniqueElements = {};
+ // The indices of each unique element in the original tensor along the given
+ // axis. It is 1D and has the same size as the given axis.
+ var indices = new Int32Array(shape[$axis]);
+ // Create a buffer so we can easily extract value at a given location.
+ var inputBuffer = new tfjsCore.TensorBuffer(newShape, dtype, values);
+ // The indices along the given axis that have unique elements. This is a
+ // de-duped version of "indices" above.
+ var uniqueIndices = [];
+ var is1DTensor = newShape[0] === 1 && newShape[2] === 1;
+ for (var i = 0; i < shape[$axis]; i++) {
+ // Extract values along the axis.
+ var element = void 0;
+ if (is1DTensor) {
+ // Fast path for 1D tensor input.
+ element = values[i].toString();
+ }
+ else {
+ var axisValues = [];
+ for (var m = 0; m < newShape[0]; m++) {
+ for (var n = 0; n < newShape[2]; n++) {
+ axisValues.push(inputBuffer.get(m, i, n));
+ }
+ }
+ element = axisValues.join(',');
+ }
+ // Dedup and update various indices.
+ if (uniqueElements[element] !== undefined) {
+ indices[i] = uniqueElements[element];
+ }
+ else {
+ var uniqueIndex = Object.keys(uniqueElements).length;
+ uniqueElements[element] = uniqueIndex;
+ indices[i] = uniqueIndex;
+ uniqueIndices.push(i);
+ }
+ }
+ // Now we know where each of the unique elements are located along the axis
+ // (uniqueIndices). Extract them from input buffer and store them in the
+ // output buffer.
+ var outputTmpShape = newShape.slice();
+ outputTmpShape[1] = Object.keys(uniqueElements).length;
+ var outputBuffer = new tfjsCore.TensorBuffer(outputTmpShape, dtype);
+ uniqueIndices.forEach(function (uniqueElementIndex, i) {
+ for (var m = 0; m < newShape[0]; m++) {
+ for (var n = 0; n < newShape[2]; n++) {
+ outputBuffer.set(inputBuffer.get(m, uniqueElementIndex, n), m, i, n);
+ }
+ }
+ });
+ // The output shape can be calculated from the input shape with the size of
+ // the given axis replaced by the number of unique elements along that axis.
+ var outputShape = shape.slice();
+ outputShape[$axis] = outputTmpShape[1];
+ return {
+ outputValues: outputBuffer.values,
+ outputShape: outputShape,
+ indices: indices,
+ };
+ }
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+
+ var shared = {
+ __proto__: null,
+ simpleAbsImpl: simpleAbsImpl,
+ addImpl: addImpl,
+ bincountImpl: bincountImpl,
+ bincountReduceImpl: bincountReduceImpl,
+ ceilImpl: ceilImpl,
+ concatImpl: concatImpl,
+ equalImpl: equalImpl,
+ expImpl: expImpl,
+ expm1Impl: expm1Impl,
+ floorImpl: floorImpl,
+ gatherNdImpl: gatherNdImpl,
+ gatherV2Impl: gatherV2Impl,
+ greaterImpl: greaterImpl,
+ greaterEqualImpl: greaterEqualImpl,
+ lessImpl: lessImpl,
+ lessEqualImpl: lessEqualImpl,
+ linSpaceImpl: linSpaceImpl,
+ logImpl: logImpl,
+ maxImpl: maxImpl,
+ maximumImpl: maximumImpl,
+ minimumImpl: minimumImpl,
+ multiplyImpl: multiplyImpl,
+ negImpl: negImpl,
+ notEqualImpl: notEqualImpl,
+ prodImpl: prodImpl,
+ rangeImpl: rangeImpl,
+ rsqrtImpl: rsqrtImpl,
+ sigmoidImpl: sigmoidImpl,
+ sliceImpl: sliceImpl,
+ sparseFillEmptyRowsImpl: sparseFillEmptyRowsImpl,
+ sparseReshapeImpl: sparseReshapeImpl,
+ sparseSegmentReductionImpl: sparseSegmentReductionImpl,
+ sqrtImpl: sqrtImpl,
+ squaredDifferenceImpl: squaredDifferenceImpl,
+ stridedSliceImpl: stridedSliceImpl,
+ stringNGramsImpl: stringNGramsImpl,
+ stringSplitImpl: stringSplitImpl,
+ stringToHashBucketFastImpl: stringToHashBucketFastImpl,
+ subImpl: subImpl,
+ tileImpl: tileImpl,
+ topKImpl: topKImpl,
+ transposeImpl: transposeImpl,
+ uniqueImpl: uniqueImpl
+ };
+
+ /** @license See the LICENSE file. */
+ // This code is auto-generated, do not modify this file!
+ var version = '3.12.0';
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ // Side effects for default initialization of MathBackendCPU
+ tfjsCore.registerBackend('cpu', function () { return new MathBackendCPU(); }, 1 /* priority */);
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ var elu = unaryKernelFunc(tfjsCore.Elu, function (xi) { return xi >= 0 ? xi : (Math.exp(xi) - 1); });
+ var eluConfig = {
+ kernelName: tfjsCore.Elu,
+ backendName: 'cpu',
+ kernelFunc: elu,
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ function leakyRelu(args) {
+ var inputs = args.inputs, backend = args.backend, attrs = args.attrs;
+ var x = inputs.x;
+ var alpha = attrs.alpha;
+ assertNotComplex([x], 'leakyRelu');
+ var xSize = tfjsCore.util.sizeFromShape(x.shape);
+ var xVals = backend.data.get(x.dataId).values;
+ var outVals = tfjsCore.util.getTypedArrayFromDType('float32', xSize);
+ for (var i = 0; i < xVals.length; i++) {
+ outVals[i] = xVals[i] < 0 ? alpha * xVals[i] : xVals[i];
+ }
+ return backend.makeTensorInfo(x.shape, 'float32', outVals);
+ }
+ var leakyReluConfig = {
+ kernelName: tfjsCore.LeakyRelu,
+ backendName: 'cpu',
+ kernelFunc: leakyRelu
+ };
+
+ var preluImpl = createSimpleBinaryKernelImpl(function (xValue, aValue) { return xValue < 0 ? aValue * xValue : xValue; });
+ function prelu(args) {
+ var inputs = args.inputs, backend = args.backend;
+ var x = inputs.x, alpha = inputs.alpha;
+ assertNotComplex([x, alpha], 'prelu');
+ var aVals = backend.data.get(x.dataId).values;
+ var bVals = backend.data.get(alpha.dataId).values;
+ var _a = __read(preluImpl(x.shape, alpha.shape, aVals, bVals, 'float32'), 2), resultData = _a[0], resultShape = _a[1];
+ return backend.makeTensorInfo(resultShape, 'float32', resultData);
+ }
+ var preluConfig = {
+ kernelName: tfjsCore.Prelu,
+ backendName: 'cpu',
+ kernelFunc: prelu,
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ var relu = unaryKernelFunc(tfjsCore.Relu, function (xi) { return Math.max(0, xi); });
+ var reluConfig = {
+ kernelName: tfjsCore.Relu,
+ backendName: 'cpu',
+ kernelFunc: relu,
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ var relu6 = unaryKernelFunc(tfjsCore.Relu6, function (xi) { return Math.min(Math.max(0, xi), 6); });
+ var relu6Config = {
+ kernelName: tfjsCore.Relu6,
+ backendName: 'cpu',
+ kernelFunc: relu6,
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ function applyActivation(backend, x, activation, preluActivationWeights, leakyreluAlpha) {
+ if (activation === 'linear') {
+ return identity({ inputs: { x: x }, backend: backend });
+ }
+ else if (activation === 'relu') {
+ return relu({ inputs: { x: x }, backend: backend });
+ }
+ else if (activation === 'elu') {
+ return elu({ inputs: { x: x }, backend: backend });
+ }
+ else if (activation === 'relu6') {
+ return relu6({ inputs: { x: x }, backend: backend });
+ }
+ else if (activation === 'prelu') {
+ return prelu({ inputs: { x: x, alpha: preluActivationWeights }, backend: backend });
+ }
+ else if (activation === 'leakyrelu') {
+ return leakyRelu({ inputs: { x: x }, backend: backend, attrs: { alpha: leakyreluAlpha } });
+ }
+ else if (activation === 'sigmoid') {
+ return sigmoid({ inputs: { x: x }, backend: backend });
+ }
+ throw new Error("Activation " + activation + " has not been implemented for the CPU backend.");
+ }
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ function reshape(args) {
+ var inputs = args.inputs, backend = args.backend, attrs = args.attrs;
+ var x = inputs.x;
+ var shape = attrs.shape;
+ var xSize = tfjsCore.util.sizeFromShape(x.shape);
+ var $shape = tfjsCore.util.inferFromImplicitShape(shape, xSize);
+ var $xSize = tfjsCore.util.sizeFromShape($shape);
+ tfjsCore.util.assert(xSize === $xSize, function () { return "The new shape (" + $shape + ") has " + $xSize + " elements and the old " +
+ ("shape (" + x.shape + ") has " + xSize + " elements. The new shape and old ") +
+ "shape must have the same number of elements."; });
+ backend.incRef(x.dataId);
+ var xData = backend.data.get(x.dataId);
+ if (xData.complexTensorInfos != null) {
+ var real = xData.complexTensorInfos.real;
+ var imag = xData.complexTensorInfos.imag;
+ real.shape = $shape;
+ imag.shape = $shape;
+ }
+ return { dataId: x.dataId, shape: $shape, dtype: x.dtype };
+ }
+ var reshapeConfig = {
+ kernelName: tfjsCore.Reshape,
+ backendName: 'cpu',
+ kernelFunc: reshape
+ };
+
+ function batchMatMul(args) {
+ var inputs = args.inputs, backend = args.backend, attrs = args.attrs;
+ var a = inputs.a, b = inputs.b;
+ var transposeA = attrs.transposeA, transposeB = attrs.transposeB;
+ assertNotComplex([a, b], 'matMul');
+ var aRank = a.shape.length;
+ var bRank = b.shape.length;
+ var innerShapeA = transposeA ? a.shape[aRank - 2] : a.shape[aRank - 1];
+ var innerShapeB = transposeB ? b.shape[bRank - 1] : b.shape[bRank - 2];
+ var outerShapeA = transposeA ? a.shape[aRank - 1] : a.shape[aRank - 2];
+ var outerShapeB = transposeB ? b.shape[bRank - 2] : b.shape[bRank - 1];
+ var outerDimsA = a.shape.slice(0, -2);
+ var outerDimsB = b.shape.slice(0, -2);
+ var batchDimA = tfjsCore.util.sizeFromShape(outerDimsA);
+ var batchDimB = tfjsCore.util.sizeFromShape(outerDimsB);
+ var outShapeOuterDims = tfjsCore.broadcast_util.assertAndGetBroadcastShape(a.shape.slice(0, -2), b.shape.slice(0, -2));
+ var outShape = outShapeOuterDims.concat([outerShapeA, outerShapeB]);
+ tfjsCore.util.assert(innerShapeA === innerShapeB, function () { return "Error in matMul: inner shapes (" + innerShapeA + ") and (" +
+ (innerShapeB + ") of Tensors with shapes " + a.shape + " and ") +
+ (b.shape + " and transposeA=" + transposeA) +
+ (" and transposeB=" + transposeB + " must match."); });
+ var a3dShape = transposeA ? [batchDimA, innerShapeA, outerShapeA] :
+ [batchDimA, outerShapeA, innerShapeA];
+ var b3dShape = transposeB ? [batchDimB, outerShapeB, innerShapeB] :
+ [batchDimB, innerShapeB, outerShapeB];
+ // The rest of the implementation is designed to operate on rank-3 tensors
+ var a3d = reshape({ inputs: { x: a }, backend: backend, attrs: { shape: a3dShape } });
+ var b3d = reshape({ inputs: { x: b }, backend: backend, attrs: { shape: b3dShape } });
+ var sharedDim = transposeA ? a3d.shape[1] : a3d.shape[2];
+ var leftDim = transposeA ? a3d.shape[2] : a3d.shape[1];
+ var rightDim = transposeB ? b3d.shape[1] : b3d.shape[2];
+ var batchDim = Math.max(batchDimA, batchDimB);
+ var a3dValues = backend.data.get(a3d.dataId).values;
+ var b3dValues = backend.data.get(b3d.dataId).values;
+ var a3dStrides = tfjsCore.util.computeStrides(a3d.shape);
+ var b3dStrides = tfjsCore.util.computeStrides(b3d.shape);
+ var _a = __read(transposeA ?
+ [a3dStrides[0], 1, a3dStrides[1]] :
+ [a3dStrides[0], a3dStrides[1], 1], 3), aBatch = _a[0], aOuterStep = _a[1], aInnerStep = _a[2];
+ var _b = __read(transposeB ?
+ [1, b3dStrides[1], b3dStrides[0]] :
+ [b3dStrides[1], 1, b3dStrides[0]], 3), bInnerStep = _b[0], bOuterStep = _b[1], bBatch = _b[2];
+ var size = leftDim * rightDim;
+ var result = tfjsCore.buffer([batchDim, leftDim, rightDim], a3d.dtype);
+ var resVals = result.values;
+ var blockSize = backend.blockSize;
+ for (var bi = 0; bi < batchDim; bi++) {
+ for (var i0 = 0; i0 < leftDim; i0 += blockSize) {
+ for (var j0 = 0; j0 < rightDim; j0 += blockSize) {
+ for (var k0 = 0; k0 < sharedDim; k0 += blockSize) {
+ // for when blockSize doesn't evenly divide the input
+ var iBlock = Math.min(i0 + blockSize, leftDim);
+ var jBlock = Math.min(j0 + blockSize, rightDim);
+ var kBlock = Math.min(k0 + blockSize, sharedDim);
+ for (var i = i0; i < iBlock; i++) {
+ for (var j = j0; j < jBlock; j++) {
+ var sum = 0.0;
+ for (var k = k0; k < kBlock; k++) {
+ var batchOffsetA = Math.min(bi, batchDimA - 1) * aBatch;
+ var batchOffsetB = Math.min(bi, batchDimB - 1) * bBatch;
+ var aVal = a3dValues[batchOffsetA + i * aOuterStep + k * aInnerStep];
+ var bVal = b3dValues[k * bInnerStep + j * bOuterStep + batchOffsetB];
+ sum += aVal * bVal;
+ }
+ resVals[bi * size + (i * rightDim + j)] += sum;
+ }
+ }
+ }
+ }
+ }
+ }
+ backend.disposeIntermediateTensorInfo(a3d);
+ backend.disposeIntermediateTensorInfo(b3d);
+ // set correct shape on output.
+ return backend.makeTensorInfo(outShape, result.dtype, result.values);
+ }
+ var batchMatMulConfig = {
+ kernelName: tfjsCore.BatchMatMul,
+ backendName: 'cpu',
+ kernelFunc: batchMatMul,
+ };
+
+ function _fusedMatMul(args) {
+ var e_1, _a;
+ var inputs = args.inputs, backend = args.backend, attrs = args.attrs;
+ var a = inputs.a, b = inputs.b, bias = inputs.bias, preluActivationWeights = inputs.preluActivationWeights;
+ var transposeA = attrs.transposeA, transposeB = attrs.transposeB, activation = attrs.activation, leakyreluAlpha = attrs.leakyreluAlpha;
+ var current;
+ var addRes;
+ var activationRes;
+ var intermediates = [];
+ var matMulRes = batchMatMul({ inputs: { a: a, b: b }, attrs: { transposeA: transposeA, transposeB: transposeB }, backend: backend });
+ current = matMulRes;
+ if (bias) {
+ addRes = add({ inputs: { a: current, b: bias }, backend: backend });
+ intermediates.push(current);
+ current = addRes;
+ }
+ if (activation) {
+ activationRes = applyActivation(backend, current, activation, preluActivationWeights, leakyreluAlpha);
+ intermediates.push(current);
+ current = activationRes;
+ }
+ try {
+ for (var intermediates_1 = __values(intermediates), intermediates_1_1 = intermediates_1.next(); !intermediates_1_1.done; intermediates_1_1 = intermediates_1.next()) {
+ var i = intermediates_1_1.value;
+ backend.disposeIntermediateTensorInfo(i);
+ }
+ }
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
+ finally {
+ try {
+ if (intermediates_1_1 && !intermediates_1_1.done && (_a = intermediates_1.return)) _a.call(intermediates_1);
+ }
+ finally { if (e_1) throw e_1.error; }
+ }
+ return current;
+ }
+ var _fusedMatMulConfig = {
+ kernelName: tfjsCore._FusedMatMul,
+ backendName: 'cpu',
+ kernelFunc: _fusedMatMul,
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ var acos = unaryKernelFunc(tfjsCore.Acos, function (xi) { return Math.acos(xi); });
+ var acosConfig = {
+ kernelName: tfjsCore.Acos,
+ backendName: 'cpu',
+ kernelFunc: acos,
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ var acosh = unaryKernelFunc(tfjsCore.Acosh, function (xi) { return Math.acosh(xi); });
+ var acoshConfig = {
+ kernelName: tfjsCore.Acosh,
+ backendName: 'cpu',
+ kernelFunc: acosh,
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ function addN(args) {
+ var inputs = args.inputs, backend = args.backend;
+ var tensors = inputs;
+ assertNotComplex(inputs, 'addN');
+ var vals = tensors.map(function (t) { return backend.data.get(t.dataId).values; });
+ var outBuf = tfjsCore.buffer(tensors[0].shape, tensors[0].dtype);
+ var outVals = outBuf.values;
+ for (var i = 0; i < tensors.length; i++) {
+ var currVals = vals[i];
+ for (var j = 0; j < outVals.length; j++) {
+ outVals[j] += currVals[j];
+ }
+ }
+ return backend.makeTensorInfo(outBuf.shape, outBuf.dtype, outBuf.values);
+ }
+ var addNConfig = {
+ kernelName: tfjsCore.AddN,
+ backendName: 'cpu',
+ kernelFunc: addN
+ };
+
+ function all(args) {
+ var inputs = args.inputs, backend = args.backend, attrs = args.attrs;
+ var x = inputs.x;
+ var axis = attrs.axis, keepDims = attrs.keepDims;
+ assertNotComplex(x, 'all');
+ var origAxes = tfjsCore.util.parseAxisParam(axis, x.shape);
+ var axes = origAxes;
+ var permutedAxes = tfjsCore.backend_util.getAxesPermutation(axes, x.shape.length);
+ var $x = x;
+ if (permutedAxes != null) {
+ $x = transpose({ inputs: { x: x }, backend: backend, attrs: { perm: permutedAxes } });
+ axes = tfjsCore.backend_util.getInnerMostAxes(axes.length, x.shape.length);
+ }
+ tfjsCore.backend_util.assertAxesAreInnerMostDims('all', axes, $x.shape.length);
+ var _a = __read(tfjsCore.backend_util.computeOutAndReduceShapes($x.shape, axes), 2), outShape = _a[0], reduceShape = _a[1];
+ var reduceSize = tfjsCore.util.sizeFromShape(reduceShape);
+ var vals = tfjsCore.util.makeZerosTypedArray(tfjsCore.util.sizeFromShape(outShape), $x.dtype);
+ var aVals = backend.data.get($x.dataId).values;
+ for (var i = 0; i < vals.length; ++i) {
+ var offset = i * reduceSize;
+ var all_1 = aVals[offset];
+ for (var j = 0; j < reduceSize; ++j) {
+ var value = aVals[offset + j];
+ all_1 = all_1 && value;
+ }
+ vals[i] = all_1;
+ }
+ if (permutedAxes != null) {
+ backend.disposeIntermediateTensorInfo($x);
+ }
+ var result = backend.makeTensorInfo(outShape, $x.dtype, vals);
+ if (keepDims) {
+ var expandedShape = tfjsCore.backend_util.expandShapeToKeepDim(outShape, origAxes);
+ var reshapedResult = reshape({ inputs: { x: result }, backend: backend, attrs: { shape: expandedShape } });
+ backend.disposeIntermediateTensorInfo(result);
+ return reshapedResult;
+ }
+ return result;
+ }
+ var allConfig = {
+ kernelName: tfjsCore.All,
+ backendName: 'cpu',
+ kernelFunc: all
+ };
+
+ function any(args) {
+ var inputs = args.inputs, backend = args.backend, attrs = args.attrs;
+ var x = inputs.x;
+ var axis = attrs.axis, keepDims = attrs.keepDims;
+ assertNotComplex(x, 'any');
+ var origAxes = tfjsCore.util.parseAxisParam(axis, x.shape);
+ var axes = origAxes;
+ var permutedAxes = tfjsCore.backend_util.getAxesPermutation(axes, x.shape.length);
+ var $x = x;
+ if (permutedAxes != null) {
+ $x = transpose({ inputs: { x: x }, backend: backend, attrs: { perm: permutedAxes } });
+ axes = tfjsCore.backend_util.getInnerMostAxes(axes.length, x.shape.length);
+ }
+ tfjsCore.backend_util.assertAxesAreInnerMostDims('any', axes, $x.shape.length);
+ var _a = __read(tfjsCore.backend_util.computeOutAndReduceShapes($x.shape, axes), 2), outShape = _a[0], reduceShape = _a[1];
+ var reduceSize = tfjsCore.util.sizeFromShape(reduceShape);
+ var vals = tfjsCore.util.makeZerosTypedArray(tfjsCore.util.sizeFromShape(outShape), $x.dtype);
+ var aVals = backend.data.get($x.dataId).values;
+ for (var i = 0; i < vals.length; ++i) {
+ var offset = i * reduceSize;
+ var anyVal = aVals[offset];
+ for (var j = 0; j < reduceSize; ++j) {
+ var value = aVals[offset + j];
+ anyVal = anyVal || value;
+ }
+ vals[i] = anyVal;
+ }
+ if (permutedAxes != null) {
+ backend.disposeIntermediateTensorInfo($x);
+ }
+ var result = backend.makeTensorInfo(outShape, $x.dtype, vals);
+ if (keepDims) {
+ var expandedShape = tfjsCore.backend_util.expandShapeToKeepDim(outShape, origAxes);
+ var reshapedResult = reshape({ inputs: { x: result }, backend: backend, attrs: { shape: expandedShape } });
+ backend.disposeIntermediateTensorInfo(result);
+ return reshapedResult;
+ }
+ return result;
+ }
+ var anyConfig = {
+ kernelName: tfjsCore.Any,
+ backendName: 'cpu',
+ kernelFunc: any
+ };
+
+ function argMax(args) {
+ var inputs = args.inputs, backend = args.backend, attrs = args.attrs;
+ var x = inputs.x;
+ var axis = attrs.axis;
+ assertNotComplex(x, 'argMax');
+ var axes = tfjsCore.util.parseAxisParam(axis, x.shape);
+ var permutedAxes = tfjsCore.backend_util.getAxesPermutation(axes, x.shape.length);
+ var $x = x;
+ var intermediateTensorInfos = [];
+ if (permutedAxes != null) {
+ $x = transpose({ inputs: { x: x }, backend: backend, attrs: { perm: permutedAxes } });
+ intermediateTensorInfos.push($x);
+ axes = tfjsCore.backend_util.getInnerMostAxes(axes.length, $x.shape.length);
+ }
+ axes = [axes[0]];
+ tfjsCore.backend_util.assertAxesAreInnerMostDims('argMax', axes, $x.shape.length);
+ var _a = __read(tfjsCore.backend_util.computeOutAndReduceShapes($x.shape, axes), 2), outShape = _a[0], reduceShape = _a[1];
+ var outSize = tfjsCore.util.sizeFromShape(outShape);
+ var vals = tfjsCore.util.makeZerosTypedArray(outSize, 'int32');
+ var reduceSize = tfjsCore.util.sizeFromShape(reduceShape);
+ var aVals = backend.data.get($x.dataId).values;
+ for (var i = 0; i < vals.length; ++i) {
+ var offset = i * reduceSize;
+ var max = aVals[offset];
+ var maxIndex = 0;
+ for (var j = 0; j < reduceSize; ++j) {
+ var value = aVals[offset + j];
+ if (value > max) {
+ max = value;
+ maxIndex = j;
+ }
+ }
+ vals[i] = maxIndex;
+ }
+ intermediateTensorInfos.forEach(function (t) { return backend.disposeIntermediateTensorInfo(t); });
+ return backend.makeTensorInfo(outShape, 'int32', vals);
+ }
+ var argMaxConfig = {
+ kernelName: tfjsCore.ArgMax,
+ backendName: 'cpu',
+ kernelFunc: argMax
+ };
+
+ function argMin(args) {
+ var inputs = args.inputs, backend = args.backend, attrs = args.attrs;
+ var x = inputs.x;
+ var axis = attrs.axis;
+ assertNotComplex(x, 'argMin');
+ var axes = tfjsCore.util.parseAxisParam(axis, x.shape);
+ var permutedAxes = tfjsCore.backend_util.getAxesPermutation(axes, x.shape.length);
+ var $x = x;
+ var intermediateTensorInfos = [];
+ if (permutedAxes != null) {
+ $x = transpose({ inputs: { x: x }, backend: backend, attrs: { perm: permutedAxes } });
+ intermediateTensorInfos.push($x);
+ axes = tfjsCore.backend_util.getInnerMostAxes(axes.length, $x.shape.length);
+ }
+ axes = [axes[0]];
+ tfjsCore.backend_util.assertAxesAreInnerMostDims('argMin', axes, $x.shape.length);
+ var _a = __read(tfjsCore.backend_util.computeOutAndReduceShapes($x.shape, axes), 2), outShape = _a[0], reduceShape = _a[1];
+ var outSize = tfjsCore.util.sizeFromShape(outShape);
+ var vals = tfjsCore.util.makeZerosTypedArray(outSize, 'int32');
+ var reduceSize = tfjsCore.util.sizeFromShape(reduceShape);
+ var aVals = backend.data.get($x.dataId).values;
+ for (var i = 0; i < vals.length; ++i) {
+ var offset = i * reduceSize;
+ var min = aVals[offset];
+ var minIndex = 0;
+ for (var j = 0; j < reduceSize; ++j) {
+ var value = aVals[offset + j];
+ if (value < min) {
+ min = value;
+ minIndex = j;
+ }
+ }
+ vals[i] = minIndex;
+ }
+ intermediateTensorInfos.forEach(function (t) { return backend.disposeIntermediateTensorInfo(t); });
+ return backend.makeTensorInfo(outShape, 'int32', vals);
+ }
+ var argMinConfig = {
+ kernelName: tfjsCore.ArgMin,
+ backendName: 'cpu',
+ kernelFunc: argMin
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ var asin = unaryKernelFunc(tfjsCore.Asin, function (xi) { return Math.asin(xi); });
+ var asinConfig = {
+ kernelName: tfjsCore.Asin,
+ backendName: 'cpu',
+ kernelFunc: asin,
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ var asinh = unaryKernelFunc(tfjsCore.Asinh, function (xi) { return Math.asinh(xi); });
+ var asinhConfig = {
+ kernelName: tfjsCore.Asinh,
+ backendName: 'cpu',
+ kernelFunc: asinh,
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ var atan = unaryKernelFunc(tfjsCore.Atan, function (xi) { return Math.atan(xi); });
+ var atanConfig = {
+ kernelName: tfjsCore.Atan,
+ backendName: 'cpu',
+ kernelFunc: atan,
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ var atan2Impl = createSimpleBinaryKernelImpl(function (aValue, bValue) { return Math.atan2(aValue, bValue); });
+ var atan2 = binaryKernelFunc(tfjsCore.Atan2, atan2Impl);
+ var atan2Config = {
+ kernelName: tfjsCore.Atan2,
+ backendName: 'cpu',
+ kernelFunc: atan2,
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ var atanh = unaryKernelFunc(tfjsCore.Atanh, function (xi) { return Math.atanh(xi); });
+ var atanhConfig = {
+ kernelName: tfjsCore.Atanh,
+ backendName: 'cpu',
+ kernelFunc: atanh,
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ function pool(xValues, xShape, dtype, strides, convInfo, poolType) {
+ var strideHeight = convInfo.strideHeight;
+ var strideWidth = convInfo.strideWidth;
+ var dilationHeight = convInfo.dilationHeight;
+ var dilationWidth = convInfo.dilationWidth;
+ var effectiveFilterHeight = convInfo.effectiveFilterHeight;
+ var effectiveFilterWidth = convInfo.effectiveFilterWidth;
+ var padTop = convInfo.padInfo.top;
+ var padLeft = convInfo.padInfo.left;
+ var initialValue = (poolType === 'max' ? Number.NEGATIVE_INFINITY :
+ Number.POSITIVE_INFINITY);
+ var output = tfjsCore.buffer(convInfo.outShape, dtype);
+ var outputVals = output.values;
+ var outputBatchStrides = convInfo.outShape[1] * convInfo.outShape[2] * convInfo.outShape[3];
+ var outputRowStrides = convInfo.outShape[2] * convInfo.outShape[3];
+ var outputColStrides = convInfo.outShape[3];
+ for (var b = 0; b < convInfo.batchSize; ++b) {
+ var outputBatchOffset = b * outputBatchStrides;
+ var inputBatchOffset = b * strides[0];
+ for (var d = 0; d < convInfo.inChannels; ++d) {
+ for (var yR = 0; yR < convInfo.outHeight; ++yR) {
+ var xRCorner = yR * strideHeight - padTop;
+ var xRMin = Math.max(0, xRCorner);
+ var xRMax = Math.min(convInfo.inHeight, effectiveFilterHeight + xRCorner);
+ var outputRowOffset = outputBatchOffset + yR * outputRowStrides;
+ for (var yC = 0; yC < convInfo.outWidth; ++yC) {
+ var xCCorner = yC * strideWidth - padLeft;
+ var xCMin = Math.max(0, xCCorner);
+ var xCMax = Math.min(convInfo.inWidth, effectiveFilterWidth + xCCorner);
+ var minMaxValue = initialValue;
+ var avgValue = 0;
+ var count = 0;
+ for (var xR = xRMin; xR < xRMax; xR += dilationHeight) {
+ var xROffset = inputBatchOffset + xR * strides[1];
+ for (var xC = xCMin; xC < xCMax; xC += dilationWidth) {
+ var xCOffset = xROffset + xC * strides[2];
+ var pixel = xValues[xCOffset + d];
+ if ((poolType === 'max' && pixel > minMaxValue)) {
+ minMaxValue = pixel;
+ }
+ else if (poolType === 'avg') {
+ avgValue += pixel;
+ count++;
+ }
+ }
+ if (isNaN(minMaxValue)) {
+ break;
+ }
+ }
+ var outputOffset = outputRowOffset + yC * outputColStrides + d;
+ outputVals[outputOffset] =
+ poolType === 'avg' ? avgValue / count : minMaxValue;
+ }
+ }
+ }
+ }
+ return output;
+ }
+ function maxPoolPositions(xValues, xShape, dtype, convInfo, flattenPositions, includeBatchInIndex) {
+ if (flattenPositions === void 0) { flattenPositions = false; }
+ if (includeBatchInIndex === void 0) { includeBatchInIndex = false; }
+ var maxPositions = tfjsCore.buffer(convInfo.outShape, 'int32');
+ var strideHeight = convInfo.strideHeight;
+ var strideWidth = convInfo.strideWidth;
+ var dilationHeight = convInfo.dilationHeight;
+ var dilationWidth = convInfo.dilationWidth;
+ var effectiveFilterHeight = convInfo.effectiveFilterHeight;
+ var effectiveFilterWidth = convInfo.effectiveFilterWidth;
+ var padTop = convInfo.padInfo.top;
+ var padLeft = convInfo.padInfo.left;
+ var xBuf = tfjsCore.buffer(xShape, dtype, xValues);
+ for (var b = 0; b < convInfo.batchSize; ++b) {
+ for (var d = 0; d < convInfo.inChannels; ++d) {
+ for (var yR = 0; yR < convInfo.outHeight; ++yR) {
+ var xRCorner = yR * strideHeight - padTop;
+ var xRMin = xRCorner;
+ while (xRMin < 0) {
+ xRMin += dilationHeight;
+ }
+ // const xRMin = Math.max(0, xRCorner);
+ var xRMax = Math.min(convInfo.inHeight, effectiveFilterHeight + xRCorner);
+ for (var yC = 0; yC < convInfo.outWidth; ++yC) {
+ var xCCorner = yC * strideWidth - padLeft;
+ var xCMin = xCCorner;
+ while (xCMin < 0) {
+ xCMin += dilationWidth;
+ }
+ var xCMax = Math.min(convInfo.inWidth, effectiveFilterWidth + xCCorner);
+ var maxValue = Number.NEGATIVE_INFINITY;
+ var maxPosition = -1;
+ for (var xR = xRMin; xR < xRMax; xR += dilationHeight) {
+ var wR = xR - xRCorner;
+ for (var xC = xCMin; xC < xCMax; xC += dilationWidth) {
+ var wC = xC - xCCorner;
+ var pixel = xBuf.get(b, xR, xC, d);
+ if (pixel > maxValue) {
+ maxValue = pixel;
+ if (flattenPositions) {
+ maxPosition = includeBatchInIndex ?
+ ((b * convInfo.inHeight + xR) * convInfo.inWidth + xC) *
+ convInfo.inChannels +
+ d :
+ (xR * convInfo.inWidth + xC) * convInfo.inChannels + d;
+ }
+ else {
+ maxPosition = wR * effectiveFilterWidth + wC;
+ }
+ }
+ }
+ }
+ maxPositions.set(maxPosition, b, yR, yC, d);
+ }
+ }
+ }
+ }
+ return maxPositions;
+ }
+ function pool3d(xValues, xShape, dtype, strides, convInfo, poolType) {
+ var strideDepth = convInfo.strideDepth;
+ var strideHeight = convInfo.strideHeight;
+ var strideWidth = convInfo.strideWidth;
+ var dilationDepth = convInfo.dilationDepth;
+ var dilationHeight = convInfo.dilationHeight;
+ var dilationWidth = convInfo.dilationWidth;
+ var effectiveFilterDepth = convInfo.effectiveFilterDepth;
+ var effectiveFilterHeight = convInfo.effectiveFilterHeight;
+ var effectiveFilterWidth = convInfo.effectiveFilterWidth;
+ var padFront = convInfo.padInfo.front;
+ var padTop = convInfo.padInfo.top;
+ var padLeft = convInfo.padInfo.left;
+ var initialValue = (poolType === 'max' ? Number.NEGATIVE_INFINITY :
+ Number.POSITIVE_INFINITY);
+ var output = tfjsCore.buffer(convInfo.outShape, dtype);
+ var outputVals = output.values;
+ var outputBatchStrides = convInfo.outShape[1] * convInfo.outShape[2] *
+ convInfo.outShape[3] * convInfo.outShape[4];
+ var outputDepthStrides = convInfo.outShape[2] * convInfo.outShape[3] * convInfo.outShape[4];
+ var outputRowStrides = convInfo.outShape[3] * convInfo.outShape[4];
+ var outputColStrides = convInfo.outShape[4];
+ for (var batch = 0; batch < convInfo.batchSize; ++batch) {
+ var outputBatchOffset = batch * outputBatchStrides;
+ var inputBatchOffset = batch * strides[0];
+ for (var channel = 0; channel < convInfo.inChannels; ++channel) {
+ for (var yDepth = 0; yDepth < convInfo.outDepth; ++yDepth) {
+ var xDepthCorner = yDepth * strideDepth - padFront;
+ var xDepthMin = xDepthCorner;
+ while (xDepthMin < 0) {
+ xDepthMin += dilationDepth;
+ }
+ var xDepthMax = Math.min(convInfo.inDepth, effectiveFilterDepth + xDepthCorner);
+ var outputDepthOffset = outputBatchOffset + yDepth * outputDepthStrides;
+ for (var yRow = 0; yRow < convInfo.outHeight; ++yRow) {
+ var xRowCorner = yRow * strideHeight - padTop;
+ var xRowMin = xRowCorner;
+ while (xRowMin < 0) {
+ xRowMin += dilationHeight;
+ }
+ var xRowMax = Math.min(convInfo.inHeight, effectiveFilterHeight + xRowCorner);
+ var outputRowOffset = outputDepthOffset + yRow * outputRowStrides;
+ for (var yCol = 0; yCol < convInfo.outWidth; ++yCol) {
+ var xColCorner = yCol * strideWidth - padLeft;
+ var xColMin = xColCorner;
+ while (xColMin < 0) {
+ xColMin += dilationWidth;
+ }
+ var xColMax = Math.min(convInfo.inWidth, effectiveFilterWidth + xColCorner);
+ // Shader code begins
+ var outputColOffset = outputRowOffset + yCol * outputColStrides;
+ var minMaxValue = initialValue;
+ var avgValue = 0;
+ var count = 0;
+ for (var xDepth = xDepthMin; xDepth < xDepthMax; xDepth += dilationDepth) {
+ var xDepthOffset = inputBatchOffset + xDepth * strides[1];
+ for (var xRow = xRowMin; xRow < xRowMax; xRow += dilationHeight) {
+ var xRowOffset = xDepthOffset + xRow * strides[2];
+ for (var xCol = xColMin; xCol < xColMax; xCol += dilationWidth) {
+ var xColOffset = xRowOffset + xCol * strides[3];
+ var pixel = xValues[xColOffset + channel];
+ if ((poolType === 'max' && pixel > minMaxValue)) {
+ minMaxValue = pixel;
+ }
+ else if (poolType === 'avg') {
+ avgValue += pixel;
+ count++;
+ }
+ if (isNaN(minMaxValue)) {
+ break;
+ }
+ }
+ if (isNaN(minMaxValue)) {
+ break;
+ }
+ }
+ if (isNaN(minMaxValue)) {
+ break;
+ }
+ }
+ var outputOffset = outputColOffset + channel;
+ outputVals[outputOffset] =
+ poolType === 'avg' ? avgValue / count : minMaxValue;
+ }
+ }
+ }
+ }
+ }
+ return output;
+ }
+ function maxPool3dPositions(xBuf, convInfo) {
+ var maxPositions = tfjsCore.buffer(convInfo.outShape, 'int32');
+ var strideDepth = convInfo.strideDepth;
+ var strideHeight = convInfo.strideHeight;
+ var strideWidth = convInfo.strideWidth;
+ var dilationDepth = convInfo.dilationDepth;
+ var dilationHeight = convInfo.dilationHeight;
+ var dilationWidth = convInfo.dilationWidth;
+ var effectiveFilterDepth = convInfo.effectiveFilterDepth;
+ var effectiveFilterHeight = convInfo.effectiveFilterHeight;
+ var effectiveFilterWidth = convInfo.effectiveFilterWidth;
+ var padFront = convInfo.padInfo.front;
+ var padTop = convInfo.padInfo.top;
+ var padLeft = convInfo.padInfo.left;
+ for (var batch = 0; batch < convInfo.batchSize; ++batch) {
+ for (var channel = 0; channel < convInfo.inChannels; ++channel) {
+ for (var yDepth = 0; yDepth < convInfo.outDepth; ++yDepth) {
+ var xDepthCorner = yDepth * strideDepth - padFront;
+ var xDepthMin = xDepthCorner;
+ while (xDepthMin < 0) {
+ xDepthMin += dilationDepth;
+ }
+ var xDepthMax = Math.min(convInfo.inDepth, effectiveFilterDepth + xDepthCorner);
+ for (var yRow = 0; yRow < convInfo.outHeight; ++yRow) {
+ var xRowCorner = yRow * strideHeight - padTop;
+ var xRowMin = xRowCorner;
+ while (xRowMin < 0) {
+ xRowMin += dilationHeight;
+ }
+ var xRowMax = Math.min(convInfo.inHeight, effectiveFilterHeight + xRowCorner);
+ for (var yCol = 0; yCol < convInfo.outWidth; ++yCol) {
+ var xColCorner = yCol * strideWidth - padLeft;
+ var xColMin = xColCorner;
+ while (xColMin < 0) {
+ xColMin += dilationWidth;
+ }
+ var xColMax = Math.min(convInfo.inWidth, effectiveFilterWidth + xColCorner);
+ // Shader code begins
+ var maxValue = Number.NEGATIVE_INFINITY;
+ var maxPosition = -1;
+ for (var xDepth = xDepthMin; xDepth < xDepthMax; xDepth += dilationDepth) {
+ var wDepth = xDepth - xDepthCorner;
+ for (var xRow = xRowMin; xRow < xRowMax; xRow += dilationHeight) {
+ var wRow = xRow - xRowCorner;
+ for (var xCol = xColMin; xCol < xColMax; xCol += dilationWidth) {
+ var wCol = xCol - xColCorner;
+ var pixel = xBuf.get(batch, xDepth, xRow, xCol, channel);
+ if (pixel >= maxValue) {
+ maxValue = pixel;
+ maxPosition =
+ wDepth * effectiveFilterHeight * effectiveFilterWidth +
+ wRow * effectiveFilterHeight + wCol;
+ }
+ }
+ }
+ }
+ maxPositions.set(maxPosition, batch, yDepth, yRow, yCol, channel);
+ }
+ }
+ }
+ }
+ }
+ return maxPositions;
+ }
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ function avgPool(args) {
+ var inputs = args.inputs, backend = args.backend, attrs = args.attrs;
+ var x = inputs.x;
+ assertNotComplex(x, 'avgPool');
+ var filterSize = attrs.filterSize, strides = attrs.strides, pad = attrs.pad, dimRoundingMode = attrs.dimRoundingMode;
+ var dilations = 1;
+ tfjsCore.util.assert(tfjsCore.backend_util.eitherStridesOrDilationsAreOne(strides, dilations), function () { return 'Error in avgPool: Either strides or dilations must be 1. ' +
+ ("Got strides " + strides + " and dilations '" + dilations + "'"); });
+ var convInfo = tfjsCore.backend_util.computePool2DInfo(x.shape, filterSize, strides, dilations, pad, dimRoundingMode);
+ var res;
+ if (convInfo.filterWidth === 1 && convInfo.filterHeight === 1 &&
+ tfjsCore.util.arraysEqual(convInfo.inShape, convInfo.outShape)) {
+ res = identity({ inputs: { x: x }, backend: backend });
+ }
+ else {
+ var xValues = backend.data.get(x.dataId).values;
+ var strides_1 = tfjsCore.util.computeStrides(x.shape);
+ var buffer = pool(xValues, x.shape, x.dtype, strides_1, convInfo, 'avg');
+ res = backend.makeTensorInfo(convInfo.outShape, x.dtype, buffer.values);
+ }
+ return res;
+ }
+ var avgPoolConfig = {
+ kernelName: tfjsCore.AvgPool,
+ backendName: 'cpu',
+ kernelFunc: avgPool
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ function avgPool3D(args) {
+ var inputs = args.inputs, backend = args.backend, attrs = args.attrs;
+ var x = inputs.x;
+ var filterSize = attrs.filterSize, strides = attrs.strides, pad = attrs.pad, dimRoundingMode = attrs.dimRoundingMode, dataFormat = attrs.dataFormat;
+ assertNotComplex(x, 'avgPool3d');
+ var convInfo = tfjsCore.backend_util.computePool3DInfo(x.shape, filterSize, strides, 1 /* dilations */, pad, dimRoundingMode, dataFormat);
+ var xValues = backend.data.get(x.dataId).values;
+ var outBuf = pool3d(xValues, x.shape, x.dtype, tfjsCore.util.computeStrides(x.shape), convInfo, 'avg');
+ return backend.makeTensorInfo(outBuf.shape, 'float32', outBuf.values);
+ }
+ var avgPool3DConfig = {
+ kernelName: tfjsCore.AvgPool3D,
+ backendName: 'cpu',
+ kernelFunc: avgPool3D
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ function avgPool3DGrad(args) {
+ var inputs = args.inputs, backend = args.backend, attrs = args.attrs;
+ var dy = inputs.dy, input = inputs.input;
+ var filterSize = attrs.filterSize, strides = attrs.strides, pad = attrs.pad, dimRoundingMode = attrs.dimRoundingMode;
+ assertNotComplex([dy, input], 'avgPool3DGrad');
+ var convInfo = tfjsCore.backend_util.computePool3DInfo(input.shape, filterSize, strides, 1 /* dilations */, pad, dimRoundingMode);
+ var strideDepth = convInfo.strideDepth;
+ var strideHeight = convInfo.strideHeight;
+ var strideWidth = convInfo.strideWidth;
+ var filterDepth = convInfo.filterDepth;
+ var filterHeight = convInfo.filterHeight;
+ var filterWidth = convInfo.filterWidth;
+ var dilationDepth = convInfo.dilationDepth;
+ var dilationHeight = convInfo.dilationHeight;
+ var dilationWidth = convInfo.dilationWidth;
+ var effectiveFilterDepth = convInfo.effectiveFilterDepth;
+ var effectiveFilterHeight = convInfo.effectiveFilterHeight;
+ var effectiveFilterWidth = convInfo.effectiveFilterWidth;
+ var padFront = effectiveFilterDepth - 1 - convInfo.padInfo.front;
+ var padLeft = effectiveFilterWidth - 1 - convInfo.padInfo.left;
+ var padTop = effectiveFilterHeight - 1 - convInfo.padInfo.top;
+ var dx = tfjsCore.buffer(input.shape, 'float32');
+ var avgMultiplier = 1 / (filterDepth * filterHeight * filterWidth);
+ var dyBuf = backend.bufferSync(dy);
+ for (var batch = 0; batch < convInfo.batchSize; ++batch) {
+ for (var channel = 0; channel < convInfo.inChannels; ++channel) {
+ for (var dxDepth = 0; dxDepth < convInfo.inDepth; ++dxDepth) {
+ for (var dxRow = 0; dxRow < convInfo.inHeight; ++dxRow) {
+ for (var dxCol = 0; dxCol < convInfo.inWidth; ++dxCol) {
+ // Shader code begins.
+ var dyDepthCorner = dxDepth - padFront;
+ var dyRowCorner = dxRow - padTop;
+ var dyColCorner = dxCol - padLeft;
+ var dotProd = 0;
+ for (var wDepth = 0; wDepth < effectiveFilterDepth; wDepth += dilationDepth) {
+ var dyDepth = (dyDepthCorner + wDepth) / strideDepth;
+ if (dyDepth < 0 || dyDepth >= convInfo.outDepth ||
+ Math.floor(dyDepth) !== dyDepth) {
+ continue;
+ }
+ for (var wRow = 0; wRow < effectiveFilterHeight; wRow += dilationHeight) {
+ var dyRow = (dyRowCorner + wRow) / strideHeight;
+ if (dyRow < 0 || dyRow >= convInfo.outHeight ||
+ Math.floor(dyRow) !== dyRow) {
+ continue;
+ }
+ for (var wCol = 0; wCol < effectiveFilterWidth; wCol += dilationWidth) {
+ var dyCol = (dyColCorner + wCol) / strideWidth;
+ if (dyCol < 0 || dyCol >= convInfo.outWidth ||
+ Math.floor(dyCol) !== dyCol) {
+ continue;
+ }
+ var pixel = dyBuf.get(batch, dyDepth, dyRow, dyCol, channel);
+ dotProd += pixel;
+ }
+ }
+ }
+ dx.set(dotProd * avgMultiplier, batch, dxDepth, dxRow, dxCol, channel);
+ }
+ }
+ }
+ }
+ }
+ return backend.makeTensorInfo(dx.shape, dx.dtype, dx.values);
+ }
+ var avgPool3DGradConfig = {
+ kernelName: tfjsCore.AvgPool3DGrad,
+ backendName: 'cpu',
+ kernelFunc: avgPool3DGrad
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ function avgPoolGrad(args) {
+ var inputs = args.inputs, backend = args.backend, attrs = args.attrs;
+ var dy = inputs.dy, input = inputs.input;
+ var x = input;
+ assertNotComplex([dy, input], 'avgPoolGrad');
+ var filterSize = attrs.filterSize, strides = attrs.strides, pad = attrs.pad;
+ var convInfo = tfjsCore.backend_util.computePool2DInfo(x.shape, filterSize, strides, 1 /* dilations */, pad);
+ var strideHeight = convInfo.strideHeight;
+ var strideWidth = convInfo.strideWidth;
+ var filterHeight = convInfo.filterHeight;
+ var filterWidth = convInfo.filterWidth;
+ var dilationHeight = convInfo.dilationHeight;
+ var dilationWidth = convInfo.dilationWidth;
+ var effectiveFilterHeight = convInfo.effectiveFilterHeight;
+ var effectiveFilterWidth = convInfo.effectiveFilterWidth;
+ var padLeft = effectiveFilterWidth - 1 - convInfo.padInfo.left;
+ var padTop = effectiveFilterHeight - 1 - convInfo.padInfo.top;
+ var dx = tfjsCore.buffer(x.shape, 'float32');
+ var avgMultiplier = 1 / (filterHeight * filterWidth);
+ var dyData = backend.data.get(dy.dataId).values;
+ var dyBuf = tfjsCore.buffer(dy.shape, 'float32', dyData);
+ for (var b = 0; b < convInfo.batchSize; ++b) {
+ for (var d = 0; d < convInfo.inChannels; ++d) {
+ for (var dxR = 0; dxR < convInfo.inHeight; ++dxR) {
+ for (var dxC = 0; dxC < convInfo.inWidth; ++dxC) {
+ // Shader code begins.
+ var dyRCorner = dxR - padTop;
+ var dyCCorner = dxC - padLeft;
+ var dotProd = 0;
+ for (var wR = 0; wR < effectiveFilterHeight; wR += dilationHeight) {
+ var dyR = (dyRCorner + wR) / strideHeight;
+ if (dyR < 0 || dyR >= convInfo.outHeight ||
+ Math.floor(dyR) !== dyR) {
+ continue;
+ }
+ for (var wC = 0; wC < effectiveFilterWidth; wC += dilationWidth) {
+ var dyC = (dyCCorner + wC) / strideWidth;
+ if (dyC < 0 || dyC >= convInfo.outWidth ||
+ Math.floor(dyC) !== dyC) {
+ continue;
+ }
+ var pixel = dyBuf.get(b, dyR, dyC, d);
+ dotProd += pixel;
+ }
+ }
+ dx.set(dotProd * avgMultiplier, b, dxR, dxC, d);
+ }
+ }
+ }
+ }
+ return backend.makeTensorInfo(dx.shape, dx.dtype, dx.values);
+ }
+ var avgPoolGradConfig = {
+ kernelName: tfjsCore.AvgPoolGrad,
+ backendName: 'cpu',
+ kernelFunc: avgPoolGrad
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ function batchNorm(args) {
+ var inputs = args.inputs, backend = args.backend, attrs = args.attrs;
+ var x = inputs.x, scale = inputs.scale, offset = inputs.offset, mean = inputs.mean, variance = inputs.variance;
+ tfjsCore.util.assert(mean.shape.length === variance.shape.length, function () { return 'Batch normalization gradient requires mean and variance to have ' +
+ 'equal ranks.'; });
+ tfjsCore.util.assert(offset == null || mean.shape.length === offset.shape.length, function () { return 'Batch normalization gradient requires mean and offset to have ' +
+ 'equal ranks.'; });
+ tfjsCore.util.assert(scale == null || mean.shape.length === scale.shape.length, function () { return 'Batch normalization gradient requires mean and scale to have ' +
+ 'equal ranks.'; });
+ assertNotComplex([x, mean, variance, scale, offset], 'batchNorm');
+ var varianceEpsilon = attrs.varianceEpsilon;
+ if (varianceEpsilon == null) {
+ varianceEpsilon = 0.001;
+ }
+ var xVals = backend.data.get(x.dataId).values;
+ var mVals = backend.data.get(mean.dataId).values;
+ var varVals = backend.data.get(variance.dataId).values;
+ var sVals = scale ? backend.data.get(scale.dataId).values :
+ new Float32Array([1]);
+ var offVals = offset ?
+ backend.data.get(offset.dataId).values :
+ new Float32Array([0]);
+ var outVals = new Float32Array(xVals.length);
+ var offValsLength = offVals.length;
+ var sValsLength = sVals.length;
+ var varValsLength = varVals.length;
+ var mValsLength = mVals.length;
+ var offi = 0;
+ var mi = 0;
+ var si = 0;
+ var vi = 0;
+ for (var i = 0; i < xVals.length; ++i) {
+ outVals[i] = offVals[offi++] +
+ (xVals[i] - mVals[mi++]) * sVals[si++] /
+ Math.sqrt(varVals[vi++] + varianceEpsilon);
+ if (offi >= offValsLength) {
+ offi = 0;
+ }
+ if (mi >= mValsLength) {
+ mi = 0;
+ }
+ if (si >= sValsLength) {
+ si = 0;
+ }
+ if (vi >= varValsLength) {
+ vi = 0;
+ }
+ }
+ return backend.makeTensorInfo(x.shape, x.dtype, outVals);
+ }
+ var batchNormConfig = {
+ kernelName: tfjsCore.FusedBatchNorm,
+ backendName: 'cpu',
+ kernelFunc: batchNorm,
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ function batchToSpaceND(args) {
+ var inputs = args.inputs, backend = args.backend, attrs = args.attrs;
+ var x = inputs.x;
+ var blockShape = attrs.blockShape, crops = attrs.crops;
+ assertNotComplex([x], 'batchToSpaceND');
+ var prod = blockShape.reduce(function (a, b) { return a * b; });
+ var reshaped = tfjsCore.backend_util.getReshaped(x.shape, blockShape, prod);
+ var permuted = tfjsCore.backend_util.getPermuted(reshaped.length, blockShape.length);
+ var reshapedPermuted = tfjsCore.backend_util.getReshapedPermuted(x.shape, blockShape, prod);
+ var sliceBeginCoords = tfjsCore.backend_util.getSliceBeginCoords(crops, blockShape.length);
+ var sliceSize = tfjsCore.backend_util.getSliceSize(reshapedPermuted, crops, blockShape.length);
+ var xReshaped = reshape({ inputs: { x: x }, backend: backend, attrs: { shape: reshaped } });
+ var xTransposed = transpose({ inputs: { x: xReshaped }, backend: backend, attrs: { perm: permuted } });
+ var xTransposedReshaped = reshape({ inputs: { x: xTransposed }, backend: backend, attrs: { shape: reshapedPermuted } });
+ var result = slice({
+ inputs: { x: xTransposedReshaped },
+ backend: backend,
+ attrs: { begin: sliceBeginCoords, size: sliceSize }
+ });
+ backend.disposeIntermediateTensorInfo(xReshaped);
+ backend.disposeIntermediateTensorInfo(xTransposed);
+ backend.disposeIntermediateTensorInfo(xTransposedReshaped);
+ return result;
+ }
+ var batchToSpaceNDConfig = {
+ kernelName: tfjsCore.BatchToSpaceND,
+ backendName: 'cpu',
+ kernelFunc: batchToSpaceND
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ function bincount(args) {
+ var inputs = args.inputs, backend = args.backend, attrs = args.attrs;
+ var x = inputs.x, weights = inputs.weights;
+ var size = attrs.size;
+ var xVals = backend.data.get(x.dataId).values;
+ var weightsVals = backend.data.get(weights.dataId).values;
+ var outVals = bincountImpl(xVals, weightsVals, weights.dtype, weights.shape, size);
+ return backend.makeTensorInfo([size], weights.dtype, outVals);
+ }
+ var bincountConfig = {
+ kernelName: tfjsCore.Bincount,
+ backendName: 'cpu',
+ kernelFunc: bincount
+ };
+
+ /**
+ * @license
+ * Copyright 2021 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ function broadcastArgs(args) {
+ var inputs = args.inputs, backend = args.backend;
+ var s0 = inputs.s0, s1 = inputs.s1;
+ var s0Vals = backend.data.get(s0.dataId).values;
+ var s1Vals = backend.data.get(s1.dataId).values;
+ var broadcastShape = tfjsCore.backend_util.assertAndGetBroadcastShape(Array.from(s0Vals), Array.from(s1Vals));
+ return backend.makeTensorInfo([broadcastShape.length], 'int32', Int32Array.from(broadcastShape));
+ }
+ var broadcastArgsConfig = {
+ kernelName: tfjsCore.BroadcastArgs,
+ backendName: 'cpu',
+ kernelFunc: broadcastArgs
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ var clip = unaryKernelFunc(tfjsCore.ClipByValue, function (xi, attrs) {
+ var clipAttrs = attrs;
+ if (xi > clipAttrs.clipValueMax) {
+ return clipAttrs.clipValueMax;
+ }
+ return xi < clipAttrs.clipValueMin ? clipAttrs.clipValueMin : xi;
+ });
+ var clipConfig = {
+ kernelName: tfjsCore.ClipByValue,
+ backendName: 'cpu',
+ kernelFunc: clip,
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ var complexAbs = function (args) {
+ var x = args.inputs.x;
+ var cpuBackend = args.backend;
+ var resultValues = new Float32Array(tfjsCore.util.sizeFromShape(x.shape));
+ var complexVals = cpuBackend.data.get(x.dataId);
+ var real = complexVals.complexTensorInfos.real;
+ var imag = complexVals.complexTensorInfos.imag;
+ var realVals = cpuBackend.data.get(real.dataId).values;
+ var imagVals = cpuBackend.data.get(imag.dataId).values;
+ for (var i = 0; i < realVals.length; i++) {
+ var real_1 = realVals[i];
+ var imag_1 = imagVals[i];
+ resultValues[i] = Math.hypot(real_1, imag_1);
+ }
+ return cpuBackend.makeOutput(resultValues, x.shape, 'float32');
+ };
+ var complexAbsConfig = {
+ kernelName: tfjsCore.ComplexAbs,
+ backendName: 'cpu',
+ kernelFunc: complexAbs,
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ function imag(args) {
+ var inputs = args.inputs, backend = args.backend;
+ var input = inputs.input;
+ var imag = backend.data.get(input.dataId).complexTensorInfos.imag;
+ var imagVal = backend.data.get(imag.dataId).values;
+ // When complex tensor is disposed, its underlying parts will be disposed too.
+ // Make new tensor out of the imag value of the complex. This makes sure the
+ // value is still accessible even if complex tensor is disposed.
+ return backend.makeTensorInfo(imag.shape, imag.dtype, imagVal);
+ }
+ var imagConfig = {
+ kernelName: tfjsCore.Imag,
+ backendName: 'cpu',
+ kernelFunc: imag
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ function concat(args) {
+ var inputs = args.inputs, backend = args.backend, attrs = args.attrs;
+ var axis = attrs.axis;
+ var $axis = tfjsCore.util.parseAxisParam(axis, inputs[0].shape)[0];
+ var outShape = tfjsCore.backend_util.computeOutShape(inputs.map(function (t) { return t.shape; }), $axis);
+ if (tfjsCore.util.sizeFromShape(outShape) === 0) {
+ return backend.makeTensorInfo(outShape, inputs[0].dtype, []);
+ }
+ // Keep only non-empty tensors (ignore tensors with 0 in their shape).
+ var $inputs = inputs.filter(function (t) { return tfjsCore.util.sizeFromShape(t.shape) > 0; });
+ if ($inputs.length === 1) {
+ return identity({ inputs: { x: $inputs[0] }, backend: backend });
+ }
+ var shapes = $inputs.map(function (t) { return t.shape; });
+ tfjsCore.backend_util.assertParamsConsistent(shapes, $axis);
+ if ($inputs[0].dtype === 'complex64') {
+ var reals = $inputs.map(function (t) { return real({ inputs: { input: t }, backend: backend }); });
+ var imags = $inputs.map(function (t) { return imag({ inputs: { input: t }, backend: backend }); });
+ var realConcated = concat({ inputs: reals, backend: backend, attrs: { axis: $axis } });
+ var imagConcated = concat({ inputs: imags, backend: backend, attrs: { axis: $axis } });
+ var result = complex({ inputs: { real: realConcated, imag: imagConcated }, backend: backend });
+ reals.forEach(function (r) { return backend.disposeIntermediateTensorInfo(r); });
+ imags.forEach(function (i) { return backend.disposeIntermediateTensorInfo(i); });
+ backend.disposeIntermediateTensorInfo(realConcated);
+ backend.disposeIntermediateTensorInfo(imagConcated);
+ return result;
+ }
+ // Any concat of n-dimensional tensors across any axis can be reduced to
+ // a concatenation of two-dimensional tensors across the axis 1 by first
+ // partitioning the axes of the original tensors into those less than the
+ // axis to be concatenated and the rest. Then reshape the tensors
+ // into a two-dimensional tensor by collapsing these two sets of axes and
+ // concatenate the resulting matrices across the axis 1, finally reshaping
+ // the result to have the proper shape.
+ var inputs2D = $inputs.map(function (t) {
+ var innerSize = tfjsCore.util.sizeFromShape(t.shape.slice($axis));
+ var shape = [-1, innerSize];
+ return reshape({ inputs: { x: t }, backend: backend, attrs: { shape: shape } });
+ });
+ var inputsValShapes = inputs2D.map(function (t) {
+ return { vals: backend.data.get(t.dataId).values, shape: t.shape };
+ });
+ // Concats 2d tensors along axis=1.
+ outShape =
+ tfjsCore.backend_util.computeOutShape(inputs2D.map(function (t) { return t.shape; }), 1 /* axis */);
+ var simplyConcat = inputs2D[0].shape[0] === 1;
+ var outVals = concatImpl(inputsValShapes, outShape, inputs[0].dtype, simplyConcat);
+ var finalOutShape = tfjsCore.backend_util.computeOutShape($inputs.map(function (t) { return t.shape; }), $axis);
+ var outInfo = backend.makeTensorInfo(finalOutShape, inputs[0].dtype, outVals);
+ inputs2D.forEach(function (t) { return backend.disposeIntermediateTensorInfo(t); });
+ return outInfo;
+ }
+ var concatConfig = {
+ kernelName: tfjsCore.Concat,
+ backendName: 'cpu',
+ kernelFunc: concat
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ function conv2D(args) {
+ var inputs = args.inputs, backend = args.backend, attrs = args.attrs;
+ var x = inputs.x, filter = inputs.filter;
+ var strides = attrs.strides, pad = attrs.pad, dataFormat = attrs.dataFormat, dilations = attrs.dilations, dimRoundingMode = attrs.dimRoundingMode;
+ assertNotComplex([x, filter], 'conv2d');
+ var $dataFormat = tfjsCore.backend_util.convertConv2DDataFormat(dataFormat);
+ var convInfo = tfjsCore.backend_util.computeConv2DInfo(x.shape, filter.shape, strides, dilations, pad, dimRoundingMode, false /* depthwise */, $dataFormat);
+ var filterHeight = convInfo.filterHeight;
+ var filterWidth = convInfo.filterWidth;
+ var dilationHeight = convInfo.dilationHeight;
+ var dilationWidth = convInfo.dilationWidth;
+ var padLeft = convInfo.padInfo.left;
+ var padTop = convInfo.padInfo.top;
+ var isChannelsLast = convInfo.dataFormat === 'channelsLast';
+ var y = new tfjsCore.TensorBuffer(convInfo.outShape, x.dtype);
+ var xStrides = tfjsCore.util.computeStrides(x.shape);
+ var filterStrides = tfjsCore.util.computeStrides(filter.shape);
+ var xBatchStride = xStrides[0];
+ var xRowStride = isChannelsLast ? xStrides[1] : xStrides[2];
+ var xColStride = isChannelsLast ? xStrides[2] : 1;
+ var xChannelStride = isChannelsLast ? 1 : xStrides[1];
+ var yBatchStride = y.strides[0];
+ var yRowStride = isChannelsLast ? y.strides[1] : y.strides[2];
+ var yColStride = isChannelsLast ? y.strides[2] : 1;
+ var yChannelStride = isChannelsLast ? 1 : y.strides[1];
+ var xVals = backend.data.get(x.dataId).values;
+ var wVals = backend.data.get(filter.dataId).values;
+ var yVals = y.values;
+ for (var b = 0; b < convInfo.batchSize; ++b) {
+ var xOffset1 = b * xBatchStride;
+ var yOffset1 = b * yBatchStride;
+ for (var yR = 0; yR < convInfo.outHeight; ++yR) {
+ var yOffset2 = yOffset1 + yR * yRowStride;
+ var xRCorner = yR * convInfo.strideHeight - padTop;
+ for (var wR = 0; wR < filterHeight; ++wR) {
+ var xR = xRCorner + wR * dilationHeight;
+ if (xR < 0 || xR >= convInfo.inHeight) {
+ continue;
+ }
+ var wOffset1 = wR * filterStrides[0];
+ var xOffset2 = xOffset1 + xR * xRowStride;
+ for (var yC = 0; yC < convInfo.outWidth; ++yC) {
+ var yOffset3 = yOffset2 + yC * yColStride;
+ var xCCorner = yC * convInfo.strideWidth - padLeft;
+ for (var wC = 0; wC < filterWidth; ++wC) {
+ var xC = xCCorner + wC * dilationWidth;
+ if (xC < 0 || xC >= convInfo.inWidth) {
+ continue;
+ }
+ var wOffset2 = wOffset1 + wC * filterStrides[1];
+ var xOffset3 = xOffset2 + xC * xColStride;
+ var wOffset3 = wOffset2;
+ for (var d1 = 0; d1 < convInfo.inChannels; ++d1) {
+ var xVal = xVals[xOffset3 + d1 * xChannelStride];
+ for (var d2 = 0; d2 < convInfo.outChannels; ++d2) {
+ yVals[yOffset3 + d2 * yChannelStride] +=
+ xVal * wVals[wOffset3 + d2];
+ }
+ wOffset3 += convInfo.outChannels;
+ }
+ }
+ }
+ }
+ }
+ }
+ return backend.makeTensorInfo(y.shape, y.dtype, yVals);
+ }
+ var conv2DConfig = {
+ kernelName: tfjsCore.Conv2D,
+ backendName: 'cpu',
+ kernelFunc: conv2D
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ function conv2DBackpropFilter(args) {
+ var inputs = args.inputs, backend = args.backend, attrs = args.attrs;
+ var x = inputs.x, dy = inputs.dy;
+ var strides = attrs.strides, pad = attrs.pad, dataFormat = attrs.dataFormat, dimRoundingMode = attrs.dimRoundingMode, filterShape = attrs.filterShape;
+ assertNotComplex([x, dy], 'conv2dBackpropFilter');
+ var $dataFormat = tfjsCore.backend_util.convertConv2DDataFormat(dataFormat);
+ var convInfo = tfjsCore.backend_util.computeConv2DInfo(x.shape, filterShape, strides, 1 /* dilations */, pad, dimRoundingMode, false /* depthwise */, $dataFormat);
+ var strideHeight = convInfo.strideHeight, strideWidth = convInfo.strideWidth, filterHeight = convInfo.filterHeight, filterWidth = convInfo.filterWidth;
+ var isChannelsLast = convInfo.dataFormat === 'channelsLast';
+ var dW = new tfjsCore.TensorBuffer(convInfo.filterShape, 'float32');
+ var leftPad = convInfo.padInfo.left;
+ var topPad = convInfo.padInfo.top;
+ var xVals = backend.data.get(x.dataId).values;
+ var dyVals = backend.data.get(dy.dataId).values;
+ var xBuf = new tfjsCore.TensorBuffer(x.shape, x.dtype, xVals);
+ var dyBuf = new tfjsCore.TensorBuffer(dy.shape, dy.dtype, dyVals);
+ for (var wR = 0; wR < filterHeight; ++wR) {
+ var yRMin = Math.max(0, Math.ceil((topPad - wR) / strideHeight));
+ var yRMax = Math.min(convInfo.outHeight, (convInfo.inHeight + topPad - wR) / strideHeight);
+ for (var wC = 0; wC < filterWidth; ++wC) {
+ var yCMin = Math.max(0, Math.ceil((leftPad - wC) / strideWidth));
+ var yCMax = Math.min(convInfo.outWidth, (convInfo.inWidth + leftPad - wC) / strideWidth);
+ for (var d1 = 0; d1 < convInfo.inChannels; ++d1) {
+ for (var d2 = 0; d2 < convInfo.outChannels; ++d2) {
+ var dotProd = 0;
+ for (var b = 0; b < convInfo.batchSize; ++b) {
+ for (var yR = yRMin; yR < yRMax; ++yR) {
+ var xR = wR + yR * strideHeight - topPad;
+ for (var yC = yCMin; yC < yCMax; ++yC) {
+ var xC = wC + yC * strideWidth - leftPad;
+ if (isChannelsLast) {
+ dotProd += xBuf.get(b, xR, xC, d1) *
+ dyBuf.get(b, yR, yC, d2);
+ }
+ else {
+ dotProd += xBuf.get(b, d1, xR, xC) *
+ dyBuf.get(b, d2, yR, yC);
+ }
+ }
+ }
+ }
+ dW.set(dotProd, wR, wC, d1, d2);
+ }
+ }
+ }
+ }
+ return backend.makeTensorInfo(dW.shape, dW.dtype, dW.values);
+ }
+ var conv2DBackpropFilterConfig = {
+ kernelName: tfjsCore.Conv2DBackpropFilter,
+ backendName: 'cpu',
+ kernelFunc: conv2DBackpropFilter
+ };
+
+ function conv2DBackpropInput(args) {
+ var inputs = args.inputs, backend = args.backend, attrs = args.attrs;
+ var dy = inputs.dy, filter = inputs.filter;
+ var inputShape = attrs.inputShape, strides = attrs.strides, pad = attrs.pad, dataFormat = attrs.dataFormat, dimRoundingMode = attrs.dimRoundingMode;
+ assertNotComplex([dy, filter], 'conv2dBackpropInput');
+ var filterStrides = tfjsCore.util.computeStrides(filter.shape);
+ var dyStrides = tfjsCore.util.computeStrides(dy.shape);
+ var $dataFormat = tfjsCore.backend_util.convertConv2DDataFormat(dataFormat);
+ var convInfo = tfjsCore.backend_util.computeConv2DInfo(inputShape, filter.shape, strides, 1 /* dilations */, pad, dimRoundingMode, false, $dataFormat);
+ var dx = new tfjsCore.TensorBuffer(convInfo.inShape, 'float32');
+ var dxValues = dx.values;
+ var dyValues = backend.data.get(dy.dataId).values;
+ var fltValues = backend.data.get(filter.dataId).values;
+ var _a = __read(filterStrides, 3), fltS0 = _a[0], fltS1 = _a[1], fltS2 = _a[2];
+ var batchSize = convInfo.batchSize, filterHeight = convInfo.filterHeight, filterWidth = convInfo.filterWidth, inChannels = convInfo.inChannels, inHeight = convInfo.inHeight, inWidth = convInfo.inWidth, outChannels = convInfo.outChannels, outHeight = convInfo.outHeight, outWidth = convInfo.outWidth, strideHeight = convInfo.strideHeight, strideWidth = convInfo.strideWidth;
+ $dataFormat = convInfo.dataFormat;
+ var topPad = filterHeight - 1 - convInfo.padInfo.top;
+ var leftPad = filterWidth - 1 - convInfo.padInfo.left;
+ var isChannelsLast = $dataFormat === 'channelsLast';
+ var xBatchStride = dx.strides[0];
+ var xRowStride = isChannelsLast ? dx.strides[1] : dx.strides[2];
+ var xColStride = isChannelsLast ? dx.strides[2] : 1;
+ var xChannelStride = isChannelsLast ? 1 : dx.strides[1];
+ var yBatchStride = dyStrides[0];
+ var yRowStride = isChannelsLast ? dyStrides[1] : dyStrides[2];
+ var yColStride = isChannelsLast ? dyStrides[2] : 1;
+ var yChannelStride = isChannelsLast ? 1 : dyStrides[1];
+ for (var b = 0; b < batchSize; ++b) {
+ for (var d1 = 0; d1 < inChannels; ++d1) {
+ for (var xR = 0; xR < inHeight; ++xR) {
+ var xRCorner = xR - topPad;
+ var xRMin = Math.max(0, Math.ceil(xRCorner / strideHeight));
+ var yRMax = Math.min(outHeight, (filterHeight + xRCorner) / strideHeight);
+ for (var xC = 0; xC < inWidth; ++xC) {
+ var xCCorner = xC - leftPad;
+ var xCMin = Math.max(0, Math.ceil(xCCorner / strideWidth));
+ var yCMax = Math.min(outWidth, (filterWidth + xCCorner) / strideWidth);
+ var dotProd = 0;
+ for (var yR = xRMin; yR < yRMax; ++yR) {
+ var wR = yR * strideHeight - xRCorner;
+ for (var yC = xCMin; yC < yCMax; ++yC) {
+ var wC = yC * strideWidth - xCCorner;
+ var dyOffset = yBatchStride * b + yRowStride * yR + yColStride * yC;
+ var fltOffset = fltS0 * (filterHeight - 1 - wR) +
+ fltS1 * (filterWidth - 1 - wC) + fltS2 * d1;
+ for (var d2 = 0; d2 < outChannels; ++d2) {
+ var pixel = dyValues[dyOffset + yChannelStride * d2];
+ var weight = fltValues[fltOffset + d2];
+ dotProd += pixel * weight;
+ }
+ }
+ }
+ var dxOffset = xBatchStride * b + xRowStride * xR +
+ xColStride * xC + xChannelStride * d1;
+ dxValues[dxOffset] = dotProd;
+ }
+ }
+ }
+ }
+ return backend.makeTensorInfo(dx.shape, dx.dtype, dx.values);
+ }
+ var conv2DBackpropInputConfig = {
+ kernelName: tfjsCore.Conv2DBackpropInput,
+ backendName: 'cpu',
+ kernelFunc: conv2DBackpropInput
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ function conv3D(args) {
+ var inputs = args.inputs, backend = args.backend, attrs = args.attrs;
+ var x = inputs.x, filter = inputs.filter;
+ var strides = attrs.strides, pad = attrs.pad, dilations = attrs.dilations;
+ assertNotComplex([x, filter], 'conv3d');
+ var convInfo = tfjsCore.backend_util.computeConv3DInfo(x.shape, filter.shape, strides, dilations, pad);
+ var filterDepth = convInfo.filterDepth, filterHeight = convInfo.filterHeight, filterWidth = convInfo.filterWidth, dilationDepth = convInfo.dilationDepth, dilationHeight = convInfo.dilationHeight, dilationWidth = convInfo.dilationWidth, padInfo = convInfo.padInfo;
+ var padFront = padInfo.front;
+ var padLeft = padInfo.left;
+ var padTop = padInfo.top;
+ var y = new tfjsCore.TensorBuffer(convInfo.outShape, x.dtype);
+ var xVals = backend.data.get(x.dataId).values;
+ var wVals = backend.data.get(filter.dataId).values;
+ var yVals = y.values;
+ var xStrides = tfjsCore.util.computeStrides(x.shape);
+ var filterStrides = tfjsCore.util.computeStrides(filter.shape);
+ for (var b = 0; b < convInfo.batchSize; ++b) {
+ var xOffset1 = b * xStrides[0];
+ var yOffset1 = b * y.strides[0];
+ for (var yF = 0; yF < convInfo.outDepth; ++yF) {
+ var yOffset2 = yOffset1 + yF * y.strides[1];
+ var xFCorner = yF * convInfo.strideDepth - padFront;
+ for (var wF = 0; wF < filterDepth; ++wF) {
+ var xF = xFCorner + wF * dilationDepth;
+ if (xF < 0 || xF >= convInfo.inDepth) {
+ continue;
+ }
+ var wOffset1 = wF * filterStrides[0];
+ var xOffset2 = xOffset1 + xF * xStrides[1];
+ for (var yR = 0; yR < convInfo.outHeight; ++yR) {
+ var yOffset3 = yOffset2 + yR * y.strides[2];
+ var xRCorner = yR * convInfo.strideHeight - padTop;
+ for (var wR = 0; wR < filterHeight; ++wR) {
+ var xR = xRCorner + wR * dilationHeight;
+ if (xR < 0 || xR >= convInfo.inHeight) {
+ continue;
+ }
+ var wOffset2 = wOffset1 + wR * filterStrides[1];
+ var xOffset3 = xOffset2 + xR * xStrides[2];
+ for (var yC = 0; yC < convInfo.outWidth; ++yC) {
+ var yOffset4 = yOffset3 + yC * convInfo.outChannels;
+ var xCCorner = yC * convInfo.strideWidth - padLeft;
+ for (var wC = 0; wC < filterWidth; ++wC) {
+ var xC = xCCorner + wC * dilationWidth;
+ if (xC < 0 || xC >= convInfo.inWidth) {
+ continue;
+ }
+ var wOffset3 = wOffset2 + wC * filterStrides[2];
+ var xOffset4 = xOffset3 + xC * convInfo.inChannels;
+ var wOffset4 = wOffset3;
+ for (var d1 = 0; d1 < convInfo.inChannels; ++d1) {
+ var xVal = xVals[xOffset4 + d1];
+ for (var d2 = 0; d2 < convInfo.outChannels; ++d2) {
+ yVals[yOffset4 + d2] += xVal * wVals[wOffset4 + d2];
+ }
+ wOffset4 += convInfo.outChannels;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return backend.makeTensorInfo(y.shape, y.dtype, y.values);
+ }
+ var conv3DConfig = {
+ kernelName: tfjsCore.Conv3D,
+ backendName: 'cpu',
+ kernelFunc: conv3D
+ };
+
+ function conv3DBackpropFilterV2(args) {
+ var inputs = args.inputs, backend = args.backend, attrs = args.attrs;
+ var x = inputs.x, dy = inputs.dy;
+ var strides = attrs.strides, pad = attrs.pad, filterShape = attrs.filterShape;
+ assertNotComplex([x, dy], 'conv3dBackpropFilterV2');
+ var xStrides = tfjsCore.util.computeStrides(x.shape);
+ var dyStrides = tfjsCore.util.computeStrides(dy.shape);
+ var convInfo = tfjsCore.backend_util.computeConv3DInfo(x.shape, filterShape, strides, 1 /* dilations */, pad);
+ var strideDepth = convInfo.strideDepth;
+ var strideHeight = convInfo.strideHeight;
+ var strideWidth = convInfo.strideWidth;
+ var filterDepth = convInfo.filterDepth;
+ var filterHeight = convInfo.filterHeight;
+ var filterWidth = convInfo.filterWidth;
+ var dw = new tfjsCore.TensorBuffer(convInfo.filterShape, 'float32');
+ var dwValues = dw.values;
+ var _a = __read(dw.strides, 4), dwS0 = _a[0], dwS1 = _a[1], dwS2 = _a[2], dwS3 = _a[3];
+ var dyValues = backend.data.get(dy.dataId).values;
+ var _b = __read(dyStrides, 4), dyS0 = _b[0], dyS1 = _b[1], dyS2 = _b[2], dyS3 = _b[3];
+ var xValues = backend.data.get(x.dataId).values;
+ var _c = __read(xStrides, 4), xS0 = _c[0], xS1 = _c[1], xS2 = _c[2], xS3 = _c[3];
+ var frontPad = convInfo.padInfo.front;
+ var leftPad = convInfo.padInfo.left;
+ var topPad = convInfo.padInfo.top;
+ for (var wF = 0; wF < filterDepth; ++wF) {
+ var yFMin = Math.max(0, Math.ceil((frontPad - wF) / strideDepth));
+ var yFMax = Math.min(convInfo.outDepth, (convInfo.inDepth + frontPad - wF) / strideDepth);
+ var wOffset1 = wF * dwS0;
+ for (var wR = 0; wR < filterHeight; ++wR) {
+ var yRMin = Math.max(0, Math.ceil((topPad - wR) / strideHeight));
+ var yRMax = Math.min(convInfo.outHeight, (convInfo.inHeight + topPad - wR) / strideHeight);
+ var wOffset2 = wR * dwS1 + wOffset1;
+ for (var wC = 0; wC < filterWidth; ++wC) {
+ var yCMin = Math.max(0, Math.ceil((leftPad - wC) / strideWidth));
+ var yCMax = Math.min(convInfo.outWidth, (convInfo.inWidth + leftPad - wC) / strideWidth);
+ var wOffset3 = wC * dwS2 + wOffset2;
+ for (var d1 = 0; d1 < convInfo.inChannels; ++d1) {
+ var wOffset4 = d1 * dwS3 + wOffset3;
+ for (var d2 = 0; d2 < convInfo.outChannels; ++d2) {
+ var dotProd = 0;
+ for (var b = 0; b < convInfo.batchSize; ++b) {
+ var xOffset1 = b * xS0;
+ var yOffset1 = b * dyS0;
+ for (var yF = yFMin; yF < yFMax; ++yF) {
+ var xF = wF + yF * strideDepth - frontPad;
+ var xOffset2 = xF * xS1 + xOffset1;
+ var yOffset2 = yF * dyS1 + yOffset1;
+ for (var yR = yRMin; yR < yRMax; ++yR) {
+ var xR = wR + yR * strideHeight - topPad;
+ var xOffset3 = xR * xS2 + xOffset2;
+ var yOffset3 = yR * dyS2 + yOffset2;
+ for (var yC = yCMin; yC < yCMax; ++yC) {
+ var xC = wC + yC * strideWidth - leftPad;
+ var xOffset4 = xC * xS3 + xOffset3;
+ var yOffset4 = yC * dyS3 + yOffset3;
+ dotProd += xValues[xOffset4 + d1] * dyValues[yOffset4 + d2];
+ }
+ }
+ }
+ }
+ dwValues[wOffset4 + d2] = dotProd;
+ }
+ }
+ }
+ }
+ }
+ return backend.makeTensorInfo(dw.shape, dw.dtype, dw.values);
+ }
+ var conv3DBackpropFilterV2Config = {
+ kernelName: tfjsCore.Conv3DBackpropFilterV2,
+ backendName: 'cpu',
+ kernelFunc: conv3DBackpropFilterV2
+ };
+
+ function conv3DBackpropInputV2(args) {
+ var inputs = args.inputs, backend = args.backend, attrs = args.attrs;
+ var dy = inputs.dy, filter = inputs.filter;
+ var pad = attrs.pad, strides = attrs.strides, inputShape = attrs.inputShape;
+ assertNotComplex([dy], 'conv3dBackpropInputV2');
+ var dyStrides = tfjsCore.util.computeStrides(dy.shape);
+ var filterStrides = tfjsCore.util.computeStrides(filter.shape);
+ var convInfo = tfjsCore.backend_util.computeConv3DInfo(inputShape, filter.shape, strides, 1 /* dilations */, pad);
+ var dx = new tfjsCore.TensorBuffer(convInfo.inShape, 'float32');
+ var dxValues = dx.values;
+ var _a = __read(dx.strides, 4), dxS0 = _a[0], dxS1 = _a[1], dxS2 = _a[2], dxS3 = _a[3];
+ var dyValues = backend.data.get(dy.dataId).values;
+ var _b = __read(dyStrides, 4), dyS0 = _b[0], dyS1 = _b[1], dyS2 = _b[2], dyS3 = _b[3];
+ var fltValues = backend.data.get(filter.dataId).values;
+ var _c = __read(filterStrides, 4), fltS0 = _c[0], fltS1 = _c[1], fltS2 = _c[2], fltS3 = _c[3];
+ var batchSize = convInfo.batchSize, filterDepth = convInfo.filterDepth, filterHeight = convInfo.filterHeight, filterWidth = convInfo.filterWidth, inChannels = convInfo.inChannels, inDepth = convInfo.inDepth, inHeight = convInfo.inHeight, inWidth = convInfo.inWidth, outChannels = convInfo.outChannels, outDepth = convInfo.outDepth, outHeight = convInfo.outHeight, outWidth = convInfo.outWidth, strideDepth = convInfo.strideDepth, strideHeight = convInfo.strideHeight, strideWidth = convInfo.strideWidth;
+ var frontPad = filterDepth - 1 - convInfo.padInfo.front;
+ var topPad = filterHeight - 1 - convInfo.padInfo.top;
+ var leftPad = filterWidth - 1 - convInfo.padInfo.left;
+ for (var b = 0; b < batchSize; ++b) {
+ for (var d1 = 0; d1 < inChannels; ++d1) {
+ // Frames of depth
+ for (var xF = 0; xF < inDepth; ++xF) {
+ var xFCorner = xF - frontPad;
+ var xFMin = Math.max(0, Math.ceil(xFCorner / strideDepth));
+ var yFMax = Math.min(outDepth, (filterDepth + xFCorner) / strideDepth);
+ // Rows as per standard 2d matrix notation
+ for (var xR = 0; xR < inHeight; ++xR) {
+ var xRCorner = xR - topPad;
+ var xRMin = Math.max(0, Math.ceil(xRCorner / strideHeight));
+ var yRMax = Math.min(outHeight, (filterHeight + xRCorner) / strideHeight);
+ // Columns as per standard 2d matrix notation
+ for (var xC = 0; xC < inWidth; ++xC) {
+ var xCCorner = xC - leftPad;
+ var xCMin = Math.max(0, Math.ceil(xCCorner / strideWidth));
+ var yCMax = Math.min(outWidth, (filterWidth + xCCorner) / strideWidth);
+ var dotProd = 0;
+ for (var yF = xFMin; yF < yFMax; ++yF) {
+ var wF = yF * strideDepth - xFCorner;
+ for (var yR = xRMin; yR < yRMax; ++yR) {
+ var wR = yR * strideHeight - xRCorner;
+ for (var yC = xCMin; yC < yCMax; ++yC) {
+ var wC = yC * strideWidth - xCCorner;
+ var dyOffset = dyS0 * b + dyS1 * yF + dyS2 * yR + dyS3 * yC;
+ var fltOffset = fltS0 * (filterDepth - 1 - wF) +
+ fltS1 * (filterHeight - 1 - wR) +
+ fltS2 * (filterWidth - 1 - wC) + fltS3 * d1;
+ for (var d2 = 0; d2 < outChannels; ++d2) {
+ var pixel = dyValues[dyOffset + d2];
+ var weight = fltValues[fltOffset + d2];
+ dotProd += pixel * weight;
+ }
+ }
+ }
+ }
+ dxValues[dxS0 * b + dxS1 * xF + dxS2 * xR + dxS3 * xC + d1] =
+ dotProd;
+ }
+ }
+ }
+ }
+ }
+ return backend.makeTensorInfo(dx.shape, dx.dtype, dx.values);
+ }
+ var conv3DBackpropInputV2Config = {
+ kernelName: tfjsCore.Conv3DBackpropInputV2,
+ backendName: 'cpu',
+ kernelFunc: conv3DBackpropInputV2
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ var cos = unaryKernelFunc(tfjsCore.Cos, function (xi) { return Math.cos(xi); });
+ var cosConfig = {
+ kernelName: tfjsCore.Cos,
+ backendName: 'cpu',
+ kernelFunc: cos,
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ var cosh = unaryKernelFunc(tfjsCore.Cosh, function (xi) { return Math.cosh(xi); });
+ var coshConfig = {
+ kernelName: tfjsCore.Cosh,
+ backendName: 'cpu',
+ kernelFunc: cosh,
+ };
+
+ function cropAndResize(args) {
+ var inputs = args.inputs, backend = args.backend, attrs = args.attrs;
+ var image = inputs.image, boxes = inputs.boxes, boxInd = inputs.boxInd;
+ var cropSize = attrs.cropSize, method = attrs.method, extrapolationValue = attrs.extrapolationValue;
+ var _a = __read(image.shape, 4), batch = _a[0], imageHeight = _a[1], imageWidth = _a[2], numChannels = _a[3];
+ var numBoxes = boxes.shape[0];
+ var _b = __read(cropSize, 2), cropHeight = _b[0], cropWidth = _b[1];
+ var output = tfjsCore.buffer([numBoxes, cropHeight, cropWidth, numChannels], 'float32');
+ var boxVals = backend.data.get(boxes.dataId).values;
+ var boxIndVals = backend.data.get(boxInd.dataId).values;
+ var imageVals = backend.data.get(image.dataId).values;
+ var inStride = tfjsCore.util.computeStrides(image.shape); // to calculate flat indexes into image
+ var outStride = tfjsCore.util.computeStrides(output.shape); // to calculate flat indexes into output
+ // Reference implementation
+ // tslint:disable-next-line:max-line-length
+ // https://github.com/tensorflow/tensorflow/blob/master/tensorflow/core/kernels/crop_and_resize_op.cc
+ for (var b = 0; b < numBoxes; b++) {
+ var startInd = b * 4;
+ var y1 = boxVals[startInd];
+ var x1 = boxVals[startInd + 1];
+ var y2 = boxVals[startInd + 2];
+ var x2 = boxVals[startInd + 3];
+ var bInd = boxIndVals[b];
+ if (bInd >= batch) {
+ continue;
+ }
+ var heightScale = (cropHeight > 1) ? (y2 - y1) * (imageHeight - 1) / (cropHeight - 1) : 0;
+ var widthScale = (cropWidth > 1) ? (x2 - x1) * (imageWidth - 1) / (cropWidth - 1) : 0;
+ for (var y = 0; y < cropHeight; y++) {
+ var yInd = (cropHeight > 1) ?
+ y1 * (imageHeight - 1) + y * (heightScale) :
+ 0.5 * (y1 + y2) * (imageHeight - 1);
+ if (yInd < 0 || yInd > imageHeight - 1) {
+ for (var x = 0; x < cropWidth; x++) {
+ for (var c = 0; c < numChannels; c++) {
+ var ind = c + x * outStride[2] + y * outStride[1] + b * outStride[0];
+ output.values[ind] = extrapolationValue;
+ }
+ }
+ continue;
+ }
+ if (method === 'bilinear') {
+ var topInd = Math.floor(yInd);
+ var bottomInd = Math.ceil(yInd);
+ var yLerp = yInd - topInd;
+ for (var x = 0; x < cropWidth; x++) {
+ var xInd = (cropWidth > 1) ?
+ x1 * (imageWidth - 1) + x * widthScale :
+ 0.5 * (x1 + x2) * (imageWidth - 1);
+ if (xInd < 0 || xInd > imageWidth - 1) {
+ for (var c = 0; c < numChannels; c++) {
+ var ind = c + x * outStride[2] + y * outStride[1] + b * outStride[0];
+ output.values[ind] = extrapolationValue;
+ }
+ continue;
+ }
+ var leftInd = Math.floor(xInd);
+ var rightInd = Math.ceil(xInd);
+ var xLerp = xInd - leftInd;
+ for (var c = 0; c < numChannels; c++) {
+ var ind = c + leftInd * inStride[2] + topInd * inStride[1] +
+ bInd * inStride[0];
+ var topLeft = imageVals[ind];
+ ind = c + rightInd * inStride[2] + topInd * inStride[1] +
+ bInd * inStride[0];
+ var topRight = imageVals[ind];
+ ind = c + leftInd * inStride[2] + bottomInd * inStride[1] +
+ bInd * inStride[0];
+ var bottomLeft = imageVals[ind];
+ ind = c + rightInd * inStride[2] + bottomInd * inStride[1] +
+ bInd * inStride[0];
+ var bottomRight = imageVals[ind];
+ var top = topLeft + (topRight - topLeft) * xLerp;
+ var bottom = bottomLeft + (bottomRight - bottomLeft) * xLerp;
+ ind = c + x * outStride[2] + y * outStride[1] + b * outStride[0];
+ output.values[ind] = top + ((bottom - top) * yLerp);
+ }
+ }
+ }
+ else { // method == "nearest"
+ for (var x = 0; x < cropWidth; ++x) {
+ var xInd = (cropWidth > 1) ?
+ x1 * (imageWidth - 1) + x * widthScale :
+ 0.5 * (x1 + x2) * (imageWidth - 1);
+ if (xInd < 0 || xInd > imageWidth - 1) {
+ for (var c = 0; c < numChannels; c++) {
+ var ind = c + x * outStride[2] + y * outStride[1] + b * outStride[0];
+ output.values[ind] = extrapolationValue;
+ }
+ continue;
+ }
+ var closestX = Math.round(xInd);
+ var closestY = Math.round(yInd);
+ for (var c = 0; c < numChannels; c++) {
+ var inInd = c + closestX * inStride[2] + closestY * inStride[1] +
+ bInd * inStride[0];
+ var outInd = c + x * outStride[2] + y * outStride[1] + b * outStride[0];
+ output.values[outInd] = imageVals[inInd];
+ }
+ }
+ }
+ }
+ }
+ return backend.makeTensorInfo(output.shape, output.dtype, output.values);
+ }
+ var cropAndResizeConfig = {
+ kernelName: tfjsCore.CropAndResize,
+ backendName: 'cpu',
+ kernelFunc: cropAndResize
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ function cumsum(args) {
+ var inputs = args.inputs, backend = args.backend, attrs = args.attrs;
+ var x = inputs.x;
+ var axis = attrs.axis, exclusive = attrs.exclusive, reverse = attrs.reverse;
+ assertNotComplex(x, 'cumsum');
+ var permutation = tfjsCore.backend_util.getAxesPermutation([axis], x.shape.length);
+ var $x = x;
+ if (permutation != null) {
+ $x = transpose({ inputs: { x: x }, backend: backend, attrs: { perm: permutation } });
+ }
+ var permutedAxis = tfjsCore.backend_util.getInnerMostAxes(1, x.shape.length)[0];
+ if (permutedAxis !== $x.shape.length - 1) {
+ throw new Error("backend.cumsum in CPU expects an inner-most " +
+ ("axis=" + ($x.shape.length - 1) + " but got axis=" + permutedAxis));
+ }
+ var resultDtype = tfjsCore.upcastType($x.dtype, 'int32');
+ var vals = tfjsCore.util.makeZerosTypedArray(tfjsCore.util.sizeFromShape($x.shape), resultDtype);
+ var aVals = backend.data.get($x.dataId).values;
+ var finalDim = $x.shape[$x.shape.length - 1];
+ var indexAdjuster = reverse ?
+ function (i, j) { return i + finalDim - j - 1; } :
+ function (i, j) { return i + j; };
+ for (var i = 0; i < aVals.length; i += finalDim) {
+ for (var j = 0; j < finalDim; j++) {
+ var idx = indexAdjuster(i, j);
+ if (j === 0) {
+ vals[idx] = exclusive ? 0 : aVals[idx];
+ }
+ else {
+ var prevIdx = indexAdjuster(i, j - 1);
+ vals[idx] = exclusive ? aVals[prevIdx] + vals[prevIdx] :
+ aVals[idx] + vals[prevIdx];
+ }
+ }
+ }
+ var result = backend.makeTensorInfo($x.shape, resultDtype, vals);
+ if (permutation != null) {
+ var reversePermutation = tfjsCore.backend_util.getUndoAxesPermutation(permutation);
+ var reverseTransposedResult = transpose({ inputs: { x: result }, backend: backend, attrs: { perm: reversePermutation } });
+ backend.disposeIntermediateTensorInfo(result);
+ backend.disposeIntermediateTensorInfo($x);
+ return reverseTransposedResult;
+ }
+ return result;
+ }
+ var cumsumConfig = {
+ kernelName: tfjsCore.Cumsum,
+ backendName: 'cpu',
+ kernelFunc: cumsum
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ function denseBincount(args) {
+ var inputs = args.inputs, backend = args.backend, attrs = args.attrs;
+ var x = inputs.x, weights = inputs.weights;
+ var size = attrs.size, binaryOutput = attrs.binaryOutput;
+ if (x.shape.length === 1) {
+ var xVals = backend.data.get(x.dataId).values;
+ var weightsVals = backend.data.get(weights.dataId).values;
+ var outVals = bincountImpl(xVals, weightsVals, weights.dtype, weights.shape, size);
+ return backend.makeTensorInfo([size], weights.dtype, outVals);
+ }
+ else if (x.shape.length === 2) {
+ var xBuf = backend.bufferSync(x);
+ var weightsBuf = backend.bufferSync(weights);
+ var outBuf = bincountReduceImpl(xBuf, weightsBuf, size, binaryOutput);
+ return backend.makeTensorInfo(outBuf.shape, weights.dtype, outBuf.values);
+ }
+ throw new Error("Error in denseBincount: input must be at most rank 2, but got rank" +
+ (x.shape.length + "."));
+ }
+ var denseBincountConfig = {
+ kernelName: tfjsCore.DenseBincount,
+ backendName: 'cpu',
+ kernelFunc: denseBincount
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ function depthToSpace(args) {
+ var inputs = args.inputs, backend = args.backend, attrs = args.attrs;
+ var x = inputs.x;
+ var blockSize = attrs.blockSize, dataFormat = attrs.dataFormat;
+ tfjsCore.util.assert(dataFormat === 'NHWC', function () { return "Only NHWC dataFormat supported on CPU for depthToSpace. Got " + dataFormat; });
+ var batchSize = x.shape[0];
+ var inputHeight = x.shape[1];
+ var inputWidth = x.shape[2];
+ var inputDepth = x.shape[3];
+ var outputHeight = inputHeight * blockSize;
+ var outputWidth = inputWidth * blockSize;
+ var outputDepth = inputDepth / (blockSize * blockSize);
+ var xValues = backend.data.get(x.dataId).values;
+ var result = new Float32Array(batchSize * outputHeight * outputWidth * outputDepth);
+ var outputIdx = 0;
+ for (var b = 0; b < batchSize; ++b) {
+ for (var h = 0; h < outputHeight; ++h) {
+ var inH = Math.floor(h / blockSize);
+ var offsetH = (h % blockSize);
+ for (var w = 0; w < outputWidth; ++w) {
+ var inW = Math.floor(w / blockSize);
+ var offsetW = (w % blockSize);
+ var offsetD = (offsetH * blockSize + offsetW) * outputDepth;
+ for (var d = 0; d < outputDepth; ++d) {
+ var inD = d + offsetD;
+ var inputIdx = inD + inputDepth * (inW + inputWidth * (inH + inputHeight * b));
+ result[outputIdx++] = xValues[inputIdx];
+ }
+ }
+ }
+ }
+ return backend.makeTensorInfo([batchSize, outputHeight, outputWidth, outputDepth], x.dtype, result);
+ }
+ var depthToSpaceConfig = {
+ kernelName: tfjsCore.DepthToSpace,
+ backendName: 'cpu',
+ kernelFunc: depthToSpace
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ function depthwiseConv2dNative(args) {
+ var inputs = args.inputs, backend = args.backend, attrs = args.attrs;
+ var x = inputs.x, filter = inputs.filter;
+ var strides = attrs.strides, pad = attrs.pad, dilations = attrs.dilations, dimRoundingMode = attrs.dimRoundingMode;
+ assertNotComplex([x, filter], 'depthwiseConv2DNative');
+ var xStrides = tfjsCore.util.computeStrides(x.shape);
+ var filterStrides = tfjsCore.util.computeStrides(filter.shape);
+ var $dilations = dilations;
+ if ($dilations == null) {
+ $dilations = [1, 1];
+ }
+ tfjsCore.util.assert(tfjsCore.backend_util.eitherStridesOrDilationsAreOne(strides, $dilations), function () { return 'Error in depthwiseConv2d: Either strides or dilations must be ' +
+ ("1. Got strides " + strides + " and dilations '" + $dilations + "'"); });
+ var convInfo = tfjsCore.backend_util.computeConv2DInfo(x.shape, filter.shape, strides, $dilations, pad, dimRoundingMode, true /* depthwise */);
+ var filterHeight = convInfo.filterHeight, filterWidth = convInfo.filterWidth, dilationHeight = convInfo.dilationHeight, dilationWidth = convInfo.dilationWidth, padInfo = convInfo.padInfo;
+ var padLeft = padInfo.left;
+ var padTop = padInfo.top;
+ var chMul = convInfo.outChannels / convInfo.inChannels;
+ var y = new tfjsCore.TensorBuffer(convInfo.outShape, x.dtype);
+ var xVals = backend.data.get(x.dataId).values;
+ var wVals = backend.data.get(filter.dataId).values;
+ var yVals = y.values;
+ for (var b = 0; b < convInfo.batchSize; ++b) {
+ var xOffset1 = b * xStrides[0];
+ var yOffset1 = b * y.strides[0];
+ for (var yR = 0; yR < convInfo.outHeight; ++yR) {
+ var yOffset2 = yOffset1 + yR * y.strides[1];
+ var xRCorner = yR * convInfo.strideHeight - padTop;
+ for (var wR = 0; wR < filterHeight; ++wR) {
+ var xR = xRCorner + wR * dilationHeight;
+ if (xR < 0 || xR >= convInfo.inHeight) {
+ continue;
+ }
+ var wOffset1 = wR * filterStrides[0];
+ var xOffset2 = xOffset1 + xR * xStrides[1];
+ for (var yC = 0; yC < convInfo.outWidth; ++yC) {
+ var yOffset3 = yOffset2 + yC * y.strides[2];
+ var xCCorner = yC * convInfo.strideWidth - padLeft;
+ for (var wC = 0; wC < filterWidth; ++wC) {
+ var xC = xCCorner + wC * dilationWidth;
+ if (xC < 0 || xC >= convInfo.inWidth) {
+ continue;
+ }
+ var wOffset2 = wOffset1 + wC * filterStrides[1];
+ var xOffset3 = xOffset2 + xC * convInfo.inChannels;
+ var yOffset4 = yOffset3;
+ var wOffset3 = wOffset2;
+ for (var d1 = 0; d1 < convInfo.inChannels; ++d1) {
+ var xVal = xVals[xOffset3 + d1];
+ for (var q = 0; q < chMul; ++q) {
+ yVals[yOffset4 + q] += xVal * wVals[wOffset3 + q];
+ }
+ yOffset4 += chMul;
+ wOffset3 += chMul;
+ }
+ }
+ }
+ }
+ }
+ }
+ return backend.makeTensorInfo(y.shape, y.dtype, y.values);
+ }
+ var depthwiseConv2dNativeConfig = {
+ kernelName: tfjsCore.DepthwiseConv2dNative,
+ backendName: 'cpu',
+ kernelFunc: depthwiseConv2dNative
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ function depthwiseConv2dNativeBackpropFilter(args) {
+ var inputs = args.inputs, backend = args.backend, attrs = args.attrs;
+ var x = inputs.x, dy = inputs.dy;
+ var strides = attrs.strides, dilations = attrs.dilations, pad = attrs.pad, dimRoundingMode = attrs.dimRoundingMode, filterShape = attrs.filterShape;
+ assertNotComplex([x, dy], 'depthwiseConv2dNativeBackpropFilter');
+ var convInfo = tfjsCore.backend_util.computeConv2DInfo(x.shape, filterShape, strides, dilations, pad, dimRoundingMode, true /* depthwise */);
+ var strideHeight = convInfo.strideHeight, strideWidth = convInfo.strideWidth, filterHeight = convInfo.filterHeight, filterWidth = convInfo.filterWidth;
+ var dW = new tfjsCore.TensorBuffer(convInfo.filterShape, 'float32');
+ var leftPad = convInfo.padInfo.left;
+ var topPad = convInfo.padInfo.top;
+ var chMul = convInfo.outChannels / convInfo.inChannels;
+ var xVals = backend.data.get(x.dataId).values;
+ var xBuf = new tfjsCore.TensorBuffer(x.shape, x.dtype, xVals);
+ var dyVals = backend.data.get(dy.dataId).values;
+ var dyBuf = new tfjsCore.TensorBuffer(dy.shape, dy.dtype, dyVals);
+ for (var wR = 0; wR < filterHeight; ++wR) {
+ var yRMin = Math.max(0, Math.ceil((topPad - wR) / strideHeight));
+ var yRMax = Math.min(convInfo.outHeight, (convInfo.inHeight + topPad - wR) / strideHeight);
+ for (var wC = 0; wC < filterWidth; ++wC) {
+ var yCMin = Math.max(0, Math.ceil((leftPad - wC) / strideWidth));
+ var yCMax = Math.min(convInfo.outWidth, (convInfo.inWidth + leftPad - wC) / strideWidth);
+ for (var d2 = 0; d2 < convInfo.outChannels; ++d2) {
+ var d1 = Math.trunc(d2 / chMul);
+ var dm = d2 % chMul;
+ var dotProd = 0;
+ for (var b = 0; b < convInfo.batchSize; ++b) {
+ for (var yR = yRMin; yR < yRMax; ++yR) {
+ var xR = wR + yR * strideHeight - topPad;
+ for (var yC = yCMin; yC < yCMax; ++yC) {
+ var xC = wC + yC * strideWidth - leftPad;
+ dotProd += xBuf.get(b, xR, xC, d1) *
+ dyBuf.get(b, yR, yC, d2);
+ }
+ }
+ }
+ dW.set(dotProd, wR, wC, d1, dm);
+ }
+ }
+ }
+ return backend.makeTensorInfo(dW.shape, dW.dtype, dW.values);
+ }
+ var depthwiseConv2dNativeBackpropFilterConfig = {
+ kernelName: tfjsCore.DepthwiseConv2dNativeBackpropFilter,
+ backendName: 'cpu',
+ kernelFunc: depthwiseConv2dNativeBackpropFilter
+ };
+
+ function depthwiseConv2dNativeBackpropInput(args) {
+ var inputs = args.inputs, backend = args.backend, attrs = args.attrs;
+ var dy = inputs.dy, filter = inputs.filter;
+ var strides = attrs.strides, dilations = attrs.dilations, pad = attrs.pad, dimRoundingMode = attrs.dimRoundingMode, inputShape = attrs.inputShape;
+ assertNotComplex([dy, filter], 'depthwiseConv2DNativeBackpropInput');
+ var dyStrides = tfjsCore.util.computeStrides(dy.shape);
+ var filterStrides = tfjsCore.util.computeStrides(filter.shape);
+ var convInfo = tfjsCore.backend_util.computeConv2DInfo(inputShape, filter.shape, strides, dilations, pad, dimRoundingMode, true /* depthwise */);
+ var dx = new tfjsCore.TensorBuffer(convInfo.inShape, 'float32');
+ var dxValues = dx.values;
+ var _a = __read(dx.strides, 3), dxS0 = _a[0], dxS1 = _a[1], dxS2 = _a[2];
+ var dyValues = backend.data.get(dy.dataId).values;
+ var _b = __read(dyStrides, 3), dyS0 = _b[0], dyS1 = _b[1], dyS2 = _b[2];
+ var fltValues = backend.data.get(filter.dataId).values;
+ var _c = __read(filterStrides, 3), fltS0 = _c[0], fltS1 = _c[1], fltS2 = _c[2];
+ var batchSize = convInfo.batchSize, filterHeight = convInfo.filterHeight, filterWidth = convInfo.filterWidth, inChannels = convInfo.inChannels, inHeight = convInfo.inHeight, inWidth = convInfo.inWidth, outChannels = convInfo.outChannels, outHeight = convInfo.outHeight, outWidth = convInfo.outWidth, strideHeight = convInfo.strideHeight, strideWidth = convInfo.strideWidth;
+ var topPad = filterHeight - 1 - convInfo.padInfo.top;
+ var leftPad = filterWidth - 1 - convInfo.padInfo.left;
+ var chMul = outChannels / inChannels;
+ for (var b = 0; b < batchSize; ++b) {
+ for (var d1 = 0; d1 < inChannels; ++d1) {
+ for (var xR = 0; xR < inHeight; ++xR) {
+ var xRCorner = xR - topPad;
+ var xRMin = Math.max(0, Math.ceil(xRCorner / strideHeight));
+ var yRMax = Math.min(outHeight, (filterHeight + xRCorner) / strideHeight);
+ for (var xC = 0; xC < inWidth; ++xC) {
+ var xCCorner = xC - leftPad;
+ var xCMin = Math.max(0, Math.ceil(xCCorner / strideWidth));
+ var yCMax = Math.min(outWidth, (filterWidth + xCCorner) / strideWidth);
+ var dotProd = 0;
+ for (var yR = xRMin; yR < yRMax; ++yR) {
+ var wR = yR * strideHeight - xRCorner;
+ for (var yC = xCMin; yC < yCMax; ++yC) {
+ var wC = yC * strideWidth - xCCorner;
+ var dyOffset = dyS0 * b + dyS1 * yR + dyS2 * yC;
+ var fltOffset = fltS0 * (filterHeight - 1 - wR) +
+ fltS1 * (filterWidth - 1 - wC) + fltS2 * d1;
+ for (var dm = 0; dm < chMul; ++dm) {
+ var d2 = d1 * chMul + dm;
+ var pixel = dyValues[dyOffset + d2];
+ var weight = fltValues[fltOffset + dm];
+ dotProd += pixel * weight;
+ }
+ }
+ }
+ dxValues[dxS0 * b + dxS1 * xR + dxS2 * xC + d1] = dotProd;
+ }
+ }
+ }
+ }
+ return backend.makeTensorInfo(dx.shape, dx.dtype, dx.values);
+ }
+ var depthwiseConv2dNativeBackpropInputConfig = {
+ kernelName: tfjsCore.DepthwiseConv2dNativeBackpropInput,
+ backendName: 'cpu',
+ kernelFunc: depthwiseConv2dNativeBackpropInput
+ };
+
+ function diag(args) {
+ var inputs = args.inputs, backend = args.backend;
+ var x = inputs.x;
+ var xSize = tfjsCore.util.sizeFromShape(x.shape);
+ var xVals = backend.data.get(x.dataId).values;
+ var outBuf = tfjsCore.buffer([xSize, xSize], x.dtype);
+ var vals = outBuf.values;
+ for (var i = 0; i < xVals.length; i++) {
+ vals[i * xSize + i] = xVals[i];
+ }
+ var outShape = __spread(x.shape, x.shape);
+ return backend.makeTensorInfo(outShape, outBuf.dtype, outBuf.values);
+ }
+ var diagConfig = {
+ kernelName: tfjsCore.Diag,
+ backendName: 'cpu',
+ kernelFunc: diag
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ var dilation2dConfig = {
+ kernelName: tfjsCore.Dilation2D,
+ backendName: 'cpu',
+ kernelFunc: function (_a) {
+ var inputs = _a.inputs, backend = _a.backend, attrs = _a.attrs;
+ var x = inputs.x, filter = inputs.filter;
+ var strides = attrs.strides, pad = attrs.pad, dilations = attrs.dilations;
+ var cpuBackend = backend;
+ var xVals = cpuBackend.data.get(x.dataId).values;
+ var xRank = x.shape.length;
+ var filterVals = cpuBackend.data.get(filter.dataId).values;
+ var filterRank = filter.shape.length;
+ var _b = tfjsCore.backend_util.computeDilation2DInfo(x.shape, filter.shape, strides, pad, 'NHWC' /* dataFormat */, dilations), batchSize = _b.batchSize, inHeight = _b.inHeight, inWidth = _b.inWidth, inChannels = _b.inChannels, outHeight = _b.outHeight, outWidth = _b.outWidth, padInfo = _b.padInfo, strideHeight = _b.strideHeight, strideWidth = _b.strideWidth, filterHeight = _b.filterHeight, filterWidth = _b.filterWidth, dilationHeight = _b.dilationHeight, dilationWidth = _b.dilationWidth, outShape = _b.outShape;
+ var outSize = tfjsCore.util.sizeFromShape(outShape);
+ var outRank = outShape.length;
+ var outputVals = tfjsCore.util.getArrayFromDType(x.dtype, outSize);
+ // Upsampling the input by fill in `dilation size - 1` values between each
+ // input value.
+ // This implementation follows the TF c++ implementation:
+ // https://github.com/tensorflow/tensorflow/blob/d9a3a849edc198e90172bc58eb293de457f9d986/tensorflow/core/kernels/dilation_ops.cc
+ for (var b = 0; b < batchSize; ++b) {
+ for (var hOut = 0; hOut < outHeight; ++hOut) {
+ var hBeg = hOut * strideHeight - padInfo.top;
+ for (var wOut = 0; wOut < outWidth; ++wOut) {
+ var wBeg = wOut * strideWidth - padInfo.left;
+ for (var d = 0; d < inChannels; ++d) {
+ var curVal = Number.MIN_SAFE_INTEGER;
+ for (var h = 0; h < filterHeight; ++h) {
+ var hIn = hBeg + h * dilationHeight;
+ if (hIn >= 0 && hIn < inHeight) {
+ for (var w = 0; w < filterWidth; ++w) {
+ var wIn = wBeg + w * dilationWidth;
+ if (wIn >= 0 && wIn < inWidth) {
+ var xIndex = tfjsCore.util.locToIndex([b, hIn, wIn, d], xRank, tfjsCore.util.computeStrides(x.shape));
+ var filterIndex = tfjsCore.util.locToIndex([h, w, d], filterRank, tfjsCore.util.computeStrides(filter.shape));
+ var val = xVals[xIndex] + filterVals[filterIndex];
+ if (val > curVal) {
+ curVal = val;
+ }
+ }
+ }
+ }
+ }
+ var outputIndex = tfjsCore.util.locToIndex([b, hOut, wOut, d], outRank, tfjsCore.util.computeStrides(outShape));
+ outputVals[outputIndex] = curVal;
+ }
+ }
+ }
+ }
+ var dataId = cpuBackend.write(tfjsCore.util.toTypedArray(outputVals, x.dtype), outShape, x.dtype);
+ return { dataId: dataId, shape: outShape, dtype: x.dtype };
+ }
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ var dilation2dBackpropFilterConfig = {
+ kernelName: tfjsCore.Dilation2DBackpropFilter,
+ backendName: 'cpu',
+ kernelFunc: function (_a) {
+ var inputs = _a.inputs, backend = _a.backend, attrs = _a.attrs;
+ var x = inputs.x, filter = inputs.filter, dy = inputs.dy;
+ var strides = attrs.strides, pad = attrs.pad, dilations = attrs.dilations;
+ var cpuBackend = backend;
+ var $x = tfjsCore.util.toNestedArray(x.shape, cpuBackend.data.get(x.dataId).values);
+ var $filter = tfjsCore.util.toNestedArray(filter.shape, cpuBackend.data.get(filter.dataId).values);
+ var _b = tfjsCore.backend_util.computeDilation2DInfo(x.shape, filter.shape, strides, pad, 'NHWC' /* dataFormat */, dilations), batchSize = _b.batchSize, inHeight = _b.inHeight, inWidth = _b.inWidth, inChannels = _b.inChannels, outHeight = _b.outHeight, outWidth = _b.outWidth, padInfo = _b.padInfo, strideHeight = _b.strideHeight, strideWidth = _b.strideWidth, filterHeight = _b.filterHeight, filterWidth = _b.filterWidth, dilationHeight = _b.dilationHeight, dilationWidth = _b.dilationWidth, outShape = _b.outShape;
+ tfjsCore.util.assert(dy.rank === outShape.length, function () { return "Error in " + tfjsCore.Dilation2DBackpropFilter + ", dy " +
+ ("must have the same rank as output " + outShape.length + ", but got ") +
+ ("" + dy.rank); });
+ var $dy = tfjsCore.util.toNestedArray(outShape, cpuBackend.data.get(dy.dataId).values);
+ // The computed filter gradients has the same dimensions as the filter:
+ // [filterHeight, filterWidth, depth]
+ var gradients = tfjsCore.util.makeZerosNestedTypedArray(filter.shape, filter.dtype);
+ // In the case of multiple argmax branches, we only back-propagate along the
+ // last branch, i.e., the one with largest value of `h * filter_cols + w`,
+ // similarly to the max-pooling backward routines.
+ // This implementation follows the TF c++ implementation:
+ // https://github.com/tensorflow/tensorflow/blob/d9a3a849edc198e90172bc58eb293de457f9d986/tensorflow/core/kernels/dilation_ops.cc
+ for (var b = 0; b < batchSize; ++b) {
+ for (var hOut = 0; hOut < outHeight; ++hOut) {
+ var hBeg = hOut * strideHeight - padInfo.top;
+ for (var wOut = 0; wOut < outWidth; ++wOut) {
+ var wBeg = wOut * strideWidth - padInfo.left;
+ for (var d = 0; d < inChannels; ++d) {
+ var curVal = Number.MIN_SAFE_INTEGER;
+ var hMax = 0;
+ var wMax = 0;
+ for (var h = 0; h < filterHeight; ++h) {
+ var hIn = hBeg + h * dilationHeight;
+ if (hIn >= 0 && hIn < inHeight) {
+ for (var w = 0; w < filterWidth; ++w) {
+ var wIn = wBeg + w * dilationWidth;
+ if (wIn >= 0 && wIn < inWidth) {
+ var val = $x[b][hIn][wIn][d] + $filter[h][w][d];
+ if (val > curVal) {
+ curVal = val;
+ hMax = h;
+ wMax = w;
+ }
+ }
+ }
+ }
+ }
+ gradients[hMax][wMax][d] += $dy[b][hOut][wOut][d];
+ }
+ }
+ }
+ }
+ var dataId = cpuBackend.write(tfjsCore.util.toTypedArray(gradients, x.dtype), filter.shape, filter.dtype);
+ return { dataId: dataId, shape: filter.shape, dtype: filter.dtype };
+ }
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ var dilation2dBackpropInputConfig = {
+ kernelName: tfjsCore.Dilation2DBackpropInput,
+ backendName: 'cpu',
+ kernelFunc: function (_a) {
+ var inputs = _a.inputs, backend = _a.backend, attrs = _a.attrs;
+ var x = inputs.x, filter = inputs.filter, dy = inputs.dy;
+ var strides = attrs.strides, pad = attrs.pad, dilations = attrs.dilations;
+ var cpuBackend = backend;
+ var $x = tfjsCore.util.toNestedArray(x.shape, cpuBackend.data.get(x.dataId).values);
+ var $filter = tfjsCore.util.toNestedArray(filter.shape, cpuBackend.data.get(filter.dataId).values);
+ var _b = tfjsCore.backend_util.computeDilation2DInfo(x.shape, filter.shape, strides, pad, 'NHWC' /* dataFormat */, dilations), batchSize = _b.batchSize, inHeight = _b.inHeight, inWidth = _b.inWidth, inChannels = _b.inChannels, outHeight = _b.outHeight, outWidth = _b.outWidth, padInfo = _b.padInfo, strideHeight = _b.strideHeight, strideWidth = _b.strideWidth, filterHeight = _b.filterHeight, filterWidth = _b.filterWidth, dilationHeight = _b.dilationHeight, dilationWidth = _b.dilationWidth, outShape = _b.outShape;
+ tfjsCore.util.assert(dy.rank === outShape.length, function () { return "Error in " + tfjsCore.Dilation2DBackpropInput + ", dy " +
+ ("must have the same rank as output " + outShape.length + ", but got ") +
+ ("" + dy.rank); });
+ var $dy = tfjsCore.util.toNestedArray(outShape, cpuBackend.data.get(dy.dataId).values);
+ // The computed gradients has the same dimensions as the input:
+ // [batch, inputHeight, inputCols, inChannel]
+ var gradients = tfjsCore.util.makeZerosNestedTypedArray(x.shape, x.dtype);
+ // In the case of multiple argmax branches, we only back-propagate along the
+ // last branch, i.e., the one with largest value of `h * filter_cols + w`,
+ // similarly to the max-pooling backward routines.
+ // This implementation follows the TF c++ implementation:
+ // https://github.com/tensorflow/tensorflow/blob/d9a3a849edc198e90172bc58eb293de457f9d986/tensorflow/core/kernels/dilation_ops.cc
+ for (var b = 0; b < batchSize; ++b) {
+ for (var hOut = 0; hOut < outHeight; ++hOut) {
+ var hBeg = hOut * strideHeight - padInfo.top;
+ for (var wOut = 0; wOut < outWidth; ++wOut) {
+ var wBeg = wOut * strideWidth - padInfo.left;
+ for (var d = 0; d < inChannels; ++d) {
+ var curVal = Number.MIN_SAFE_INTEGER;
+ var hInMax = (hBeg < 0) ? 0 : hBeg;
+ var wInMax = (wBeg < 0) ? 0 : wBeg;
+ for (var h = 0; h < filterHeight; ++h) {
+ var hIn = hBeg + h * dilationHeight;
+ if (hIn >= 0 && hIn < inHeight) {
+ for (var w = 0; w < filterWidth; ++w) {
+ var wIn = wBeg + w * dilationWidth;
+ if (wIn >= 0 && wIn < inWidth) {
+ var val = $x[b][hIn][wIn][d] + $filter[h][w][d];
+ if (val > curVal) {
+ curVal = val;
+ hInMax = hIn;
+ wInMax = wIn;
+ }
+ }
+ }
+ }
+ }
+ gradients[b][hInMax][wInMax][d] += $dy[b][hOut][wOut][d];
+ }
+ }
+ }
+ }
+ var dataId = cpuBackend.write(tfjsCore.util.toTypedArray(gradients, x.dtype), x.shape, x.dtype);
+ return { dataId: dataId, shape: x.shape, dtype: x.dtype };
+ }
+ };
+
+ function sum(args) {
+ var inputs = args.inputs, backend = args.backend, attrs = args.attrs;
+ var x = inputs.x;
+ var axis = attrs.axis, keepDims = attrs.keepDims;
+ assertNotComplex(x, 'sum');
+ var $x;
+ if (x.dtype === 'bool') {
+ $x = cast({ inputs: { x: x }, backend: backend, attrs: { dtype: 'int32' } });
+ }
+ else {
+ $x = identity({ inputs: { x: x }, backend: backend });
+ }
+ var xRank = $x.shape.length;
+ var axes = tfjsCore.util.parseAxisParam(axis, $x.shape);
+ var permutation = tfjsCore.backend_util.getAxesPermutation(axes, xRank);
+ var reductionAxes = axes;
+ var permutedX = $x;
+ if (permutation != null) {
+ permutedX =
+ transpose({ inputs: { x: $x }, backend: backend, attrs: { perm: permutation } });
+ reductionAxes = tfjsCore.backend_util.getInnerMostAxes(reductionAxes.length, xRank);
+ }
+ tfjsCore.backend_util.assertAxesAreInnerMostDims('sum', reductionAxes, permutedX.shape.length);
+ var _a = __read(tfjsCore.backend_util.computeOutAndReduceShapes(permutedX.shape, reductionAxes), 2), outShape = _a[0], reduceShape = _a[1];
+ var resultDtype = tfjsCore.backend_util.upcastType(permutedX.dtype, 'int32');
+ var result = zeros(backend, outShape, resultDtype);
+ var reduceSize = tfjsCore.util.sizeFromShape(reduceShape);
+ var vals = backend.data.get(result.dataId).values;
+ var aVals = backend.data.get(permutedX.dataId).values;
+ for (var i = 0; i < vals.length; ++i) {
+ var offset = i * reduceSize;
+ var sum_1 = 0;
+ for (var j = 0; j < reduceSize; ++j) {
+ sum_1 += aVals[offset + j];
+ }
+ vals[i] = sum_1;
+ }
+ if (keepDims) {
+ var newShape = tfjsCore.backend_util.expandShapeToKeepDim(result.shape, axes);
+ var oldResult = result;
+ result = reshape({ inputs: { x: result }, backend: backend, attrs: { shape: newShape } });
+ backend.disposeIntermediateTensorInfo(oldResult);
+ }
+ backend.disposeIntermediateTensorInfo($x);
+ if (permutation != null) {
+ backend.disposeIntermediateTensorInfo(permutedX);
+ }
+ return result;
+ }
+ var sumConfig = {
+ kernelName: tfjsCore.Sum,
+ backendName: 'cpu',
+ kernelFunc: sum
+ };
+
+ function einsum(args) {
+ var e_1, _a, e_2, _b;
+ var inputs = args.inputs, backend = args.backend, attrs = args.attrs;
+ var equation = attrs.equation;
+ var tensors = inputs;
+ var _c = tfjsCore.backend_util.decodeEinsumEquation(equation, tensors.length), allDims = _c.allDims, summedDims = _c.summedDims, idDims = _c.idDims;
+ tfjsCore.backend_util.checkEinsumDimSizes(allDims.length, idDims, tensors);
+ var _d = tfjsCore.backend_util.getEinsumComputePath(summedDims, idDims), path = _d.path, steps = _d.steps;
+ var nSteps = steps.length;
+ var out = null;
+ var numDimsRemaining = allDims.length;
+ var tensorsToDispose = [];
+ for (var i = 0; i < nSteps; ++i) {
+ try {
+ for (var _e = (e_1 = void 0, __values(steps[i])), _f = _e.next(); !_f.done; _f = _e.next()) {
+ var idTerm = _f.value;
+ var _g = tfjsCore.backend_util.getEinsumPermutation(numDimsRemaining, idDims[idTerm]), perm = _g.permutationIndices, dimsToExpand = _g.expandDims;
+ var x = void 0;
+ if (tfjsCore.backend_util.isIdentityPermutation(perm)) {
+ x = tensors[idTerm];
+ }
+ else {
+ x = transpose({ inputs: { x: tensors[idTerm] }, backend: backend, attrs: { perm: perm } });
+ tensorsToDispose.push(x);
+ }
+ var targetShape = x.shape.slice();
+ for (var k = 0; k < dimsToExpand.length; ++k) {
+ targetShape.splice(dimsToExpand[k], 0, 1);
+ }
+ if (!tfjsCore.util.arraysEqual(x.shape, targetShape)) {
+ x = reshape({ inputs: { x: x }, backend: backend, attrs: { shape: targetShape } });
+ tensorsToDispose.push(x);
+ }
+ if (out === null) {
+ out = x;
+ }
+ else {
+ // tslint:disable-next-line: no-unnecessary-type-assertion
+ out = multiply({ inputs: { a: x, b: out }, backend: backend });
+ tensorsToDispose.push(out);
+ }
+ }
+ }
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
+ finally {
+ try {
+ if (_f && !_f.done && (_a = _e.return)) _a.call(_e);
+ }
+ finally { if (e_1) throw e_1.error; }
+ }
+ if (i < nSteps - 1) {
+ if (path[i] >= 0) {
+ out = sum({
+ inputs: { x: out },
+ backend: backend,
+ attrs: {
+ axis: path[i] - (allDims.length - numDimsRemaining),
+ keepDims: false
+ }
+ });
+ tensorsToDispose.push(out);
+ }
+ numDimsRemaining--;
+ }
+ }
+ try {
+ // Clean up intermediate tensors.
+ for (var tensorsToDispose_1 = __values(tensorsToDispose), tensorsToDispose_1_1 = tensorsToDispose_1.next(); !tensorsToDispose_1_1.done; tensorsToDispose_1_1 = tensorsToDispose_1.next()) {
+ var tensorInfo = tensorsToDispose_1_1.value;
+ if (tensorInfo === out) {
+ continue;
+ }
+ backend.disposeIntermediateTensorInfo(tensorInfo);
+ }
+ }
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
+ finally {
+ try {
+ if (tensorsToDispose_1_1 && !tensorsToDispose_1_1.done && (_b = tensorsToDispose_1.return)) _b.call(tensorsToDispose_1);
+ }
+ finally { if (e_2) throw e_2.error; }
+ }
+ return out;
+ }
+ var einsumConfig = {
+ kernelName: tfjsCore.Einsum,
+ backendName: 'cpu',
+ kernelFunc: einsum
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ function eluGrad(args) {
+ var inputs = args.inputs, backend = args.backend;
+ var dy = inputs.dy, y = inputs.y;
+ assertNotComplex([dy, y], 'eluGrad');
+ var resultValues = new Float32Array(tfjsCore.util.sizeFromShape(y.shape));
+ var values = backend.data.get(y.dataId).values;
+ var dyValues = backend.data.get(dy.dataId).values;
+ for (var i = 0; i < values.length; ++i) {
+ var v = values[i];
+ if (v >= 1) {
+ resultValues[i] = dyValues[i];
+ }
+ else {
+ resultValues[i] = dyValues[i] * (v + 1);
+ }
+ }
+ return backend.makeTensorInfo(y.shape, 'float32', resultValues);
+ }
+ var eluGradConfig = {
+ kernelName: tfjsCore.EluGrad,
+ backendName: 'cpu',
+ kernelFunc: eluGrad
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ var p = tfjsCore.backend_util.ERF_P;
+ var a1 = tfjsCore.backend_util.ERF_A1;
+ var a2 = tfjsCore.backend_util.ERF_A2;
+ var a3 = tfjsCore.backend_util.ERF_A3;
+ var a4 = tfjsCore.backend_util.ERF_A4;
+ var a5 = tfjsCore.backend_util.ERF_A5;
+ var erf = unaryKernelFunc(tfjsCore.Erf, function (xi) {
+ var sign = Math.sign(xi);
+ var v = Math.abs(xi);
+ var t = 1.0 / (1.0 + p * v);
+ return sign *
+ (1.0 -
+ (((((a5 * t + a4) * t) + a3) * t + a2) * t + a1) * t *
+ Math.exp(-v * v));
+ });
+ var erfConfig = {
+ kernelName: tfjsCore.Erf,
+ backendName: 'cpu',
+ kernelFunc: erf,
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ function expandDims(args) {
+ var inputs = args.inputs, backend = args.backend, attrs = args.attrs;
+ var input = inputs.input;
+ var dim = attrs.dim;
+ var inputRank = input.shape.length;
+ var newShape = input.shape.slice();
+ var $dim = dim;
+ if (dim < 0) {
+ // Negative value is counted from the tail of rank.
+ tfjsCore.util.assert(-(inputRank + 1) <= dim, function () { return "Axis must be in the interval [" + -(inputRank + 1) + ", " + inputRank + "]"; });
+ $dim = inputRank + dim + 1;
+ }
+ newShape.splice($dim, 0, 1);
+ return reshape({ inputs: { x: input }, backend: backend, attrs: { shape: newShape } });
+ }
+ var expandDimsConfig = {
+ kernelName: tfjsCore.ExpandDims,
+ backendName: 'cpu',
+ kernelFunc: expandDims
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ var realDivImpl = createSimpleBinaryKernelImpl(function (a, b) { return a / b; });
+ var div = binaryKernelFunc(tfjsCore.RealDiv, realDivImpl);
+ var realDivConfig = {
+ kernelName: tfjsCore.RealDiv,
+ backendName: 'cpu',
+ kernelFunc: div
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ /**
+ * Calculate FFT of inner most elements of batch tensor.
+ */
+ function fftBatch(input, inverse, cpuBackend) {
+ var inputShape = input.shape;
+ var batch = inputShape[0];
+ var innerDim = inputShape[1];
+ var inputVals = cpuBackend.data.get(input.dataId);
+ var real2D = inputVals.complexTensorInfos.real;
+ var imag2D = inputVals.complexTensorInfos.imag;
+ // Collects real and imaginary values separately.
+ var resultShape = [batch, innerDim];
+ var resultSize = tfjsCore.util.sizeFromShape(resultShape);
+ var resultReal = tfjsCore.util.getTypedArrayFromDType('float32', resultSize);
+ var resultImag = tfjsCore.util.getTypedArrayFromDType('float32', resultSize);
+ for (var b = 0; b < batch; b++) {
+ // TODO: Support slice ops for complex type.
+ var r = slice({
+ inputs: { x: real2D },
+ backend: cpuBackend,
+ attrs: { begin: [b, 0], size: [1, innerDim] }
+ });
+ var i = slice({
+ inputs: { x: imag2D },
+ backend: cpuBackend,
+ attrs: { begin: [b, 0], size: [1, innerDim] }
+ });
+ var input_1 = complex({ inputs: { real: r, imag: i }, backend: cpuBackend });
+ // Run FFT by batch element.
+ var _a = fftImpl(input_1, inverse, cpuBackend), real_1 = _a.real, imag_1 = _a.imag;
+ var res = tfjsCore.backend_util.mergeRealAndImagArrays(real_1, imag_1);
+ for (var d = 0; d < innerDim; d++) {
+ var c = tfjsCore.backend_util.getComplexWithIndex(res, d);
+ resultReal[b * innerDim + d] = c.real;
+ resultImag[b * innerDim + d] = c.imag;
+ }
+ cpuBackend.disposeIntermediateTensorInfo(r);
+ cpuBackend.disposeIntermediateTensorInfo(i);
+ cpuBackend.disposeIntermediateTensorInfo(input_1);
+ }
+ var $realInfo = cpuBackend.makeTensorInfo(resultShape, 'float32', resultReal);
+ var $imagInfo = cpuBackend.makeTensorInfo(resultShape, 'float32', resultImag);
+ var result = complex({ inputs: { real: $realInfo, imag: $imagInfo }, backend: cpuBackend });
+ cpuBackend.disposeIntermediateTensorInfo($realInfo);
+ cpuBackend.disposeIntermediateTensorInfo($imagInfo);
+ return result;
+ }
+ function fftImpl(input, inverse, cpuBackend) {
+ var inputSize = tfjsCore.util.sizeFromShape(input.shape);
+ var inputVals = cpuBackend.data.get(input.dataId);
+ var realVals = cpuBackend.data.get(inputVals.complexTensorInfos.real.dataId).values;
+ var imagVals = cpuBackend.data.get(inputVals.complexTensorInfos.imag.dataId).values;
+ if (isExponentOf2(inputSize)) {
+ var result = fftRadix2(realVals, imagVals, inputSize, inverse, cpuBackend);
+ var resultShape = [input.shape[0], input.shape[1]];
+ if (inverse) {
+ var realInfo = cpuBackend.makeTensorInfo(resultShape, 'float32', result.real);
+ var imagInfo = cpuBackend.makeTensorInfo(resultShape, 'float32', result.imag);
+ var sizeInfo = cpuBackend.makeTensorInfo([], 'float32', tfjsCore.util.createScalarValue(inputSize, 'float32'));
+ var sizeInfoCopy = identity({ inputs: { x: sizeInfo }, backend: cpuBackend });
+ var divRealInfo = realDivConfig.kernelFunc({ inputs: { a: realInfo, b: sizeInfo }, backend: cpuBackend });
+ var divImagInfo = realDivConfig.kernelFunc({ inputs: { a: imagInfo, b: sizeInfoCopy }, backend: cpuBackend });
+ var divRealVals = cpuBackend.data.get(divRealInfo.dataId).values;
+ var divImagVals = cpuBackend.data.get(divImagInfo.dataId).values;
+ cpuBackend.disposeIntermediateTensorInfo(realInfo);
+ cpuBackend.disposeIntermediateTensorInfo(imagInfo);
+ cpuBackend.disposeIntermediateTensorInfo(sizeInfo);
+ cpuBackend.disposeIntermediateTensorInfo(sizeInfoCopy);
+ cpuBackend.disposeIntermediateTensorInfo(divRealInfo);
+ cpuBackend.disposeIntermediateTensorInfo(divImagInfo);
+ return { real: divRealVals, imag: divImagVals };
+ }
+ return result;
+ }
+ else {
+ var data = tfjsCore.backend_util.mergeRealAndImagArrays(realVals, imagVals);
+ var rawOutput = fourierTransformByMatmul(data, inputSize, inverse);
+ return tfjsCore.backend_util.splitRealAndImagArrays(rawOutput);
+ }
+ }
+ function isExponentOf2(size) {
+ return (size & size - 1) === 0;
+ }
+ // FFT using Cooley-Tukey algorithm on radix 2 dimensional input.
+ function fftRadix2(realVals, imagVals, size, inverse, cpuBackend) {
+ if (size === 1) {
+ return { real: realVals, imag: imagVals };
+ }
+ var data = tfjsCore.backend_util.mergeRealAndImagArrays(realVals, imagVals);
+ var half = size / 2;
+ var evenComplex = tfjsCore.backend_util.complexWithEvenIndex(data);
+ var evenRealVals = evenComplex.real;
+ var evenImagVals = evenComplex.imag;
+ var evenShape = [evenRealVals.length];
+ var evenRealInfo = cpuBackend.makeTensorInfo(evenShape, 'float32', evenRealVals);
+ var evenImagInfo = cpuBackend.makeTensorInfo(evenShape, 'float32', evenImagVals);
+ var evenTensorInfo = complex({ inputs: { real: evenRealInfo, imag: evenImagInfo }, backend: cpuBackend });
+ var oddComplex = tfjsCore.backend_util.complexWithOddIndex(data);
+ var oddRealVals = oddComplex.real;
+ var oddImagVals = oddComplex.imag;
+ var oddShape = [oddRealVals.length];
+ var oddRealInfo = cpuBackend.makeTensorInfo(oddShape, 'float32', oddRealVals);
+ var oddImagInfo = cpuBackend.makeTensorInfo(oddShape, 'float32', oddImagVals);
+ var oddTensorInfo = complex({ inputs: { real: oddRealInfo, imag: oddImagInfo }, backend: cpuBackend });
+ // Recursive call for half part of original input.
+ var $evenComplex = fftRadix2(evenRealVals, evenImagVals, half, inverse, cpuBackend);
+ var $evenRealVals = $evenComplex.real;
+ var $evenImagVals = $evenComplex.imag;
+ var $evenShape = [$evenRealVals.length];
+ var $evenRealInfo = cpuBackend.makeTensorInfo($evenShape, 'float32', $evenRealVals);
+ var $evenImagInfo = cpuBackend.makeTensorInfo($evenShape, 'float32', $evenImagVals);
+ var $evenTensorInfo = complex({
+ inputs: { real: $evenRealInfo, imag: $evenImagInfo },
+ backend: cpuBackend
+ });
+ var $oddComplex = fftRadix2(oddRealVals, oddImagVals, half, inverse, cpuBackend);
+ var $oddRealVals = $oddComplex.real;
+ var $oddImagVals = $oddComplex.imag;
+ var $oddShape = [$oddRealVals.length];
+ var $oddRealInfo = cpuBackend.makeTensorInfo($oddShape, 'float32', $oddRealVals);
+ var $oddImagInfo = cpuBackend.makeTensorInfo($oddShape, 'float32', $oddImagVals);
+ var $oddTensorInfo = complex({ inputs: { real: $oddRealInfo, imag: $oddImagInfo }, backend: cpuBackend });
+ var e = tfjsCore.backend_util.exponents(size, inverse);
+ var eShape = [e.real.length];
+ var eRealInfo = cpuBackend.makeTensorInfo(eShape, 'float32', e.real);
+ var eImagInfo = cpuBackend.makeTensorInfo(eShape, 'float32', e.imag);
+ var complexInfo = complex({ inputs: { real: eRealInfo, imag: eImagInfo }, backend: cpuBackend });
+ var exponentInfo = multiply({ inputs: { a: complexInfo, b: $oddTensorInfo }, backend: cpuBackend });
+ var addPart = add({
+ inputs: { a: $evenTensorInfo, b: exponentInfo },
+ backend: cpuBackend
+ });
+ var subPart = sub({
+ inputs: { a: $evenTensorInfo, b: exponentInfo },
+ backend: cpuBackend
+ });
+ var addPartReal = real({ inputs: { input: addPart }, backend: cpuBackend });
+ var subPartReal = real({ inputs: { input: subPart }, backend: cpuBackend });
+ var addPartImag = imag({ inputs: { input: addPart }, backend: cpuBackend });
+ var subPartImag = imag({ inputs: { input: subPart }, backend: cpuBackend });
+ var $real = concat({
+ inputs: [addPartReal, subPartReal],
+ backend: cpuBackend,
+ attrs: { axis: 0 }
+ });
+ var $imag = concat({
+ inputs: [addPartImag, subPartImag],
+ backend: cpuBackend,
+ attrs: { axis: 0 }
+ });
+ var $realVals = cpuBackend.data.get($real.dataId).values;
+ var $imagVals = cpuBackend.data.get($imag.dataId).values;
+ cpuBackend.disposeIntermediateTensorInfo(evenRealInfo);
+ cpuBackend.disposeIntermediateTensorInfo(evenImagInfo);
+ cpuBackend.disposeIntermediateTensorInfo(evenTensorInfo);
+ cpuBackend.disposeIntermediateTensorInfo(oddRealInfo);
+ cpuBackend.disposeIntermediateTensorInfo(oddImagInfo);
+ cpuBackend.disposeIntermediateTensorInfo(oddTensorInfo);
+ cpuBackend.disposeIntermediateTensorInfo($evenRealInfo);
+ cpuBackend.disposeIntermediateTensorInfo($evenImagInfo);
+ cpuBackend.disposeIntermediateTensorInfo($evenTensorInfo);
+ cpuBackend.disposeIntermediateTensorInfo($oddRealInfo);
+ cpuBackend.disposeIntermediateTensorInfo($oddImagInfo);
+ cpuBackend.disposeIntermediateTensorInfo($oddTensorInfo);
+ cpuBackend.disposeIntermediateTensorInfo(eRealInfo);
+ cpuBackend.disposeIntermediateTensorInfo(eImagInfo);
+ cpuBackend.disposeIntermediateTensorInfo(complexInfo);
+ cpuBackend.disposeIntermediateTensorInfo(exponentInfo);
+ cpuBackend.disposeIntermediateTensorInfo(addPart);
+ cpuBackend.disposeIntermediateTensorInfo(subPart);
+ cpuBackend.disposeIntermediateTensorInfo(addPartReal);
+ cpuBackend.disposeIntermediateTensorInfo(addPartImag);
+ cpuBackend.disposeIntermediateTensorInfo(subPartReal);
+ cpuBackend.disposeIntermediateTensorInfo(subPartImag);
+ cpuBackend.disposeIntermediateTensorInfo($real);
+ cpuBackend.disposeIntermediateTensorInfo($imag);
+ return { real: $realVals, imag: $imagVals };
+ }
+ // Calculate fourier transform by multplying sinusoid matrix.
+ function fourierTransformByMatmul(data, size, inverse) {
+ var ret = new Float32Array(size * 2);
+ // TODO: Use matmul instead once it supports complex64 type.
+ for (var r = 0; r < size; r++) {
+ var real_2 = 0.0;
+ var imag_2 = 0.0;
+ for (var c = 0; c < size; c++) {
+ var e = tfjsCore.backend_util.exponent(r * c, size, inverse);
+ var term = tfjsCore.backend_util.getComplexWithIndex(data, c);
+ real_2 += term.real * e.real - term.imag * e.imag;
+ imag_2 += term.real * e.imag + term.imag * e.real;
+ }
+ if (inverse) {
+ real_2 /= size;
+ imag_2 /= size;
+ }
+ tfjsCore.backend_util.assignToTypedArray(ret, real_2, imag_2, r);
+ }
+ return ret;
+ }
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ function fft(args) {
+ var inputs = args.inputs, backend = args.backend;
+ var input = inputs.input;
+ var inputSize = tfjsCore.util.sizeFromShape(input.shape);
+ // Collapse all outer dimensions to a single batch dimension.
+ var innerDimensionSize = input.shape[input.shape.length - 1];
+ var batch = inputSize / innerDimensionSize;
+ var input2D = reshape({
+ inputs: { x: input },
+ backend: backend,
+ attrs: { shape: [batch, innerDimensionSize] }
+ });
+ var result = fftBatch(input2D, false, backend);
+ var resultReshaped = reshape({ inputs: { x: result }, backend: backend, attrs: { shape: input.shape } });
+ backend.disposeIntermediateTensorInfo(input2D);
+ backend.disposeIntermediateTensorInfo(result);
+ return resultReshaped;
+ }
+ var fftConfig = {
+ kernelName: tfjsCore.FFT,
+ backendName: 'cpu',
+ kernelFunc: fft
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ function fill(args) {
+ var backend = args.backend, attrs = args.attrs;
+ var shape = attrs.shape, value = attrs.value, dtype = attrs.dtype;
+ var $dtype = dtype || tfjsCore.util.inferDtype(value);
+ var values = tfjsCore.util.getArrayFromDType($dtype, tfjsCore.util.sizeFromShape(shape));
+ fillValues(values, value, $dtype);
+ return backend.makeTensorInfo(shape, $dtype, values);
+ }
+ var fillConfig = {
+ kernelName: tfjsCore.Fill,
+ backendName: 'cpu',
+ kernelFunc: fill
+ };
+ function fillValues(values, value, dtype) {
+ if (dtype === 'string') {
+ values.fill(value);
+ }
+ else {
+ values.fill(value);
+ }
+ }
+
+ var flipLeftRightConfig = {
+ kernelName: tfjsCore.FlipLeftRight,
+ backendName: 'cpu',
+ kernelFunc: function (_a) {
+ var inputs = _a.inputs; _a.attrs; var backend = _a.backend;
+ var image = inputs.image;
+ var cpuBackend = backend;
+ var output = tfjsCore.util.getTypedArrayFromDType(image.dtype, tfjsCore.util.sizeFromShape(image.shape));
+ var _b = __read(image.shape, 4), batch = _b[0], imageHeight = _b[1], imageWidth = _b[2], numChannels = _b[3];
+ var imageVals = cpuBackend.data.get(image.dataId).values;
+ for (var batchIdx = 0; batchIdx < batch; batchIdx++) {
+ var batchOffset = batchIdx * imageWidth * imageHeight * numChannels;
+ for (var row = 0; row < imageHeight; row++) {
+ var rowOffset = row * (imageWidth * numChannels);
+ for (var col = 0; col < imageWidth; col++) {
+ var colOffset = col * numChannels;
+ for (var channel = 0; channel < numChannels; channel++) {
+ var coordX = Math.round(imageWidth - col - 1);
+ var outIdx = batchOffset + rowOffset + colOffset + channel;
+ var outputValue = imageVals[outIdx];
+ // If the coordinate position falls within the image boundaries...
+ if (coordX >= 0 && coordX < imageWidth) {
+ // set the output to the image value at the coordinate position.
+ var rotatedColOffset = coordX * numChannels;
+ var imageIdx = batchOffset + rowOffset + rotatedColOffset + channel;
+ outputValue = imageVals[imageIdx];
+ }
+ output[outIdx] = outputValue;
+ }
+ }
+ }
+ }
+ var dataId = cpuBackend.write(output, image.shape, image.dtype);
+ return { dataId: dataId, shape: image.shape, dtype: image.dtype };
+ }
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ var floorDivImpl = createSimpleBinaryKernelImpl(function (a, b) { return Math.floor(a / b); });
+ var floorDiv = binaryKernelFunc(tfjsCore.FloorDiv, floorDivImpl, null /* complexImpl */, 'int32');
+ var floorDivConfig = {
+ kernelName: tfjsCore.FloorDiv,
+ backendName: 'cpu',
+ kernelFunc: floorDiv
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ function fusedConv2D(args) {
+ var inputs = args.inputs, backend = args.backend, attrs = args.attrs;
+ var x = inputs.x, filter = inputs.filter, bias = inputs.bias, preluActivationWeights = inputs.preluActivationWeights;
+ var strides = attrs.strides, pad = attrs.pad, dataFormat = attrs.dataFormat, dilations = attrs.dilations, dimRoundingMode = attrs.dimRoundingMode, activation = attrs.activation, leakyreluAlpha = attrs.leakyreluAlpha;
+ var result = conv2D({
+ inputs: { x: x, filter: filter },
+ backend: backend,
+ attrs: { strides: strides, pad: pad, dataFormat: dataFormat, dilations: dilations, dimRoundingMode: dimRoundingMode }
+ });
+ if (bias) {
+ var resultOld = result;
+ result = add({ inputs: { a: result, b: bias }, backend: backend });
+ backend.disposeIntermediateTensorInfo(resultOld);
+ }
+ if (activation) {
+ var resultOld = result;
+ result = applyActivation(backend, result, activation, preluActivationWeights, leakyreluAlpha);
+ backend.disposeIntermediateTensorInfo(resultOld);
+ }
+ return result;
+ }
+ var fusedConv2DConfig = {
+ kernelName: tfjsCore.FusedConv2D,
+ backendName: 'cpu',
+ kernelFunc: fusedConv2D
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ function fusedDepthwiseConv2D(args) {
+ var inputs = args.inputs, backend = args.backend, attrs = args.attrs;
+ var x = inputs.x, filter = inputs.filter, bias = inputs.bias, preluActivationWeights = inputs.preluActivationWeights;
+ var strides = attrs.strides, pad = attrs.pad, dataFormat = attrs.dataFormat, dilations = attrs.dilations, dimRoundingMode = attrs.dimRoundingMode, activation = attrs.activation, leakyreluAlpha = attrs.leakyreluAlpha;
+ var result = depthwiseConv2dNative({
+ inputs: { x: x, filter: filter },
+ backend: backend,
+ attrs: { strides: strides, pad: pad, dataFormat: dataFormat, dilations: dilations, dimRoundingMode: dimRoundingMode }
+ });
+ if (bias) {
+ var oldResult = result;
+ result = add({ inputs: { a: result, b: bias }, backend: backend });
+ backend.disposeIntermediateTensorInfo(oldResult);
+ }
+ if (activation) {
+ var oldResult = result;
+ result = applyActivation(backend, result, activation, preluActivationWeights, leakyreluAlpha);
+ backend.disposeIntermediateTensorInfo(oldResult);
+ }
+ return result;
+ }
+ var fusedDepthwiseConv2DConfig = {
+ kernelName: tfjsCore.FusedDepthwiseConv2D,
+ backendName: 'cpu',
+ kernelFunc: fusedDepthwiseConv2D
+ };
+
+ function gatherNd(args) {
+ var inputs = args.inputs, backend = args.backend;
+ var params = inputs.params, indices = inputs.indices;
+ var paramsSize = tfjsCore.util.sizeFromShape(params.shape);
+ var indicesShape = indices.shape;
+ var sliceRank = indicesShape[indicesShape.length - 1];
+ var _a = __read(tfjsCore.backend_util.prepareAndValidate(params, indices), 4), resultShape = _a[0], numSlices = _a[1], sliceSize = _a[2], strides = _a[3];
+ if (numSlices === 0) {
+ return backend.makeTensorInfo(resultShape, params.dtype, []);
+ }
+ var indicesData = backend.data.get(indices.dataId).values;
+ var paramsBuf = backend.bufferSync(params);
+ var outBuf = gatherNdImpl(indicesData, paramsBuf, params.dtype, numSlices, sliceRank, sliceSize, strides, params.shape, paramsSize);
+ return backend.makeTensorInfo(resultShape, params.dtype, outBuf.values);
+ }
+ var gatherNdConfig = {
+ kernelName: tfjsCore.GatherNd,
+ backendName: 'cpu',
+ kernelFunc: gatherNd
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ function gatherV2(args) {
+ var inputs = args.inputs, backend = args.backend, attrs = args.attrs;
+ var x = inputs.x, indices = inputs.indices;
+ var axis = attrs.axis, batchDims = attrs.batchDims;
+ assertNotComplex([x, indices], 'gatherV2');
+ // Throw error when any index is out of bound.
+ var parsedAxis = tfjsCore.util.parseAxisParam(axis, x.shape)[0];
+ var indicesVals = backend.data.get(indices.dataId).values;
+ var axisDim = x.shape[parsedAxis];
+ var _loop_1 = function (i) {
+ var index = indicesVals[i];
+ tfjsCore.util.assert(index <= axisDim - 1 && index >= 0, function () { return "GatherV2: the index value " + index + " is not in [0, " + (axisDim - 1) + "]"; });
+ };
+ for (var i = 0; i < indicesVals.length; ++i) {
+ _loop_1(i);
+ }
+ var $batchDims = batchDims;
+ if (batchDims == null) {
+ $batchDims = 0;
+ }
+ var indicesSize = tfjsCore.util.sizeFromShape(indices.shape);
+ var shapeInfo = tfjsCore.backend_util.segment_util.collectGatherOpShapeInfo(x, indices, parsedAxis, $batchDims);
+ var flattenX = reshape({
+ inputs: { x: x },
+ backend: backend,
+ attrs: {
+ shape: [
+ shapeInfo.batchSize, shapeInfo.outerSize, shapeInfo.dimSize,
+ shapeInfo.sliceSize
+ ]
+ }
+ });
+ var flattenIndex = reshape({
+ inputs: { x: indices },
+ backend: backend,
+ attrs: { shape: [shapeInfo.batchSize, indicesSize / shapeInfo.batchSize] }
+ });
+ var flattenOutputShape = [
+ shapeInfo.batchSize, shapeInfo.outerSize, indicesSize / shapeInfo.batchSize,
+ shapeInfo.sliceSize
+ ];
+ var indicesBuf = backend.bufferSync(flattenIndex);
+ var xBuf = backend.bufferSync(flattenX);
+ var outBuf = gatherV2Impl(xBuf, indicesBuf, flattenOutputShape);
+ backend.disposeIntermediateTensorInfo(flattenX);
+ backend.disposeIntermediateTensorInfo(flattenIndex);
+ return backend.makeTensorInfo(shapeInfo.outputShape, outBuf.dtype, outBuf.values);
+ }
+ var gatherV2Config = {
+ kernelName: tfjsCore.GatherV2,
+ backendName: 'cpu',
+ kernelFunc: gatherV2
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ function ifft(args) {
+ var inputs = args.inputs, backend = args.backend;
+ var input = inputs.input;
+ var inputSize = tfjsCore.util.sizeFromShape(input.shape);
+ // Collapse all outer dimensions to a single batch dimension.
+ var innerDimensionSize = input.shape[input.shape.length - 1];
+ var batch = inputSize / innerDimensionSize;
+ var input2D = reshape({
+ inputs: { x: input },
+ backend: backend,
+ attrs: { shape: [batch, innerDimensionSize] }
+ });
+ var result = fftBatch(input2D, true, backend);
+ var resultReshaped = reshape({ inputs: { x: result }, backend: backend, attrs: { shape: input.shape } });
+ backend.disposeIntermediateTensorInfo(input2D);
+ backend.disposeIntermediateTensorInfo(result);
+ return resultReshaped;
+ }
+ var ifftConfig = {
+ kernelName: tfjsCore.IFFT,
+ backendName: 'cpu',
+ kernelFunc: ifft
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ var isFinite = unaryKernelFunc(tfjsCore.IsFinite, function (xi) { return Number.isFinite(xi) ? 1 : 0; }, 'bool');
+ var isFiniteConfig = {
+ kernelName: tfjsCore.IsFinite,
+ backendName: 'cpu',
+ kernelFunc: isFinite,
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ var isInf = unaryKernelFunc(tfjsCore.IsInf, function (xi) { return Math.abs(xi) === Infinity ? 1 : 0; }, 'bool');
+ var isInfConfig = {
+ kernelName: tfjsCore.IsInf,
+ backendName: 'cpu',
+ kernelFunc: isInf,
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ var isNaN$1 = unaryKernelFunc(tfjsCore.IsNan, function (xi) { return Number.isNaN(xi) ? 1 : 0; }, 'bool');
+ var isNaNConfig = {
+ kernelName: tfjsCore.IsNan,
+ backendName: 'cpu',
+ kernelFunc: isNaN$1,
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ function linSpace(args) {
+ var backend = args.backend, attrs = args.attrs;
+ var start = attrs.start, stop = attrs.stop, num = attrs.num;
+ var outVals = linSpaceImpl(start, stop, num);
+ return backend.makeTensorInfo([outVals.length], 'float32', outVals);
+ }
+ var linSpaceConfig = {
+ kernelName: tfjsCore.LinSpace,
+ backendName: 'cpu',
+ kernelFunc: linSpace
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ var log1p = unaryKernelFunc(tfjsCore.Log1p, function (xi) { return Math.log1p(xi); });
+ var log1pConfig = {
+ kernelName: tfjsCore.Log1p,
+ backendName: 'cpu',
+ kernelFunc: log1p,
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ var logicalAndImpl = createSimpleBinaryKernelImpl(function (a, b) { return a && b; });
+ var logicalAnd = binaryKernelFunc(tfjsCore.LogicalAnd, logicalAndImpl, null /* complexImpl */, 'bool');
+ var logicalAndConfig = {
+ kernelName: tfjsCore.LogicalAnd,
+ backendName: 'cpu',
+ kernelFunc: logicalAnd
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ var logicalNot = unaryKernelFunc(tfjsCore.LogicalNot, function (xi) { return xi ? 0 : 1; }, 'bool');
+ var logicalNotConfig = {
+ kernelName: tfjsCore.LogicalNot,
+ backendName: 'cpu',
+ kernelFunc: logicalNot,
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ var logicalOrImpl = createSimpleBinaryKernelImpl(function (a, b) { return a || b; });
+ var logicalOr = binaryKernelFunc(tfjsCore.LogicalOr, logicalOrImpl, null /* complexImpl */, 'bool');
+ var logicalOrConfig = {
+ kernelName: tfjsCore.LogicalOr,
+ backendName: 'cpu',
+ kernelFunc: logicalOr
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ function lRN(args) {
+ var inputs = args.inputs, backend = args.backend, attrs = args.attrs;
+ var x = inputs.x;
+ var depthRadius = attrs.depthRadius, bias = attrs.bias, alpha = attrs.alpha, beta = attrs.beta;
+ assertNotComplex(x, 'LRN');
+ var channels = x.shape[3];
+ var maxD = channels - 1;
+ var xValues = backend.data.get(x.dataId).values;
+ var size = tfjsCore.util.sizeFromShape(x.shape);
+ var result = new Float32Array(size);
+ function sumAcrossChannels(offset) {
+ var currentChannel = offset % channels;
+ var beginSumOffset = offset - currentChannel + Math.max(0, currentChannel - depthRadius);
+ var endSumOffset = offset - currentChannel + Math.min(currentChannel + depthRadius, maxD);
+ var sum = 0.0;
+ for (; beginSumOffset <= endSumOffset; beginSumOffset++) {
+ var z = xValues[beginSumOffset];
+ sum += z * z;
+ }
+ return sum;
+ }
+ for (var offset = 0; offset < size; offset++) {
+ var sum = sumAcrossChannels(offset);
+ var val = xValues[offset] * Math.pow(bias + alpha * sum, -beta);
+ result[offset] = val;
+ }
+ return backend.makeTensorInfo(x.shape, x.dtype, result);
+ }
+ var lRNConfig = {
+ kernelName: tfjsCore.LRN,
+ backendName: 'cpu',
+ kernelFunc: lRN
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ function lRNGrad(args) {
+ var inputs = args.inputs, backend = args.backend, attrs = args.attrs;
+ var x = inputs.x, y = inputs.y, dy = inputs.dy;
+ var depthRadius = attrs.depthRadius, bias = attrs.bias, alpha = attrs.alpha, beta = attrs.beta;
+ assertNotComplex(dy, 'LRNGrad');
+ var dySize = tfjsCore.util.sizeFromShape(dy.shape);
+ var channels = dy.shape[3];
+ var dyValues = backend.data.get(dy.dataId).values;
+ var xValues = backend.data.get(x.dataId).values;
+ var yValues = backend.data.get(y.dataId).values;
+ var result = new Float32Array(dySize);
+ var size = dySize;
+ for (var offset = 0; offset < size; offset++) {
+ var currentChannel = offset % channels;
+ var depthBegin = (offset - currentChannel) + Math.max(0, currentChannel - depthRadius);
+ var depthEnd = (offset - currentChannel) +
+ Math.min(channels, currentChannel + depthRadius + 1);
+ var norm = 0;
+ for (var k = depthBegin; k < depthEnd; k++) {
+ norm += Math.pow(xValues[k], 2);
+ }
+ norm = alpha * norm + bias;
+ for (var k = depthBegin; k < depthEnd; k++) {
+ var dyi = -2 * alpha * beta * xValues[k] * yValues[offset] / norm;
+ if (offset === k) {
+ dyi += Math.pow(norm, -beta);
+ }
+ dyi *= dyValues[offset];
+ result[k] += dyi;
+ }
+ }
+ return backend.makeTensorInfo(dy.shape, x.dtype, result);
+ }
+ var lRNGradConfig = {
+ kernelName: tfjsCore.LRNGrad,
+ backendName: 'cpu',
+ kernelFunc: lRNGrad
+ };
+
+ function max(args) {
+ var inputs = args.inputs, backend = args.backend, attrs = args.attrs;
+ var x = inputs.x;
+ var reductionIndices = attrs.reductionIndices, keepDims = attrs.keepDims;
+ var cpuBackend = backend;
+ var xShape = x.shape;
+ var xRank = xShape.length;
+ var origAxes = tfjsCore.util.parseAxisParam(reductionIndices, xShape);
+ var axes = origAxes;
+ var permutedAxes = tfjsCore.backend_util.getAxesPermutation(axes, xRank);
+ var xVals = cpuBackend.data.get(x.dataId).values;
+ if (permutedAxes != null) {
+ var newShape = new Array(xRank);
+ for (var i = 0; i < newShape.length; i++) {
+ newShape[i] = xShape[permutedAxes[i]];
+ }
+ xVals = transposeImpl(xVals, xShape, x.dtype, permutedAxes, newShape);
+ axes = tfjsCore.backend_util.getInnerMostAxes(axes.length, xRank);
+ xShape = newShape;
+ }
+ assertNotComplex(x, 'max');
+ tfjsCore.backend_util.assertAxesAreInnerMostDims('max', axes, xRank);
+ var _a = __read(tfjsCore.backend_util.computeOutAndReduceShapes(xShape, axes), 2), maxOutShape = _a[0], reduceShape = _a[1];
+ var reduceSize = tfjsCore.util.sizeFromShape(reduceShape);
+ var result = maxImpl(xVals, reduceSize, maxOutShape, x.dtype);
+ var dataId = cpuBackend.write(result, maxOutShape, x.dtype);
+ var outShape = maxOutShape;
+ if (keepDims) {
+ // reshape
+ var newShape = tfjsCore.backend_util.expandShapeToKeepDim(maxOutShape, origAxes);
+ outShape = newShape;
+ }
+ return { dataId: dataId, shape: outShape, dtype: x.dtype };
+ }
+ var maxConfig = {
+ kernelName: tfjsCore.Max,
+ backendName: 'cpu',
+ kernelFunc: max
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ function maxPool(args) {
+ var inputs = args.inputs, backend = args.backend, attrs = args.attrs;
+ var x = inputs.x;
+ assertNotComplex(x, 'maxPool');
+ var filterSize = attrs.filterSize, strides = attrs.strides, pad = attrs.pad, dimRoundingMode = attrs.dimRoundingMode;
+ var dilations = 1;
+ tfjsCore.util.assert(tfjsCore.backend_util.eitherStridesOrDilationsAreOne(strides, dilations), function () { return 'Error in maxPool: Either strides or dilations must be 1. ' +
+ ("Got strides " + strides + " and dilations '" + dilations + "'"); });
+ var convInfo = tfjsCore.backend_util.computePool2DInfo(x.shape, filterSize, strides, dilations, pad, dimRoundingMode);
+ var res;
+ if (convInfo.filterWidth === 1 && convInfo.filterHeight === 1 &&
+ tfjsCore.util.arraysEqual(convInfo.inShape, convInfo.outShape)) {
+ res = identity({ inputs: { x: x }, backend: backend });
+ }
+ else {
+ var xValues = backend.data.get(x.dataId).values;
+ var strides_1 = tfjsCore.util.computeStrides(x.shape);
+ var buffer = pool(xValues, x.shape, x.dtype, strides_1, convInfo, 'max');
+ res = backend.makeTensorInfo(convInfo.outShape, x.dtype, buffer.values);
+ }
+ return res;
+ }
+ var maxPoolConfig = {
+ kernelName: tfjsCore.MaxPool,
+ backendName: 'cpu',
+ kernelFunc: maxPool
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ function maxPool3D(args) {
+ var inputs = args.inputs, backend = args.backend, attrs = args.attrs;
+ var x = inputs.x;
+ var filterSize = attrs.filterSize, strides = attrs.strides, pad = attrs.pad, dimRoundingMode = attrs.dimRoundingMode, dataFormat = attrs.dataFormat;
+ assertNotComplex(x, 'maxPool3d');
+ var convInfo = tfjsCore.backend_util.computePool3DInfo(x.shape, filterSize, strides, 1 /* dilations */, pad, dimRoundingMode, dataFormat);
+ var xValues = backend.data.get(x.dataId).values;
+ var outBuf = pool3d(xValues, x.shape, x.dtype, tfjsCore.util.computeStrides(x.shape), convInfo, 'max');
+ return backend.makeTensorInfo(outBuf.shape, 'float32', outBuf.values);
+ }
+ var maxPool3DConfig = {
+ kernelName: tfjsCore.MaxPool3D,
+ backendName: 'cpu',
+ kernelFunc: maxPool3D
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ function maxPool3DGrad(args) {
+ var inputs = args.inputs, backend = args.backend, attrs = args.attrs;
+ var dy = inputs.dy, input = inputs.input;
+ var filterSize = attrs.filterSize, strides = attrs.strides, pad = attrs.pad, dimRoundingMode = attrs.dimRoundingMode;
+ assertNotComplex([dy, input], 'maxPool3DGrad');
+ var convInfo = tfjsCore.backend_util.computePool3DInfo(input.shape, filterSize, strides, 1 /* dilations */, pad, dimRoundingMode);
+ var inputBuf = backend.bufferSync(input);
+ var maxPosBuf = maxPool3dPositions(inputBuf, convInfo);
+ var strideDepth = convInfo.strideDepth;
+ var strideHeight = convInfo.strideHeight;
+ var strideWidth = convInfo.strideWidth;
+ var dilationDepth = convInfo.dilationDepth;
+ var dilationHeight = convInfo.dilationHeight;
+ var dilationWidth = convInfo.dilationWidth;
+ var effectiveFilterDepth = convInfo.effectiveFilterDepth;
+ var effectiveFilterHeight = convInfo.effectiveFilterHeight;
+ var effectiveFilterWidth = convInfo.effectiveFilterWidth;
+ var padFront = effectiveFilterDepth - 1 - convInfo.padInfo.front;
+ var padLeft = effectiveFilterWidth - 1 - convInfo.padInfo.left;
+ var padTop = effectiveFilterHeight - 1 - convInfo.padInfo.top;
+ var dx = tfjsCore.buffer(input.shape, 'float32');
+ var dyBuf = backend.bufferSync(dy);
+ for (var batch = 0; batch < convInfo.batchSize; ++batch) {
+ for (var channel = 0; channel < convInfo.inChannels; ++channel) {
+ for (var dxDepth = 0; dxDepth < convInfo.inDepth; ++dxDepth) {
+ for (var dxRow = 0; dxRow < convInfo.inHeight; ++dxRow) {
+ for (var dxCol = 0; dxCol < convInfo.inWidth; ++dxCol) {
+ // Shader code begins
+ var dyDepthCorner = dxDepth - padFront;
+ var dyRowCorner = dxRow - padTop;
+ var dyColCorner = dxCol - padLeft;
+ var dotProd = 0;
+ for (var wDepth = 0; wDepth < effectiveFilterDepth; wDepth += dilationDepth) {
+ var dyDepth = (dyDepthCorner + wDepth) / strideDepth;
+ if (dyDepth < 0 || dyDepth >= convInfo.outDepth ||
+ Math.floor(dyDepth) !== dyDepth) {
+ continue;
+ }
+ for (var wRow = 0; wRow < effectiveFilterHeight; wRow += dilationHeight) {
+ var dyRow = (dyRowCorner + wRow) / strideHeight;
+ if (dyRow < 0 || dyRow >= convInfo.outHeight ||
+ Math.floor(dyRow) !== dyRow) {
+ continue;
+ }
+ for (var wCol = 0; wCol < effectiveFilterWidth; wCol += dilationWidth) {
+ var dyCol = (dyColCorner + wCol) / strideWidth;
+ if (dyCol < 0 || dyCol >= convInfo.outWidth ||
+ Math.floor(dyCol) !== dyCol) {
+ continue;
+ }
+ var maxPos = effectiveFilterDepth * effectiveFilterHeight *
+ effectiveFilterWidth -
+ 1 -
+ maxPosBuf.get(batch, dyDepth, dyRow, dyCol, channel);
+ var curPos = wDepth * effectiveFilterHeight * effectiveFilterWidth +
+ wRow * effectiveFilterWidth + wCol;
+ var mask = maxPos === curPos ? 1 : 0;
+ if (mask === 0) {
+ continue;
+ }
+ var pixel = dyBuf.get(batch, dyDepth, dyRow, dyCol, channel);
+ dotProd += pixel * mask;
+ }
+ }
+ }
+ dx.set(dotProd, batch, dxDepth, dxRow, dxCol, channel);
+ }
+ }
+ }
+ }
+ }
+ return backend.makeTensorInfo(dx.shape, dx.dtype, dx.values);
+ }
+ var maxPool3DGradConfig = {
+ kernelName: tfjsCore.MaxPool3DGrad,
+ backendName: 'cpu',
+ kernelFunc: maxPool3DGrad
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ function maxPoolGrad(args) {
+ var inputs = args.inputs, backend = args.backend, attrs = args.attrs;
+ var dy = inputs.dy, input = inputs.input, output = inputs.output;
+ var x = input;
+ assertNotComplex([input, output], 'maxPoolGrad');
+ var filterSize = attrs.filterSize, strides = attrs.strides, pad = attrs.pad, dimRoundingMode = attrs.dimRoundingMode;
+ var convInfo = tfjsCore.backend_util.computePool2DInfo(x.shape, filterSize, strides, 1 /* dilations */, pad, dimRoundingMode);
+ var xValues = backend.data.get(x.dataId).values;
+ var maxPosBuf = tfjsCore.buffer(convInfo.outShape, x.dtype, maxPoolPositions(xValues, x.shape, x.dtype, convInfo).values);
+ var strideHeight = convInfo.strideHeight;
+ var strideWidth = convInfo.strideWidth;
+ var dilationHeight = convInfo.dilationHeight;
+ var dilationWidth = convInfo.dilationWidth;
+ var effectiveFilterHeight = convInfo.effectiveFilterHeight;
+ var effectiveFilterWidth = convInfo.effectiveFilterWidth;
+ var padLeft = effectiveFilterWidth - 1 - convInfo.padInfo.left;
+ var padTop = effectiveFilterHeight - 1 - convInfo.padInfo.top;
+ var dx = tfjsCore.buffer(x.shape, 'float32');
+ var dyData = backend.data.get(dy.dataId).values;
+ var dyBuf = tfjsCore.buffer(dy.shape, 'float32', dyData);
+ for (var b = 0; b < convInfo.batchSize; ++b) {
+ for (var d = 0; d < convInfo.inChannels; ++d) {
+ for (var dxR = 0; dxR < convInfo.inHeight; ++dxR) {
+ for (var dxC = 0; dxC < convInfo.inWidth; ++dxC) {
+ // Shader code begins.
+ var dyRCorner = dxR - padTop;
+ var dyCCorner = dxC - padLeft;
+ var dotProd = 0;
+ for (var wR = 0; wR < effectiveFilterHeight; wR += dilationHeight) {
+ var dyR = (dyRCorner + wR) / strideHeight;
+ if (dyR < 0 || dyR >= convInfo.outHeight ||
+ Math.floor(dyR) !== dyR) {
+ continue;
+ }
+ for (var wC = 0; wC < effectiveFilterWidth; wC += dilationWidth) {
+ var dyC = (dyCCorner + wC) / strideWidth;
+ if (dyC < 0 || dyC >= convInfo.outWidth ||
+ Math.floor(dyC) !== dyC) {
+ continue;
+ }
+ var maxPos = effectiveFilterHeight * effectiveFilterWidth - 1 -
+ maxPosBuf.get(b, dyR, dyC, d);
+ var curPos = wR * effectiveFilterWidth + wC;
+ var mask = maxPos === curPos ? 1 : 0;
+ if (mask === 0) {
+ continue;
+ }
+ var pixel = dyBuf.get(b, dyR, dyC, d);
+ dotProd += pixel * mask;
+ }
+ }
+ dx.set(dotProd, b, dxR, dxC, d);
+ }
+ }
+ }
+ }
+ return backend.makeTensorInfo(dx.shape, dx.dtype, dx.values);
+ }
+ var maxPoolGradConfig = {
+ kernelName: tfjsCore.MaxPoolGrad,
+ backendName: 'cpu',
+ kernelFunc: maxPoolGrad
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ function maxPoolWithArgmaxImpl(xValues, xShape, dtype, includeBatchInIndex, convInfo) {
+ var strides = tfjsCore.util.computeStrides(xShape);
+ var maxPools = pool(xValues, xShape, dtype, strides, convInfo, 'max');
+ var maxPositions = maxPoolPositions(xValues, xShape, dtype, convInfo, true, includeBatchInIndex);
+ return [maxPools.values, maxPositions.values];
+ }
+
+ var maxPoolWithArgmaxConfig = {
+ kernelName: tfjsCore.MaxPoolWithArgmax,
+ backendName: 'cpu',
+ kernelFunc: function (_a) {
+ var inputs = _a.inputs, attrs = _a.attrs, backend = _a.backend;
+ var x = inputs.x;
+ var filterSize = attrs.filterSize, strides = attrs.strides, pad = attrs.pad, includeBatchInIndex = attrs.includeBatchInIndex;
+ var cpuBackend = backend;
+ assertNotComplex(x, 'MaxPoolWithArgmax');
+ var values = cpuBackend.data.get(x.dataId).values;
+ var convInfo = tfjsCore.backend_util.computePool2DInfo(x.shape, filterSize, strides, [1, 1], pad);
+ var _b = __read(maxPoolWithArgmaxImpl(values, x.shape, x.dtype, includeBatchInIndex, convInfo), 2), pooled = _b[0], indexes = _b[1];
+ var pooledDataId = cpuBackend.write(pooled, convInfo.outShape, x.dtype);
+ var indexesDataId = cpuBackend.write(indexes, convInfo.outShape, x.dtype);
+ return [
+ { dataId: pooledDataId, shape: convInfo.outShape, dtype: x.dtype },
+ { dataId: indexesDataId, shape: convInfo.outShape, dtype: 'int32' }
+ ];
+ }
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ function mean(args) {
+ var inputs = args.inputs, backend = args.backend, attrs = args.attrs;
+ var x = inputs.x;
+ var axis = attrs.axis, keepDims = attrs.keepDims;
+ var axes = tfjsCore.util.parseAxisParam(axis, x.shape);
+ var shapes = tfjsCore.backend_util.computeOutAndReduceShapes(x.shape, axes);
+ var reduceShape = shapes[1];
+ var reduceSize = tfjsCore.util.sizeFromShape(reduceShape);
+ var toDispose = [];
+ var reduceSizeScalar = backend.makeTensorInfo([], 'float32', new Float32Array([reduceSize]));
+ toDispose.push(reduceSizeScalar);
+ var $x = cast({ inputs: { x: x }, backend: backend, attrs: { dtype: 'float32' } });
+ toDispose.push($x);
+ var res = div({ inputs: { a: $x, b: reduceSizeScalar }, backend: backend });
+ toDispose.push(res);
+ var result = sum({ inputs: { x: res }, backend: backend, attrs: { axis: axis, keepDims: keepDims } });
+ toDispose.forEach(function (t) { return backend.disposeIntermediateTensorInfo(t); });
+ return result;
+ }
+ var meanConfig = {
+ kernelName: tfjsCore.Mean,
+ backendName: 'cpu',
+ kernelFunc: mean
+ };
+
+ function min(args) {
+ var inputs = args.inputs, backend = args.backend, attrs = args.attrs;
+ var x = inputs.x;
+ var axis = attrs.axis, keepDims = attrs.keepDims;
+ assertNotComplex(x, 'min');
+ var origAxes = tfjsCore.util.parseAxisParam(axis, x.shape);
+ var axes = origAxes;
+ var permutedAxes = tfjsCore.backend_util.getAxesPermutation(axes, x.shape.length);
+ var $x = x;
+ if (permutedAxes != null) {
+ $x = transpose({ inputs: { x: x }, backend: backend, attrs: { perm: permutedAxes } });
+ axes = tfjsCore.backend_util.getInnerMostAxes(axes.length, x.shape.length);
+ }
+ tfjsCore.backend_util.assertAxesAreInnerMostDims('min', axes, $x.shape.length);
+ var _a = __read(tfjsCore.backend_util.computeOutAndReduceShapes($x.shape, axes), 2), outShape = _a[0], reduceShape = _a[1];
+ var reduceSize = tfjsCore.util.sizeFromShape(reduceShape);
+ var vals = tfjsCore.util.makeZerosTypedArray(tfjsCore.util.sizeFromShape(outShape), $x.dtype);
+ var aVals = backend.data.get($x.dataId).values;
+ for (var i = 0; i < vals.length; ++i) {
+ var offset = i * reduceSize;
+ var min_1 = aVals[offset];
+ for (var j = 0; j < reduceSize; ++j) {
+ var value = aVals[offset + j];
+ if (Number.isNaN(value) ||
+ value < min_1) { // comparison with NaN always return false
+ min_1 = value;
+ }
+ }
+ vals[i] = min_1;
+ }
+ if (permutedAxes != null) {
+ backend.disposeIntermediateTensorInfo($x);
+ }
+ var result = backend.makeTensorInfo(outShape, $x.dtype, vals);
+ if (keepDims) {
+ var expandedShape = tfjsCore.backend_util.expandShapeToKeepDim(outShape, origAxes);
+ var reshapedResult = reshape({ inputs: { x: result }, backend: backend, attrs: { shape: expandedShape } });
+ backend.disposeIntermediateTensorInfo(result);
+ return reshapedResult;
+ }
+ return result;
+ }
+ var minConfig = {
+ kernelName: tfjsCore.Min,
+ backendName: 'cpu',
+ kernelFunc: min
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ function mirrorPad(args) {
+ var inputs = args.inputs, backend = args.backend, attrs = args.attrs;
+ var x = inputs.x;
+ var paddings = attrs.paddings, mode = attrs.mode;
+ assertNotComplex(x, 'mirrorPad');
+ var outShape = paddings.map(function (p, i) { return p[0] /* beforePad */ + x.shape[i] + p[1]; } /* afterPad */);
+ var start = paddings.map(function (p) { return p[0]; });
+ var end = paddings.map(function (p, i) { return p[0] + x.shape[i]; });
+ var offset = mode === 'reflect' ? 0 : 1;
+ var xVals = backend.data.get(x.dataId).values;
+ var xRank = x.shape.length;
+ var xStrides = tfjsCore.util.computeStrides(x.shape);
+ var resultSize = tfjsCore.util.sizeFromShape(outShape);
+ var resultRank = outShape.length;
+ var resultStrides = tfjsCore.util.computeStrides(outShape);
+ var resVals = tfjsCore.util.getTypedArrayFromDType(x.dtype, resultSize);
+ for (var i = 0; i < resultSize; i++) {
+ var coords = tfjsCore.util.indexToLoc(i, resultRank, resultStrides);
+ for (var i_1 = 0; i_1 < resultRank; i_1++) {
+ if (coords[i_1] < start[i_1]) {
+ coords[i_1] = start[i_1] * 2 - coords[i_1] - offset;
+ }
+ else if (coords[i_1] >= end[i_1]) {
+ coords[i_1] = (end[i_1] - 1) * 2 - coords[i_1] + offset;
+ }
+ }
+ coords = coords.map(function (c, i) { return c - start[i]; });
+ var inIndex = tfjsCore.util.locToIndex(coords, xRank, xStrides);
+ resVals[i] = xVals[inIndex];
+ }
+ var outId = backend.write(resVals, outShape, x.dtype);
+ return { dataId: outId, shape: outShape, dtype: x.dtype };
+ }
+ var mirrorPadConfig = {
+ kernelName: tfjsCore.MirrorPad,
+ backendName: 'cpu',
+ kernelFunc: mirrorPad
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ var modImpl = createSimpleBinaryKernelImpl((function (aValue, bValue) {
+ var rem = aValue % bValue;
+ if ((aValue < 0 && bValue < 0) || (aValue >= 0 && bValue >= 0)) {
+ return rem;
+ }
+ else {
+ return (rem + bValue) % bValue;
+ }
+ }));
+ var mod = binaryKernelFunc(tfjsCore.Mod, modImpl);
+ var modConfig = {
+ kernelName: tfjsCore.Mod,
+ backendName: 'cpu',
+ kernelFunc: mod
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ function softmax(args) {
+ var inputs = args.inputs, backend = args.backend, attrs = args.attrs;
+ var logits = inputs.logits;
+ var dim = attrs.dim;
+ var logitsRank = logits.shape.length;
+ var $dim = dim;
+ if ($dim === -1) {
+ $dim = logitsRank - 1;
+ }
+ if ($dim !== logitsRank - 1) {
+ throw Error('Softmax along a non-last dimension is not yet supported. ' +
+ ("Logits was rank " + logitsRank + " and dim was " + $dim));
+ }
+ var axes = tfjsCore.util.parseAxisParam([$dim], logits.shape);
+ var maxLogit = max({
+ inputs: { x: logits },
+ backend: backend,
+ attrs: { reductionIndices: axes, keepDims: false }
+ });
+ var expandedShape = tfjsCore.backend_util.expandShapeToKeepDim(maxLogit.shape, axes);
+ var maxLogitReshaped = reshape({ inputs: { x: maxLogit }, backend: backend, attrs: { shape: expandedShape } });
+ var a = sub({ inputs: { a: logits, b: maxLogitReshaped }, backend: backend });
+ var b = exp({ inputs: { x: a }, backend: backend });
+ var sumExp = sum({ inputs: { x: b }, backend: backend, attrs: { axis: axes, keepDims: false } });
+ var sumReshaped = reshape({ inputs: { x: sumExp }, backend: backend, attrs: { shape: expandedShape } });
+ var result = div({ inputs: { a: b, b: sumReshaped }, backend: backend });
+ backend.disposeIntermediateTensorInfo(maxLogit);
+ backend.disposeIntermediateTensorInfo(maxLogitReshaped);
+ backend.disposeIntermediateTensorInfo(a);
+ backend.disposeIntermediateTensorInfo(b);
+ backend.disposeIntermediateTensorInfo(sumExp);
+ backend.disposeIntermediateTensorInfo(sumReshaped);
+ return result;
+ }
+ var softmaxConfig = {
+ kernelName: tfjsCore.Softmax,
+ backendName: 'cpu',
+ kernelFunc: softmax
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ function multinomial(args) {
+ var inputs = args.inputs, backend = args.backend, attrs = args.attrs;
+ var logits = inputs.logits;
+ var numSamples = attrs.numSamples, seed = attrs.seed, normalized = attrs.normalized;
+ assertNotComplex(logits, 'multinomial');
+ var probabilities = normalized ?
+ logits :
+ softmax({ inputs: { logits: logits }, backend: backend, attrs: { dim: -1 } });
+ var batchSize = probabilities.shape[0];
+ var numEvents = probabilities.shape[1];
+ var probVals = backend.data.get(probabilities.dataId).values;
+ var resShape = [batchSize, numSamples];
+ var resVals = tfjsCore.util.makeZerosTypedArray(tfjsCore.util.sizeFromShape(resShape), 'int32');
+ for (var b = 0; b < batchSize; ++b) {
+ var offset = b * numEvents;
+ // The cdf won't include the last event. It will be implicit if no other
+ // event happened.
+ var cdf = new Float32Array(numEvents - 1);
+ cdf[0] = probVals[offset];
+ for (var event = 1; event < cdf.length; ++event) {
+ cdf[event] = cdf[event - 1] + probVals[offset + event];
+ }
+ var random = seedrandom__namespace.alea(seed.toString());
+ var outOffset = b * numSamples;
+ for (var sampleId = 0; sampleId < numSamples; ++sampleId) {
+ var r = random();
+ // Assume last event happened by default.
+ resVals[outOffset + sampleId] = cdf.length;
+ for (var event = 0; event < cdf.length; event++) {
+ if (r < cdf[event]) {
+ resVals[outOffset + sampleId] = event;
+ break;
+ }
+ }
+ }
+ }
+ if (!normalized) {
+ backend.disposeIntermediateTensorInfo(probabilities);
+ }
+ return backend.makeTensorInfo(resShape, 'int32', resVals);
+ }
+ var multinomialConfig = {
+ kernelName: tfjsCore.Multinomial,
+ backendName: 'cpu',
+ kernelFunc: multinomial
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ var nonMaxSuppressionV3Impl = tfjsCore.kernel_impls.nonMaxSuppressionV3Impl;
+ function nonMaxSuppressionV3(args) {
+ var inputs = args.inputs, backend = args.backend, attrs = args.attrs;
+ var boxes = inputs.boxes, scores = inputs.scores;
+ var maxOutputSize = attrs.maxOutputSize, iouThreshold = attrs.iouThreshold, scoreThreshold = attrs.scoreThreshold;
+ assertNotComplex(boxes, 'NonMaxSuppression');
+ var boxesVals = backend.data.get(boxes.dataId).values;
+ var scoresVals = backend.data.get(scores.dataId).values;
+ var selectedIndices = nonMaxSuppressionV3Impl(boxesVals, scoresVals, maxOutputSize, iouThreshold, scoreThreshold).selectedIndices;
+ return backend.makeTensorInfo([selectedIndices.length], 'int32', new Int32Array(selectedIndices));
+ }
+ var nonMaxSuppressionV3Config = {
+ kernelName: tfjsCore.NonMaxSuppressionV3,
+ backendName: 'cpu',
+ kernelFunc: nonMaxSuppressionV3
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ var nonMaxSuppressionV4Impl = tfjsCore.kernel_impls.nonMaxSuppressionV4Impl;
+ function nonMaxSuppressionV4(args) {
+ var inputs = args.inputs, backend = args.backend, attrs = args.attrs;
+ var boxes = inputs.boxes, scores = inputs.scores;
+ var maxOutputSize = attrs.maxOutputSize, iouThreshold = attrs.iouThreshold, scoreThreshold = attrs.scoreThreshold, padToMaxOutputSize = attrs.padToMaxOutputSize;
+ assertNotComplex(boxes, 'NonMaxSuppressionPadded');
+ var boxesVals = backend.data.get(boxes.dataId).values;
+ var scoresVals = backend.data.get(scores.dataId).values;
+ var _a = nonMaxSuppressionV4Impl(boxesVals, scoresVals, maxOutputSize, iouThreshold, scoreThreshold, padToMaxOutputSize), selectedIndices = _a.selectedIndices, validOutputs = _a.validOutputs;
+ return [
+ backend.makeTensorInfo([selectedIndices.length], 'int32', new Int32Array(selectedIndices)),
+ backend.makeTensorInfo([], 'int32', new Int32Array([validOutputs]))
+ ];
+ }
+ var nonMaxSuppressionV4Config = {
+ kernelName: tfjsCore.NonMaxSuppressionV4,
+ backendName: 'cpu',
+ kernelFunc: nonMaxSuppressionV4
+ };
+
+ /**
+ * @license
+ * Copyright 2019 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ var nonMaxSuppressionV5Impl = tfjsCore.kernel_impls.nonMaxSuppressionV5Impl;
+ function nonMaxSuppressionV5(args) {
+ var inputs = args.inputs, backend = args.backend, attrs = args.attrs;
+ var boxes = inputs.boxes, scores = inputs.scores;
+ var maxOutputSize = attrs.maxOutputSize, iouThreshold = attrs.iouThreshold, scoreThreshold = attrs.scoreThreshold, softNmsSigma = attrs.softNmsSigma;
+ assertNotComplex(boxes, 'NonMaxSuppressionWithScore');
+ var boxesVals = backend.data.get(boxes.dataId).values;
+ var scoresVals = backend.data.get(scores.dataId).values;
+ var maxOutputSizeVal = maxOutputSize;
+ var iouThresholdVal = iouThreshold;
+ var scoreThresholdVal = scoreThreshold;
+ var softNmsSigmaVal = softNmsSigma;
+ var _a = nonMaxSuppressionV5Impl(boxesVals, scoresVals, maxOutputSizeVal, iouThresholdVal, scoreThresholdVal, softNmsSigmaVal), selectedIndices = _a.selectedIndices, selectedScores = _a.selectedScores;
+ return [
+ backend.makeTensorInfo([selectedIndices.length], 'int32', new Int32Array(selectedIndices)),
+ backend.makeTensorInfo([selectedScores.length], 'float32', new Float32Array(selectedScores))
+ ];
+ }
+ var nonMaxSuppressionV5Config = {
+ kernelName: tfjsCore.NonMaxSuppressionV5,
+ backendName: 'cpu',
+ kernelFunc: nonMaxSuppressionV5
+ };
+
+ function oneHot(args) {
+ var inputs = args.inputs, backend = args.backend, attrs = args.attrs;
+ var indices = inputs.indices;
+ var depth = attrs.depth, onValue = attrs.onValue, offValue = attrs.offValue;
+ assertNotComplex(indices, 'oneHot');
+ var indicesSize = tfjsCore.util.sizeFromShape(indices.shape);
+ var res = new Float32Array(indicesSize * depth);
+ res.fill(offValue);
+ var indicesVal = backend.data.get(indices.dataId).values;
+ for (var event = 0; event < indicesSize; ++event) {
+ if (indicesVal[event] >= 0 && indicesVal[event] < depth) {
+ res[event * depth + indicesVal[event]] = onValue;
+ }
+ }
+ return backend.makeTensorInfo(__spread(indices.shape, [depth]), 'int32', res);
+ }
+ var oneHotConfig = {
+ kernelName: tfjsCore.OneHot,
+ backendName: 'cpu',
+ kernelFunc: oneHot
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ function zerosLike(args) {
+ var inputs = args.inputs, backend = args.backend;
+ var x = inputs.x;
+ if (x.dtype === 'string') {
+ throw new Error('zerosLike is not supported for string tensors');
+ }
+ else if (x.dtype === 'complex64') {
+ var realPart = real({ inputs: { input: x }, backend: backend });
+ var r = zerosLike({ inputs: { x: realPart }, backend: backend });
+ var imagPart = imag({ inputs: { input: x }, backend: backend });
+ var i = zerosLike({ inputs: { x: imagPart }, backend: backend });
+ var result = complex({ inputs: { real: r, imag: i }, backend: backend });
+ backend.disposeIntermediateTensorInfo(realPart);
+ backend.disposeIntermediateTensorInfo(r);
+ backend.disposeIntermediateTensorInfo(imagPart);
+ backend.disposeIntermediateTensorInfo(i);
+ return result;
+ }
+ else {
+ return fill({ backend: backend, attrs: { shape: x.shape, value: 0, dtype: x.dtype } });
+ }
+ }
+ var zerosLikeConfig = {
+ kernelName: tfjsCore.ZerosLike,
+ backendName: 'cpu',
+ kernelFunc: zerosLike
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ function onesLike(args) {
+ var inputs = args.inputs, backend = args.backend;
+ var x = inputs.x;
+ if (x.dtype === 'string') {
+ throw new Error('onesLike is not supported for string tensors');
+ }
+ else if (x.dtype === 'complex64') {
+ var realPart = real({ inputs: { input: x }, backend: backend });
+ var r = onesLike({ inputs: { x: realPart }, backend: backend });
+ var imagPart = imag({ inputs: { input: x }, backend: backend });
+ var i = zerosLike({ inputs: { x: imagPart }, backend: backend });
+ var result = complex({ inputs: { real: r, imag: i }, backend: backend });
+ backend.disposeIntermediateTensorInfo(realPart);
+ backend.disposeIntermediateTensorInfo(r);
+ backend.disposeIntermediateTensorInfo(imagPart);
+ backend.disposeIntermediateTensorInfo(i);
+ return result;
+ }
+ else {
+ return fill({ backend: backend, attrs: { shape: x.shape, value: 1, dtype: x.dtype } });
+ }
+ }
+ var onesLikeConfig = {
+ kernelName: tfjsCore.OnesLike,
+ backendName: 'cpu',
+ kernelFunc: onesLike
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ function pack(args) {
+ var inputs = args.inputs, backend = args.backend, attrs = args.attrs;
+ var axis = attrs.axis;
+ if (inputs.length === 1) {
+ return expandDims({ inputs: { input: inputs[0] }, backend: backend, attrs: { dim: axis } });
+ }
+ var shape = inputs[0].shape;
+ var dtype = inputs[0].dtype;
+ inputs.forEach(function (t) {
+ tfjsCore.util.assertShapesMatch(shape, t.shape, 'All tensors passed to stack must have matching shapes');
+ tfjsCore.util.assert(dtype === t.dtype, function () { return 'All tensors passed to stack must have matching dtypes'; });
+ });
+ var intermediateTensorInfos = [];
+ var expandedTensors = inputs.map(function (t) {
+ var expandedT = expandDims({ inputs: { input: t }, backend: backend, attrs: { dim: axis } });
+ intermediateTensorInfos.push(expandedT);
+ return expandedT;
+ });
+ var result = concat({ inputs: expandedTensors, backend: backend, attrs: { axis: axis } });
+ intermediateTensorInfos.forEach(function (t) { return backend.disposeIntermediateTensorInfo(t); });
+ return result;
+ }
+ var packConfig = {
+ kernelName: tfjsCore.Pack,
+ backendName: 'cpu',
+ kernelFunc: pack
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ function padV2(args) {
+ var inputs = args.inputs, backend = args.backend, attrs = args.attrs;
+ var x = inputs.x;
+ var paddings = attrs.paddings, constantValue = attrs.constantValue;
+ assertNotComplex(x, 'pad');
+ var outShape = paddings.map(function (p, i) { return p[0] /* beforePad */ + x.shape[i] + p[1]; } /* afterPad */);
+ var start = paddings.map(function (p) { return p[0]; });
+ var xVals = backend.data.get(x.dataId).values;
+ var xSize = tfjsCore.util.sizeFromShape(x.shape);
+ var xRank = x.shape.length;
+ var xStrides = tfjsCore.util.computeStrides(x.shape);
+ var resultSize = tfjsCore.util.sizeFromShape(outShape);
+ var resultRank = outShape.length;
+ var resultStrides = tfjsCore.util.computeStrides(outShape);
+ var resVals = tfjsCore.util.getTypedArrayFromDType(x.dtype, resultSize);
+ if (constantValue !== 0) {
+ resVals.fill(constantValue);
+ }
+ for (var i = 0; i < xSize; i++) {
+ var coords = tfjsCore.util.indexToLoc(i, xRank, xStrides);
+ var outCoords = coords.map(function (c, i) { return c + start[i]; });
+ var outIndex = tfjsCore.util.locToIndex(outCoords, resultRank, resultStrides);
+ resVals[outIndex] = xVals[i];
+ }
+ var outId = backend.write(resVals, outShape, x.dtype);
+ return { dataId: outId, shape: outShape, dtype: x.dtype };
+ }
+ var padV2Config = {
+ kernelName: tfjsCore.PadV2,
+ backendName: 'cpu',
+ kernelFunc: padV2
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ var powImpl = createSimpleBinaryKernelImpl(function (a, b) { return Math.pow(a, b); });
+ var pow = binaryKernelFunc(tfjsCore.Pow, powImpl);
+ var powConfig = {
+ kernelName: tfjsCore.Pow,
+ backendName: 'cpu',
+ kernelFunc: pow
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ function range(args) {
+ var backend = args.backend, attrs = args.attrs;
+ var start = attrs.start, stop = attrs.stop, dtype = attrs.dtype, step = attrs.step;
+ var values = rangeImpl(start, stop, step, dtype);
+ return backend.makeTensorInfo([values.length], dtype, values);
+ }
+ var rangeConfig = {
+ kernelName: tfjsCore.Range,
+ backendName: 'cpu',
+ kernelFunc: range
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ var reciprocal = unaryKernelFunc(tfjsCore.Reciprocal, function (xi) { return 1 / xi; });
+ var reciprocalConfig = {
+ kernelName: tfjsCore.Reciprocal,
+ backendName: 'cpu',
+ kernelFunc: reciprocal,
+ };
+
+ function resizeBilinear(args) {
+ var inputs = args.inputs, backend = args.backend, attrs = args.attrs;
+ var images = inputs.images;
+ var alignCorners = attrs.alignCorners, halfPixelCenters = attrs.halfPixelCenters, size = attrs.size;
+ assertNotComplex(images, 'resizeBilinear');
+ var imagesStrides = tfjsCore.util.computeStrides(images.shape);
+ var _a = __read(size, 2), newHeight = _a[0], newWidth = _a[1];
+ var _b = __read(images.shape, 4), batch = _b[0], oldHeight = _b[1], oldWidth = _b[2], numChannels = _b[3];
+ var xValues = backend.data.get(images.dataId).values;
+ var result = new Float32Array(tfjsCore.util.sizeFromShape([batch, newHeight, newWidth, numChannels]));
+ var effectiveInputSize = [
+ (alignCorners && newHeight > 1) ? oldHeight - 1 : oldHeight,
+ (alignCorners && newWidth > 1) ? oldWidth - 1 : oldWidth
+ ];
+ var effectiveOutputSize = [
+ (alignCorners && newHeight > 1) ? newHeight - 1 : newHeight,
+ (alignCorners && newWidth > 1) ? newWidth - 1 : newWidth
+ ];
+ var outputIdx = 0;
+ var effectiveRowSizeRatio = effectiveInputSize[0] / effectiveOutputSize[0];
+ var effectiveColSizeRatio = effectiveInputSize[1] / effectiveOutputSize[1];
+ for (var b = 0; b < batch; b++) {
+ for (var r = 0; r < newHeight; r++) {
+ var sourceFracRow = void 0;
+ if (halfPixelCenters) {
+ sourceFracRow = effectiveRowSizeRatio * (r + 0.5) - 0.5;
+ }
+ else {
+ sourceFracRow = effectiveRowSizeRatio * r;
+ }
+ var sourceRowFloor = Math.max(0, Math.floor(sourceFracRow));
+ var rowFrac = sourceFracRow - sourceRowFloor;
+ var sourceRowCeil = Math.min(oldHeight - 1, Math.ceil(sourceFracRow));
+ var topRowOffset = b * imagesStrides[0] + sourceRowFloor * imagesStrides[1];
+ var botRowOffset = b * imagesStrides[0] + sourceRowCeil * imagesStrides[1];
+ for (var c = 0; c < newWidth; c++) {
+ var sourceFracCol = void 0;
+ if (halfPixelCenters) {
+ sourceFracCol = effectiveColSizeRatio * (c + 0.5) - 0.5;
+ }
+ else {
+ sourceFracCol = effectiveColSizeRatio * c;
+ }
+ var sourceColFloor = Math.max(0, Math.floor(sourceFracCol));
+ var colFrac = sourceFracCol - sourceColFloor;
+ var sourceColCeil = Math.min(oldWidth - 1, Math.ceil(sourceFracCol));
+ var topLeftOffest = topRowOffset + sourceColFloor * imagesStrides[2];
+ var botLeftOffset = botRowOffset + sourceColFloor * imagesStrides[2];
+ var topRightOffset = topRowOffset + sourceColCeil * imagesStrides[2];
+ var botRightOffest = botRowOffset + sourceColCeil * imagesStrides[2];
+ for (var d = 0; d < numChannels; d++) {
+ // Begin shader.
+ // Compute the fractional index of the source.
+ var topLeft = xValues[topLeftOffest + d];
+ var bottomLeft = xValues[botLeftOffset + d];
+ var topRight = xValues[topRightOffset + d];
+ var bottomRight = xValues[botRightOffest + d];
+ var top = topLeft + (topRight - topLeft) * colFrac;
+ var bottom = bottomLeft + (bottomRight - bottomLeft) * colFrac;
+ var newValue = top + (bottom - top) * rowFrac;
+ result[outputIdx++] = newValue;
+ }
+ }
+ }
+ }
+ return backend.makeTensorInfo([batch, newHeight, newWidth, numChannels], 'float32', result);
+ }
+ var resizeBilinearConfig = {
+ kernelName: tfjsCore.ResizeBilinear,
+ backendName: 'cpu',
+ kernelFunc: resizeBilinear
+ };
+
+ function resizeBilinearGrad(args) {
+ var inputs = args.inputs, backend = args.backend, attrs = args.attrs;
+ var images = inputs.images, dy = inputs.dy;
+ var alignCorners = attrs.alignCorners;
+ assertNotComplex([dy, images], 'resizeBilinearGrad');
+ var imagesStrides = tfjsCore.util.computeStrides(images.shape);
+ var _a = __read(images.shape, 4), batch = _a[0], xHeight = _a[1], xWidth = _a[2], depth = _a[3];
+ var _b = __read(dy.shape, 3), yHeight = _b[1], yWidth = _b[2];
+ var output = new Float32Array(batch * xHeight * xWidth * depth);
+ // In the backwards pass, we want to find the pixels that were generated
+ // for each pixel in the input image the forward pass and add the
+ // corresponding coefficient from dy to the gradient (with some
+ // interpolation).
+ var effectiveXSize = [
+ (alignCorners && yHeight > 1) ? xHeight - 1 : xHeight,
+ (alignCorners && yWidth > 1) ? xWidth - 1 : xWidth
+ ];
+ var effectiveYSize = [
+ (alignCorners && yHeight > 1) ? yHeight - 1 : yHeight,
+ (alignCorners && yWidth > 1) ? yWidth - 1 : yWidth
+ ];
+ var heightScale = effectiveXSize[0] / effectiveYSize[0];
+ var widthScale = effectiveXSize[1] / effectiveYSize[1];
+ // Reference implementation
+ // tslint:disable-next-line:max-line-length
+ // https://github.com/tensorflow/tensorflow/blob/3039375c86a5bbc9610c7725dcaa95d635f87ba2/tensorflow/core/kernels/resize_bilinear_op.cc#L275
+ var dyValues = backend.data.get(dy.dataId).values;
+ var offset = 0;
+ for (var b = 0; b < batch; b++) {
+ var bOffset = b * imagesStrides[0];
+ for (var r = 0; r < yHeight; r++) {
+ var dxR = r * heightScale;
+ var topDxRIndex = Math.floor(dxR);
+ var bottomDxRIndex = Math.min(Math.ceil(dxR), xHeight - 1);
+ var topDxROffset = bOffset + topDxRIndex * imagesStrides[1];
+ var bottomDxROffset = bOffset + bottomDxRIndex * imagesStrides[1];
+ var dxRLerp = dxR - topDxRIndex;
+ var inverseDxRLerp = 1.0 - dxRLerp;
+ for (var c = 0; c < yWidth; c++) {
+ var dxC = c * widthScale;
+ var leftDxCIndex = Math.floor(dxC);
+ var rightDxCIndex = Math.min(Math.ceil(dxC), xWidth - 1);
+ var dxCLerp = dxC - leftDxCIndex;
+ var inverseDxCLerp = 1.0 - dxCLerp;
+ var topLeftRCOffset = topDxROffset + leftDxCIndex * imagesStrides[2];
+ var topRightRCOffset = topDxROffset + rightDxCIndex * imagesStrides[2];
+ var bottomLeftRCOffset = bottomDxROffset + leftDxCIndex * imagesStrides[2];
+ var bottomRightRCOffset = bottomDxROffset + rightDxCIndex * imagesStrides[2];
+ var inverseDxRLerpTimesInverseDxCLerp = inverseDxRLerp * inverseDxCLerp;
+ var inverseDxRLerpTimesDxCLerp = inverseDxRLerp * dxCLerp;
+ var dxRLerpTimesInverseDxCLerp = dxRLerp * inverseDxCLerp;
+ var dxRLerpTimesDxCLerp = dxRLerp * dxCLerp;
+ for (var d = 0; d < depth; d++) {
+ var dyVal = dyValues[offset++];
+ output[topLeftRCOffset + d] +=
+ dyVal * inverseDxRLerpTimesInverseDxCLerp;
+ output[topRightRCOffset + d] += dyVal * inverseDxRLerpTimesDxCLerp;
+ output[bottomLeftRCOffset + d] += dyVal * dxRLerpTimesInverseDxCLerp;
+ output[bottomRightRCOffset + d] += dyVal * dxRLerpTimesDxCLerp;
+ }
+ }
+ }
+ }
+ return backend.makeTensorInfo([batch, xWidth, xHeight, depth], 'float32', output);
+ }
+ var resizeBilinearGradConfig = {
+ kernelName: tfjsCore.ResizeBilinearGrad,
+ backendName: 'cpu',
+ kernelFunc: resizeBilinearGrad
+ };
+
+ function resizeNearestNeighbor(args) {
+ var inputs = args.inputs, backend = args.backend, attrs = args.attrs;
+ var images = inputs.images;
+ var alignCorners = attrs.alignCorners, halfPixelCenters = attrs.halfPixelCenters, size = attrs.size;
+ assertNotComplex(images, 'resizeNearestNeighbor');
+ var imagesStrides = tfjsCore.util.computeStrides(images.shape);
+ var _a = __read(size, 2), newHeight = _a[0], newWidth = _a[1];
+ var _b = __read(images.shape, 4), batch = _b[0], oldHeight = _b[1], oldWidth = _b[2], numChannels = _b[3];
+ var xValues = backend.data.get(images.dataId).values;
+ var output = new Float32Array(batch * newHeight * newWidth * numChannels);
+ var effectiveInputSize = [
+ (alignCorners && newHeight > 1) ? oldHeight - 1 : oldHeight,
+ (alignCorners && newWidth > 1) ? oldWidth - 1 : oldWidth
+ ];
+ var effectiveOutputSize = [
+ (alignCorners && newHeight > 1) ? newHeight - 1 : newHeight,
+ (alignCorners && newWidth > 1) ? newWidth - 1 : newWidth
+ ];
+ var effectiveRowSizeRatio = effectiveInputSize[0] / effectiveOutputSize[0];
+ var effectiveColSizeRatio = effectiveInputSize[1] / effectiveOutputSize[1];
+ var outputOffset = 0;
+ for (var b = 0; b < batch; b++) {
+ var batchOffset = b * imagesStrides[0];
+ for (var r = 0; r < newHeight; r++) {
+ var sourceFracRow = halfPixelCenters ?
+ effectiveRowSizeRatio * (r + 0.5) :
+ effectiveRowSizeRatio * r;
+ var sourceNearestRow = Math.min(oldHeight - 1, alignCorners ? Math.round(sourceFracRow) : Math.floor(sourceFracRow));
+ if (halfPixelCenters) {
+ sourceNearestRow = Math.max(0, sourceNearestRow);
+ }
+ var rowOffset = batchOffset + sourceNearestRow * imagesStrides[1];
+ for (var c = 0; c < newWidth; c++) {
+ var sourceFracCol = halfPixelCenters ?
+ effectiveColSizeRatio * (c + 0.5) :
+ effectiveColSizeRatio * c;
+ var sourceNearestCol = Math.min(oldWidth - 1, alignCorners ? Math.round(sourceFracCol) :
+ Math.floor(sourceFracCol));
+ if (halfPixelCenters) {
+ sourceNearestCol = Math.max(0, sourceNearestCol);
+ }
+ var colOffset = rowOffset + sourceNearestCol * imagesStrides[2];
+ for (var d = 0; d < numChannels; d++) {
+ // Begin shader.
+ // Compute the fractional index of the source.
+ var newVal = xValues[colOffset + d];
+ output[outputOffset++] = newVal;
+ }
+ }
+ }
+ }
+ return backend.makeTensorInfo([batch, newHeight, newWidth, numChannels], images.dtype, output);
+ }
+ var resizeNearestNeighborConfig = {
+ kernelName: tfjsCore.ResizeNearestNeighbor,
+ backendName: 'cpu',
+ kernelFunc: resizeNearestNeighbor
+ };
+
+ function resizeNearestNeighborGrad(args) {
+ var inputs = args.inputs, backend = args.backend, attrs = args.attrs;
+ var images = inputs.images, dy = inputs.dy;
+ var alignCorners = attrs.alignCorners;
+ assertNotComplex([dy, images], 'resizeNearestNeighborGrad');
+ var imagesStrides = tfjsCore.util.computeStrides(images.shape);
+ var dyStrides = tfjsCore.util.computeStrides(dy.shape);
+ var _a = __read(images.shape, 4), batch = _a[0], xHeight = _a[1], xWidth = _a[2], depth = _a[3];
+ var _b = __read(dy.shape, 3), yHeight = _b[1], yWidth = _b[2];
+ var output = new Float32Array(batch * xHeight * xWidth * depth);
+ var dyValues = backend.data.get(dy.dataId).values;
+ // In the backwards pass, we want to find the pixels that were generated
+ // for each pixel in the input image the forward pass
+ var effectiveXSize = [
+ (alignCorners && yHeight > 1) ? xHeight - 1 : xHeight,
+ (alignCorners && yWidth > 1) ? xWidth - 1 : xWidth
+ ];
+ var effectiveYSize = [
+ (alignCorners && yHeight > 1) ? yHeight - 1 : yHeight,
+ (alignCorners && yWidth > 1) ? yWidth - 1 : yWidth
+ ];
+ var heightScale = effectiveXSize[0] / effectiveYSize[0];
+ var widthScale = effectiveXSize[1] / effectiveYSize[1];
+ var invHeightScale = 1 / heightScale;
+ var invWidthScale = 1 / widthScale;
+ // This defines the size of the window of values around a particular
+ // index in dy that we want to search for contributions to dx.
+ var winHeight = (Math.ceil(invHeightScale) * 2) + 2;
+ var winWidth = (Math.ceil(invWidthScale) * 2) + 2;
+ // Loop over the output space.
+ for (var b = 0; b < batch; b++) {
+ var batchOffset = b * imagesStrides[0];
+ for (var r = 0; r < xHeight; r++) {
+ var rowOffset = batchOffset + r * imagesStrides[1];
+ // Compute bounds for where in dy we will look
+ var startRLerp = Math.floor(r * invHeightScale);
+ var startDyR = Math.floor(startRLerp - (winHeight / 2));
+ for (var c = 0; c < xWidth; c++) {
+ var colOffset = rowOffset + c * imagesStrides[2];
+ // Compute bounds for where in dy we will look
+ var startCLerp = Math.floor(c * invWidthScale);
+ var startDyC = Math.floor(startCLerp - (winWidth / 2));
+ for (var d = 0; d < depth; d++) {
+ var accum = 0;
+ // loop over dy
+ for (var dyRIndex = 0; dyRIndex < winHeight; dyRIndex++) {
+ var dyR = dyRIndex + startDyR;
+ // Guard against the window exceeding the bounds of dy
+ if (dyR < 0 || dyR >= yHeight) {
+ continue;
+ }
+ var dyROffset = batchOffset + dyR * dyStrides[1];
+ var sourceFracRow = dyR * heightScale;
+ var sourceNearestRow = Math.min(xHeight - 1, alignCorners ? Math.round(sourceFracRow) :
+ Math.floor(sourceFracRow));
+ if (r !== sourceNearestRow) {
+ continue;
+ }
+ for (var dyCIndex = 0; dyCIndex < winWidth; dyCIndex++) {
+ var dyC = dyCIndex + startDyC;
+ // Guard against the window exceeding the bounds of dy
+ if (dyC < 0 || dyC >= yWidth) {
+ continue;
+ }
+ var dyCOffset = dyROffset + dyC * dyStrides[2];
+ var sourceFracCol = dyC * widthScale;
+ var sourceNearestCol = Math.min(xWidth - 1, alignCorners ? Math.round(sourceFracCol) :
+ Math.floor(sourceFracCol));
+ if (c === sourceNearestCol) {
+ accum += dyValues[dyCOffset + d];
+ }
+ }
+ }
+ output[colOffset + d] = accum;
+ }
+ }
+ }
+ }
+ return backend.makeTensorInfo(images.shape, images.dtype, output);
+ }
+ var resizeNearestNeighborGradConfig = {
+ kernelName: tfjsCore.ResizeNearestNeighborGrad,
+ backendName: 'cpu',
+ kernelFunc: resizeNearestNeighborGrad
+ };
+
+ function reverse(args) {
+ var inputs = args.inputs, backend = args.backend, attrs = args.attrs;
+ var x = inputs.x;
+ var dims = attrs.dims;
+ assertNotComplex(x, 'reverse');
+ var xRank = x.shape.length;
+ var $dims = tfjsCore.util.parseAxisParam(dims, x.shape);
+ if (xRank === 0) {
+ return identity({ inputs: { x: x }, backend: backend });
+ }
+ var outBuf = new tfjsCore.TensorBuffer(x.shape, x.dtype);
+ var xBuf = backend.bufferSync(x);
+ var _loop_1 = function (i) {
+ var outLoc = outBuf.indexToLoc(i);
+ var inLoc = outLoc.slice();
+ $dims.forEach(function (d) { return inLoc[d] = x.shape[d] - 1 - inLoc[d]; });
+ outBuf.set.apply(outBuf, __spread([xBuf.get.apply(xBuf, __spread(inLoc))], outLoc));
+ };
+ for (var i = 0; i < outBuf.size; i++) {
+ _loop_1(i);
+ }
+ return backend.makeTensorInfo(outBuf.shape, outBuf.dtype, outBuf.values);
+ }
+ var reverseConfig = {
+ kernelName: tfjsCore.Reverse,
+ backendName: 'cpu',
+ kernelFunc: reverse
+ };
+
+ var rotateWithOffsetConfig = {
+ kernelName: tfjsCore.RotateWithOffset,
+ backendName: 'cpu',
+ kernelFunc: function (_a) {
+ var inputs = _a.inputs, attrs = _a.attrs, backend = _a.backend;
+ var image = inputs.image;
+ var radians = attrs.radians, fillValue = attrs.fillValue, center = attrs.center;
+ var cpuBackend = backend;
+ var output = tfjsCore.util.getTypedArrayFromDType(image.dtype, tfjsCore.util.sizeFromShape(image.shape));
+ var _b = __read(image.shape, 4), batch = _b[0], imageHeight = _b[1], imageWidth = _b[2], numChannels = _b[3];
+ var _c = __read(tfjsCore.backend_util.getImageCenter(center, imageHeight, imageWidth), 2), centerX = _c[0], centerY = _c[1];
+ var fullOpacityValue = 255;
+ var sinFactor = Math.sin(radians);
+ var cosFactor = Math.cos(radians);
+ var imageVals = cpuBackend.data.get(image.dataId).values;
+ for (var batchIdx = 0; batchIdx < batch; batchIdx++) {
+ var batchOffset = batchIdx * imageWidth * imageHeight * numChannels;
+ for (var row = 0; row < imageHeight; row++) {
+ var rowOffset = row * (imageWidth * numChannels);
+ for (var col = 0; col < imageWidth; col++) {
+ var colOffset = col * numChannels;
+ for (var channel = 0; channel < numChannels; channel++) {
+ var coords = [batch, row, col, channel];
+ var x = coords[2];
+ var y = coords[1];
+ // coordX/coordY are the result of rotating and translating x/y.
+ var coordX = (x - centerX) * cosFactor - (y - centerY) * sinFactor;
+ var coordY = (x - centerX) * sinFactor + (y - centerY) * cosFactor;
+ coordX = Math.round(coordX + centerX);
+ coordY = Math.round(coordY + centerY);
+ var outputValue = fillValue;
+ if (typeof fillValue !== 'number') {
+ if (channel === 3) {
+ outputValue = fullOpacityValue;
+ }
+ else {
+ outputValue = fillValue[channel];
+ }
+ }
+ // If the coordinate position falls within the image boundaries...
+ if (coordX >= 0 && coordX < imageWidth && coordY >= 0 &&
+ coordY < imageHeight) {
+ // set the output to the image value at the coordinate position.
+ var rotatedRowOffset = coordY * (imageWidth * numChannels);
+ var rotatedColOffset = coordX * numChannels;
+ var imageIdx = batchOffset + rotatedRowOffset + rotatedColOffset + channel;
+ outputValue = imageVals[imageIdx];
+ }
+ var outIdx = batchOffset + rowOffset + colOffset + channel;
+ output[outIdx] = outputValue;
+ }
+ }
+ }
+ }
+ var dataId = cpuBackend.write(output, image.shape, image.dtype);
+ return { dataId: dataId, shape: image.shape, dtype: image.dtype };
+ }
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ var round = unaryKernelFunc(tfjsCore.Round, function (xi) {
+ // The algorithm is based on banker's rounding.
+ var base = Math.floor(xi);
+ if (xi - base < 0.5) {
+ return Math.floor(xi);
+ }
+ else if (xi - base > 0.5) {
+ return Math.ceil(xi);
+ }
+ else {
+ if (base % 2.0 === 0.0) {
+ return base;
+ }
+ else {
+ return base + 1.0;
+ }
+ }
+ });
+ var roundConfig = {
+ kernelName: tfjsCore.Round,
+ backendName: 'cpu',
+ kernelFunc: round,
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ function scatterImpl(indices, updates, shape, outputSize, sliceSize, numUpdates, sliceRank, strides, defaultValue, sumDupeIndices) {
+ var flattenShape = [outputSize / sliceSize, sliceSize];
+ var indicesData = indices.values;
+ var updatesData = updates.values;
+ if (outputSize === 0) {
+ return tfjsCore.buffer(shape, updates.dtype);
+ }
+ var outBuf = tfjsCore.buffer(flattenShape, updates.dtype);
+ outBuf.values.fill(defaultValue);
+ for (var i = 0; i < numUpdates; i++) {
+ var index = [];
+ var flattenIndex = 0;
+ for (var j = 0; j < sliceRank; j++) {
+ var dim = indicesData[i * sliceRank + j];
+ index.push(dim);
+ flattenIndex += dim * strides[j];
+ }
+ if (flattenIndex < 0 || flattenIndex >= outputSize / sliceSize) {
+ throw new Error("Invalid indices: " + index + " does not index into " + shape);
+ }
+ for (var k = 0; k < sliceSize; k++) {
+ if (sumDupeIndices) {
+ outBuf.values[flattenIndex * sliceSize + k] +=
+ updatesData[i * sliceSize + k];
+ }
+ else {
+ outBuf.values[flattenIndex * sliceSize + k] = updates.rank === 0 ?
+ updatesData[0] :
+ updatesData[i * sliceSize + k];
+ }
+ }
+ }
+ return outBuf;
+ }
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ function scatterNd(args) {
+ var inputs = args.inputs, backend = args.backend, attrs = args.attrs;
+ var indices = inputs.indices, updates = inputs.updates;
+ var shape = attrs.shape;
+ var _a = tfjsCore.backend_util.calculateShapes(updates, indices, shape), sliceRank = _a.sliceRank, numUpdates = _a.numUpdates, sliceSize = _a.sliceSize, strides = _a.strides, outputSize = _a.outputSize;
+ var sumDupeIndices = true;
+ var indicesBuf = backend.bufferSync(indices);
+ var updatesBuf = backend.bufferSync(updates);
+ var outBuf = scatterImpl(indicesBuf, updatesBuf, shape, outputSize, sliceSize, numUpdates, sliceRank, strides, 0 /* defaultValue */, sumDupeIndices);
+ return backend.makeTensorInfo(shape, outBuf.dtype, outBuf.values);
+ }
+ var scatterNdConfig = {
+ kernelName: tfjsCore.ScatterNd,
+ backendName: 'cpu',
+ kernelFunc: scatterNd
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ function select(args) {
+ var inputs = args.inputs, backend = args.backend;
+ var condition = inputs.condition, t = inputs.t, e = inputs.e;
+ assertNotComplex([condition, t, e], 'select');
+ var conditionRank = condition.shape.length;
+ var values = backend.data.get(condition.dataId).values;
+ var tValues = backend.data.get(t.dataId).values;
+ var eValues = backend.data.get(e.dataId).values;
+ var resultDtype = tfjsCore.upcastType(t.dtype, e.dtype);
+ var newValues = tfjsCore.util.makeZerosTypedArray(tfjsCore.util.sizeFromShape(t.shape), resultDtype);
+ var index = 0;
+ var offset = conditionRank === 0 || conditionRank > 1 || t.shape.length === 1 ?
+ 1 :
+ tfjsCore.util.sizeFromShape(t.shape.slice(1));
+ for (var i = 0; i < values.length; i++) {
+ for (var j = 0; j < offset; j++) {
+ if (values[i] === 1) {
+ newValues[index++] = tValues[i];
+ }
+ else {
+ newValues[index++] = eValues[i];
+ }
+ }
+ }
+ return backend.makeTensorInfo(t.shape, resultDtype, newValues);
+ }
+ var selectConfig = {
+ kernelName: tfjsCore.Select,
+ backendName: 'cpu',
+ kernelFunc: select
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ var scaleAlpha = tfjsCore.backend_util.SELU_SCALEALPHA;
+ var scale = tfjsCore.backend_util.SELU_SCALE;
+ var selu = unaryKernelFunc(tfjsCore.Selu, function (xi) {
+ if (xi >= 0) {
+ return scale * xi;
+ }
+ else {
+ return scaleAlpha * (Math.exp(xi) - 1);
+ }
+ });
+ var seluConfig = {
+ kernelName: tfjsCore.Selu,
+ backendName: 'cpu',
+ kernelFunc: selu,
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ var sign = unaryKernelFunc(tfjsCore.Sign, function (xi) {
+ if (xi < 0) {
+ return -1;
+ }
+ else if (xi > 0) {
+ return 1;
+ }
+ else {
+ return 0;
+ }
+ });
+ var signConfig = {
+ kernelName: tfjsCore.Sign,
+ backendName: 'cpu',
+ kernelFunc: sign,
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ var sin = unaryKernelFunc(tfjsCore.Sin, function (xi) { return Math.sin(xi); });
+ var sinConfig = {
+ kernelName: tfjsCore.Sin,
+ backendName: 'cpu',
+ kernelFunc: sin,
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ var sinh = unaryKernelFunc(tfjsCore.Sinh, function (xi) { return Math.sinh(xi); });
+ var sinhConfig = {
+ kernelName: tfjsCore.Sinh,
+ backendName: 'cpu',
+ kernelFunc: sinh,
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ // mirrors the implementation of tf.nn.softplus: https://goo.gl/vkcvwX
+ // epsilon is the difference between 1.0 and the next representable float.
+ // For a single precision 32 bit float this should be 2^-23, see:
+ // https://math.byu.edu/~schow/work/IEEEFloatingPoint.htm
+ var epsilon = 1.1920928955078125e-7;
+ var threshold = Math.log(epsilon) + 2.0;
+ var softplus = unaryKernelFunc(tfjsCore.Softplus, function (xi) {
+ // Value above which exp(x) may overflow, but softplus(x) == x
+ // is within machine epsilon.
+ var tooLarge = xi > -threshold;
+ // Value below which exp(x) may underflow, but softplus(x) == exp(x)
+ // is within machine epsilon.
+ var tooSmall = xi < threshold;
+ var expX = Math.exp(xi);
+ var result;
+ if (tooSmall) {
+ result = expX;
+ }
+ else if (tooLarge) {
+ result = xi;
+ }
+ else {
+ result = Math.log(1.0 + expX);
+ }
+ return result;
+ });
+ var softplusConfig = {
+ kernelName: tfjsCore.Softplus,
+ backendName: 'cpu',
+ kernelFunc: softplus,
+ };
+
+ function spaceToBatchND(args) {
+ var inputs = args.inputs, backend = args.backend, attrs = args.attrs;
+ var x = inputs.x;
+ var blockShape = attrs.blockShape, paddings = attrs.paddings;
+ assertNotComplex([x], 'spaceToBatchND');
+ var prod = tfjsCore.util.sizeFromShape(blockShape);
+ var completePaddings = [[0, 0]];
+ completePaddings.push.apply(completePaddings, __spread(paddings));
+ for (var i = 1 + blockShape.length; i < x.shape.length; ++i) {
+ completePaddings.push([0, 0]);
+ }
+ var paddedX = padV2Config.kernelFunc({
+ inputs: { x: x },
+ backend: backend,
+ attrs: { paddings: completePaddings, constantValue: 0 }
+ });
+ var reshapedPaddedShape = tfjsCore.backend_util.getReshaped(paddedX.shape, blockShape, prod, false);
+ var permutedReshapedPaddedPermutation = tfjsCore.backend_util.getPermuted(reshapedPaddedShape.length, blockShape.length, false);
+ var flattenShape = tfjsCore.backend_util.getReshapedPermuted(paddedX.shape, blockShape, prod, false);
+ var reshapeInputs = { x: paddedX };
+ var reshapeAttrs = { shape: reshapedPaddedShape };
+ var paddedXReshaped = reshape({ inputs: reshapeInputs, backend: backend, attrs: reshapeAttrs });
+ var transposeInputs = { x: paddedXReshaped };
+ var transposeAttrs = { perm: permutedReshapedPaddedPermutation };
+ var paddedXT = transpose({ inputs: transposeInputs, backend: backend, attrs: transposeAttrs });
+ var resultReshapeInputs = { x: paddedXT };
+ var resultReshapeAttrs = { shape: flattenShape };
+ var result = reshape({ inputs: resultReshapeInputs, backend: backend, attrs: resultReshapeAttrs });
+ backend.disposeIntermediateTensorInfo(paddedX);
+ backend.disposeIntermediateTensorInfo(paddedXReshaped);
+ backend.disposeIntermediateTensorInfo(paddedXT);
+ return result;
+ }
+ var spaceToBatchNDConfig = {
+ kernelName: tfjsCore.SpaceToBatchND,
+ backendName: 'cpu',
+ kernelFunc: spaceToBatchND
+ };
+
+ function sparseFillEmptyRows(args) {
+ var inputs = args.inputs, backend = args.backend;
+ var indices = inputs.indices, values = inputs.values, denseShape = inputs.denseShape, defaultValue = inputs.defaultValue;
+ if (denseShape.shape.length !== 1) {
+ throw new Error("Dense shape must be a vector, saw:\n " + denseShape.shape);
+ }
+ if (indices.shape.length !== 2) {
+ throw new Error("Indices must be a matrix, saw:\n " + indices.shape);
+ }
+ if (values.shape.length !== 1) {
+ throw new Error("Values must be a vector, saw:\n " + values.shape);
+ }
+ if (defaultValue.shape.length !== 0) {
+ throw new Error("Default value must be a scalar, saw:\n " + defaultValue.shape);
+ }
+ var $indices = backend.data.get(indices.dataId).values;
+ var $values = backend.data.get(values.dataId).values;
+ var $denseShape = backend.data.get(denseShape.dataId).values;
+ var $defaultValue = backend.data.get(defaultValue.dataId).values[0];
+ var _a = __read(sparseFillEmptyRowsImpl($indices, indices.shape, indices.dtype, $values, values.dtype, $denseShape, $defaultValue), 5), outputIndices = _a[0], outputIndicesShape = _a[1], outputValues = _a[2], emptyRowIndicator = _a[3], reverseIndexMap = _a[4];
+ return [
+ backend.makeTensorInfo(outputIndicesShape, indices.dtype, outputIndices),
+ backend.makeTensorInfo([outputIndicesShape[0]], values.dtype, outputValues),
+ backend.makeTensorInfo([emptyRowIndicator.length], 'bool', new Uint8Array(emptyRowIndicator.map(function (value) { return Number(value); }))),
+ backend.makeTensorInfo([reverseIndexMap.length], indices.dtype, new Int32Array(reverseIndexMap)),
+ ];
+ }
+ var sparseFillEmptyRowsConfig = {
+ kernelName: tfjsCore.SparseFillEmptyRows,
+ backendName: 'cpu',
+ kernelFunc: sparseFillEmptyRows,
+ };
+
+ function sparseReshape(args) {
+ var inputs = args.inputs, backend = args.backend;
+ var inputIndices = inputs.inputIndices, inputShape = inputs.inputShape, newShape = inputs.newShape;
+ if (inputIndices.shape.length !== 2) {
+ throw new Error("Input indices should be a matrix but received shape\n " + inputIndices.shape);
+ }
+ if (inputShape.shape.length !== 1) {
+ throw new Error("Input shape should be a vector but received shape\n " + inputShape.shape);
+ }
+ if (newShape.shape.length !== 1) {
+ throw new Error("Target shape should be a vector but received shape " + newShape.shape);
+ }
+ var $inputShape = Array.from(backend.data.get(inputShape.dataId).values);
+ var $inputIndices = backend.data.get(inputIndices.dataId).values;
+ var targetShape = Array.from(backend.data.get(newShape.dataId).values);
+ var _a = __read(sparseReshapeImpl($inputIndices, inputIndices.shape, inputIndices.dtype, $inputShape, targetShape), 3), newIndices = _a[0], indicesShape = _a[1], outputShape = _a[2];
+ return [
+ backend.makeTensorInfo(indicesShape, inputIndices.dtype, newIndices),
+ backend.makeTensorInfo([outputShape.length], newShape.dtype, new Int32Array(outputShape)),
+ ];
+ }
+ var sparseReshapeConfig = {
+ kernelName: tfjsCore.SparseReshape,
+ backendName: 'cpu',
+ kernelFunc: sparseReshape,
+ };
+
+ function sparseSegmentMean(args) {
+ var inputs = args.inputs, backend = args.backend;
+ var data = inputs.data, indices = inputs.indices, segmentIds = inputs.segmentIds;
+ if (data.shape.length < 1) {
+ throw new Error("Data should be at least 1 dimensional but received scalar");
+ }
+ if (indices.shape.length !== 1) {
+ throw new Error("Indices should be a vector but received shape\n " + indices.shape);
+ }
+ if (segmentIds.shape.length !== 1) {
+ throw new Error("Segment ids should be a vector but received shape\n " + segmentIds.shape);
+ }
+ if (indices.shape[0] !== segmentIds.shape[0]) {
+ throw new Error("segmentIds and indices should have same size.");
+ }
+ var $data = backend.data.get(data.dataId).values;
+ var $indices = backend.data.get(indices.dataId).values;
+ var $segmentIds = backend.data.get(segmentIds.dataId).values;
+ var _a = __read(sparseSegmentReductionImpl($data, data.shape, data.dtype, $indices, $segmentIds, true), 2), outputData = _a[0], outputDataShape = _a[1];
+ return backend.makeTensorInfo(outputDataShape, data.dtype, outputData);
+ }
+ var sparseSegmentMeanConfig = {
+ kernelName: tfjsCore.SparseSegmentMean,
+ backendName: 'cpu',
+ kernelFunc: sparseSegmentMean,
+ };
+
+ function sparseSegmentSum(args) {
+ var inputs = args.inputs, backend = args.backend;
+ var data = inputs.data, indices = inputs.indices, segmentIds = inputs.segmentIds;
+ if (data.shape.length < 1) {
+ throw new Error("Data should be at least 1 dimensional but received scalar");
+ }
+ if (indices.shape.length !== 1) {
+ throw new Error("Indices should be a vector but received shape\n " + indices.shape);
+ }
+ if (segmentIds.shape.length !== 1) {
+ throw new Error("Segment ids should be a vector but received shape\n " + segmentIds.shape);
+ }
+ if (indices.shape[0] !== segmentIds.shape[0]) {
+ throw new Error("segmentIds and indices should have same size.");
+ }
+ var $data = backend.data.get(data.dataId).values;
+ var $indices = backend.data.get(indices.dataId).values;
+ var $segmentIds = backend.data.get(segmentIds.dataId).values;
+ var _a = __read(sparseSegmentReductionImpl($data, data.shape, data.dtype, $indices, $segmentIds), 2), outputData = _a[0], outputDataShape = _a[1];
+ return backend.makeTensorInfo(outputDataShape, data.dtype, outputData);
+ }
+ var sparseSegmentSumConfig = {
+ kernelName: tfjsCore.SparseSegmentSum,
+ backendName: 'cpu',
+ kernelFunc: sparseSegmentSum,
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ function sparseToDense(args) {
+ var inputs = args.inputs, backend = args.backend, attrs = args.attrs;
+ var sparseIndices = inputs.sparseIndices, sparseValues = inputs.sparseValues, defaultValue = inputs.defaultValue;
+ var outputShape = attrs.outputShape;
+ var _a = tfjsCore.backend_util.calculateShapes(sparseValues, sparseIndices, outputShape), sliceRank = _a.sliceRank, numUpdates = _a.numUpdates, sliceSize = _a.sliceSize, strides = _a.strides, outputSize = _a.outputSize;
+ var sumDupeIndices = false;
+ var indicesBuf = backend.bufferSync(sparseIndices);
+ var updatesBuf = backend.bufferSync(sparseValues);
+ var $defaultValue = backend.data.get(defaultValue.dataId).values[0];
+ var outBuf = scatterImpl(indicesBuf, updatesBuf, outputShape, outputSize, sliceSize, numUpdates, sliceRank, strides, $defaultValue, sumDupeIndices);
+ return backend.makeTensorInfo(outputShape, outBuf.dtype, outBuf.values);
+ }
+ var sparseToDenseConfig = {
+ kernelName: tfjsCore.SparseToDense,
+ backendName: 'cpu',
+ kernelFunc: sparseToDense
+ };
+
+ function splitV(args) {
+ var inputs = args.inputs, backend = args.backend, attrs = args.attrs;
+ var x = inputs.x;
+ var numOrSizeSplits = attrs.numOrSizeSplits, axis = attrs.axis;
+ var $axis = tfjsCore.util.parseAxisParam(axis, x.shape)[0];
+ var splitSizes = tfjsCore.backend_util.prepareSplitSize(x, numOrSizeSplits, $axis);
+ var begin = new Array(x.shape.length).fill(0);
+ var size = x.shape.slice();
+ return splitSizes.map(function (s) {
+ var sliceSize = __spread(size);
+ sliceSize[$axis] = s;
+ var sliceT = slice({ inputs: { x: x }, backend: backend, attrs: { begin: begin, size: sliceSize } });
+ begin[$axis] += s;
+ return sliceT;
+ });
+ }
+ var splitVConfig = {
+ kernelName: tfjsCore.SplitV,
+ backendName: 'cpu',
+ kernelFunc: splitV
+ };
+
+ /**
+ * @license
+ * Copyright 2019 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ var squareConfig = {
+ kernelName: tfjsCore.Square,
+ backendName: 'cpu',
+ kernelFunc: function (_a) {
+ var inputs = _a.inputs, backend = _a.backend;
+ var x = inputs.x;
+ var cpuBackend = backend;
+ assertNotComplex(x, 'square');
+ var values = cpuBackend.data.get(x.dataId).values;
+ var newValues = new Float32Array(values.length);
+ for (var i = 0; i < values.length; ++i) {
+ var value = values[i];
+ newValues[i] = value * value;
+ }
+ var dataId = cpuBackend.write(newValues, x.shape, x.dtype);
+ return { dataId: dataId, shape: x.shape, dtype: x.dtype };
+ }
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ var step = unaryKernelFunc(tfjsCore.Step, function (xi, attrs) {
+ var stepAttrs = attrs;
+ if (isNaN(xi)) {
+ return NaN;
+ }
+ else {
+ return xi > 0 ? 1 : stepAttrs.alpha;
+ }
+ });
+ var stepConfig = {
+ kernelName: tfjsCore.Step,
+ backendName: 'cpu',
+ kernelFunc: step,
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ function stridedSlice(args) {
+ var inputs = args.inputs, backend = args.backend, attrs = args.attrs;
+ var x = inputs.x;
+ var begin = attrs.begin, end = attrs.end, strides = attrs.strides, beginMask = attrs.beginMask, endMask = attrs.endMask, ellipsisMask = attrs.ellipsisMask, newAxisMask = attrs.newAxisMask, shrinkAxisMask = attrs.shrinkAxisMask;
+ assertNotComplex(x, 'stridedSlice');
+ var _a = tfjsCore.slice_util.sliceInfo(x.shape, begin, end, strides, beginMask, endMask, ellipsisMask, newAxisMask, shrinkAxisMask), finalShapeSparse = _a.finalShapeSparse, finalShape = _a.finalShape, isIdentity = _a.isIdentity, sliceDim0 = _a.sliceDim0, isSimpleSlice = _a.isSimpleSlice, $begin = _a.begin, $end = _a.end, $strides = _a.strides;
+ var result;
+ // ref:
+ // https://github.com/tensorflow/tensorflow/blob/master/tensorflow/core/kernels/strided_slice_op.cc
+ if (isIdentity) {
+ // Optimization #1, slice is a no-op plus reshape
+ result = reshape({ inputs: { x: x }, backend: backend, attrs: { shape: finalShape } });
+ }
+ else if (sliceDim0 || isSimpleSlice) {
+ // Optimization #2, slice is memory contiguous (only occurs in dim 0)
+ tfjsCore.util.assert(x.shape.length >= 1, function () { return "Input must have rank at least 1, got: " + x.shape.length; });
+ var size = tfjsCore.slice_util.computeOutShape($begin, $end, $strides);
+ // To tolerate begin[0] > end[0] (a 0-output slice), we min(begin, end).
+ var sliced = slice({ inputs: { x: x }, backend: backend, attrs: { begin: $begin, size: size } });
+ result =
+ reshape({ inputs: { x: sliced }, backend: backend, attrs: { shape: finalShape } });
+ backend.disposeIntermediateTensorInfo(sliced);
+ }
+ else {
+ var xBuf = backend.bufferSync(x);
+ var outBuf = stridedSliceImpl(finalShapeSparse, xBuf, $strides, $begin);
+ result = backend.makeTensorInfo(finalShape, outBuf.dtype, outBuf.values);
+ }
+ return result;
+ }
+ var stridedSliceConfig = {
+ kernelName: tfjsCore.StridedSlice,
+ backendName: 'cpu',
+ kernelFunc: stridedSlice
+ };
+
+ function stringNGrams(args) {
+ var inputs = args.inputs, backend = args.backend, attrs = args.attrs;
+ var separator = attrs.separator, nGramWidths = attrs.nGramWidths, leftPad = attrs.leftPad, rightPad = attrs.rightPad, padWidth = attrs.padWidth, preserveShortSequences = attrs.preserveShortSequences;
+ var data = inputs.data, dataSplits = inputs.dataSplits;
+ var $data = backend.data.get(data.dataId).values;
+ var $dataSplits = backend.data.get(dataSplits.dataId).values;
+ var _a = __read(stringNGramsImpl($data, $dataSplits, separator, nGramWidths, leftPad, rightPad, padWidth, preserveShortSequences), 2), nGrams = _a[0], nGramsSplits = _a[1];
+ return [
+ backend.makeTensorInfo([nGrams.length], 'string', nGrams),
+ backend.makeTensorInfo(dataSplits.shape, 'int32', nGramsSplits),
+ ];
+ }
+ var stringNGramsConfig = {
+ kernelName: tfjsCore.StringNGrams,
+ backendName: 'cpu',
+ kernelFunc: stringNGrams,
+ };
+
+ function stringSplit(args) {
+ var inputs = args.inputs, backend = args.backend, attrs = args.attrs;
+ var skipEmpty = attrs.skipEmpty;
+ var input = inputs.input, delimiter = inputs.delimiter;
+ if (input.dtype !== 'string') {
+ throw new Error('Input must be of datatype string');
+ }
+ if (input.shape.length !== 1) {
+ throw new Error("Input must be a vector, got shape: " + input.shape);
+ }
+ if (delimiter.shape.length !== 0) {
+ throw new Error("Delimiter must be a scalar, got shape: " + delimiter.shape);
+ }
+ var $input = backend.data.get(input.dataId).values;
+ var $delimiter = backend.data.get(delimiter.dataId).values[0];
+ var _a = __read(stringSplitImpl($input, $delimiter, skipEmpty), 3), indices = _a[0], values = _a[1], shape = _a[2];
+ var outputSize = values.length;
+ return [
+ backend.makeTensorInfo([outputSize, 2], 'int32', indices),
+ backend.makeTensorInfo([outputSize], 'string', values),
+ backend.makeTensorInfo([2], 'int32', new Int32Array(shape))
+ ];
+ }
+ var stringSplitConfig = {
+ kernelName: tfjsCore.StringSplit,
+ backendName: 'cpu',
+ kernelFunc: stringSplit,
+ };
+
+ /**
+ * @license
+ * Copyright 2021 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ function stringToHashBucketFast(args) {
+ var inputs = args.inputs, backend = args.backend, attrs = args.attrs;
+ var numBuckets = attrs.numBuckets;
+ var input = inputs.input;
+ if (input.dtype !== 'string') {
+ throw new Error('Input must be of datatype string');
+ }
+ if (numBuckets <= 0) {
+ throw new Error("Number of buckets must be at least 1");
+ }
+ var $input = backend.data.get(input.dataId).values;
+ var output = stringToHashBucketFastImpl($input, numBuckets);
+ return backend.makeTensorInfo(input.shape, 'int32', output);
+ }
+ var stringToHashBucketFastConfig = {
+ kernelName: tfjsCore.StringToHashBucketFast,
+ backendName: 'cpu',
+ kernelFunc: stringToHashBucketFast,
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ var tan = unaryKernelFunc(tfjsCore.Tan, function (xi) { return Math.tan(xi); });
+ var tanConfig = {
+ kernelName: tfjsCore.Tan,
+ backendName: 'cpu',
+ kernelFunc: tan,
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ var tanh = unaryKernelFunc(tfjsCore.Tanh, function (xi) { return Math.tanh(xi); });
+ var tanhConfig = {
+ kernelName: tfjsCore.Tanh,
+ backendName: 'cpu',
+ kernelFunc: tanh,
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ function tile(args) {
+ var inputs = args.inputs, backend = args.backend, attrs = args.attrs;
+ var x = inputs.x;
+ var reps = attrs.reps;
+ assertNotComplex(x, 'tile');
+ var outBuf = tileImpl(backend.bufferSync(x), reps);
+ return backend.makeTensorInfo(outBuf.shape, outBuf.dtype, outBuf.values);
+ }
+ var tileConfig = {
+ kernelName: tfjsCore.Tile,
+ backendName: 'cpu',
+ kernelFunc: tile
+ };
+
+ function topK(args) {
+ var inputs = args.inputs, backend = args.backend, attrs = args.attrs;
+ var x = inputs.x;
+ var k = attrs.k, sorted = attrs.sorted;
+ assertNotComplex(x, 'topk');
+ var xVals = backend.data.get(x.dataId).values;
+ var _a = __read(topKImpl(xVals, x.shape, x.dtype, k, sorted), 2), allTopKVals = _a[0], allTopKIndices = _a[1];
+ return [
+ backend.makeTensorInfo(allTopKVals.shape, allTopKVals.dtype, allTopKVals.values),
+ backend.makeTensorInfo(allTopKIndices.shape, allTopKIndices.dtype, allTopKIndices.values)
+ ];
+ }
+ var topKConfig = {
+ kernelName: tfjsCore.TopK,
+ backendName: 'cpu',
+ kernelFunc: topK
+ };
+
+ function transform(args) {
+ var inputs = args.inputs, attrs = args.attrs, backend = args.backend;
+ var image = inputs.image, transforms = inputs.transforms;
+ var interpolation = attrs.interpolation, fillMode = attrs.fillMode, fillValue = attrs.fillValue, outputShape = attrs.outputShape;
+ var _a = __read(image.shape, 4), batch = _a[0], imageHeight = _a[1], imageWidth = _a[2], numChannels = _a[3];
+ var _b = __read(outputShape != null ? outputShape : [imageHeight, imageWidth], 2), outHeight = _b[0], outWidth = _b[1];
+ var outShape = [batch, outHeight, outWidth, numChannels];
+ var strides = tfjsCore.util.computeStrides(image.shape);
+ var batchStride = strides[0];
+ var rowStride = strides[1];
+ var colStride = strides[2];
+ var outVals = tfjsCore.util.getTypedArrayFromDType(image.dtype, tfjsCore.util.sizeFromShape(outShape));
+ outVals.fill(fillValue);
+ var imageVals = backend.data.get(image.dataId).values;
+ var transformVals = backend.data.get(transforms.dataId).values;
+ // Ref TF implementation:
+ // https://github.com/tensorflow/tensorflow/blob/master/tensorflow/core/kernels/image/image_ops.h
+ for (var b = 0; b < batch; ++b) {
+ var transform_1 = transforms.shape[0] === 1 ?
+ transformVals :
+ transformVals.subarray(b * 8, b * 8 + 8);
+ for (var outY = 0; outY < outHeight; ++outY) {
+ for (var outX = 0; outX < outWidth; ++outX) {
+ for (var channel = 0; channel < numChannels; ++channel) {
+ var val = void 0;
+ var projection = transform_1[6] * outX + transform_1[7] * outY + 1;
+ if (projection === 0) {
+ // Return the fill value for infinite coordinates,
+ // which are outside the input image
+ continue;
+ }
+ var inX = (transform_1[0] * outX + transform_1[1] * outY + transform_1[2]) /
+ projection;
+ var inY = (transform_1[3] * outX + transform_1[4] * outY + transform_1[5]) /
+ projection;
+ var x = mapCoord(inX, imageWidth, fillMode);
+ var y = mapCoord(inY, imageHeight, fillMode);
+ switch (interpolation) {
+ case 'nearest':
+ val = nearestInterpolation(imageVals, imageHeight, imageWidth, batchStride, rowStride, colStride, b, y, x, channel, fillValue);
+ break;
+ case 'bilinear':
+ val = bilinearInterpolation(imageVals, imageHeight, imageWidth, batchStride, rowStride, colStride, b, y, x, channel, fillValue);
+ break;
+ default:
+ throw new Error("Error in Transform: Expect 'nearest' or " +
+ ("'bilinear', but got " + interpolation));
+ }
+ var ind = b * batchStride + outY * rowStride + outX * colStride + channel;
+ outVals[ind] = val;
+ }
+ }
+ }
+ return backend.makeTensorInfo(outShape, image.dtype, outVals);
+ }
+ var dataId = backend.write(outVals, outShape, image.dtype);
+ return { dataId: dataId, shape: image.shape, dtype: image.dtype };
+ }
+ var transformConfig = {
+ kernelName: tfjsCore.Transform,
+ backendName: 'cpu',
+ kernelFunc: transform
+ };
+ function mapCoord(outCoord, len, mode) {
+ switch (mode) {
+ case 'reflect':
+ return mapCoordReflect(outCoord, len);
+ case 'wrap':
+ return mapCoordWrap(outCoord, len);
+ case 'nearest':
+ return mapCoordNearest(outCoord, len);
+ case 'constant':
+ default:
+ return mapCoordConstant(outCoord);
+ }
+ }
+ function mapCoordReflect(outCoord, len) {
+ // Reflect [abcd] to [dcba|abcd|dcba].
+ var inCoord = outCoord;
+ if (inCoord < 0) {
+ if (len <= 1) {
+ inCoord = 0;
+ }
+ else {
+ var sz2 = 2 * len;
+ if (inCoord < sz2) {
+ inCoord = sz2 * Math.trunc(-inCoord / sz2) + inCoord;
+ }
+ inCoord = inCoord < -len ? inCoord + sz2 : -inCoord - 1;
+ }
+ }
+ else if (inCoord > len - 1) {
+ if (len <= 1) {
+ inCoord = 0;
+ }
+ else {
+ var sz2 = 2 * len;
+ inCoord -= sz2 * Math.trunc(inCoord / sz2);
+ if (inCoord >= len) {
+ inCoord = sz2 - inCoord - 1;
+ }
+ }
+ }
+ // clamp is necessary because when outCoord = 3.5 and len = 4,
+ // inCoord = 3.5 and will be rounded to 4 in nearest interpolation.
+ return tfjsCore.util.clamp(0, inCoord, len - 1);
+ }
+ function mapCoordWrap(outCoord, len) {
+ // Wrap [abcd] to [abcd|abcd|abcd].
+ var inCoord = outCoord;
+ if (inCoord < 0) {
+ if (len <= 1) {
+ inCoord = 0;
+ }
+ else {
+ var sz = len - 1;
+ inCoord += len * (Math.trunc(-inCoord / sz) + 1);
+ }
+ }
+ else if (inCoord > len - 1) {
+ if (len <= 1) {
+ inCoord = 0;
+ }
+ else {
+ var sz = len - 1;
+ inCoord -= len * Math.trunc(inCoord / sz);
+ }
+ }
+ // clamp is necessary because when outCoord = -0.5 and len = 4,
+ // inCoord = 3.5 and will be rounded to 4 in nearest interpolation.
+ return tfjsCore.util.clamp(0, inCoord, len - 1);
+ }
+ function mapCoordConstant(outCoord, len) {
+ return outCoord;
+ }
+ function mapCoordNearest(outCoord, len) {
+ return tfjsCore.util.clamp(0, outCoord, len - 1);
+ }
+ function readWithFillValue(imageVals, imageHeight, imageWidth, batchStride, rowStride, colStride, batch, y, x, channel, fillValue) {
+ var ind = batch * batchStride + y * rowStride + x * colStride + channel;
+ if (0 <= y && y < imageHeight && 0 <= x && x < imageWidth) {
+ return imageVals[ind];
+ }
+ else {
+ return fillValue;
+ }
+ }
+ function nearestInterpolation(imageVals, imageHeight, imageWidth, batchStride, rowStride, colStride, batch, y, x, channel, fillValue) {
+ var $y = Math.round(y);
+ var $x = Math.round(x);
+ return readWithFillValue(imageVals, imageHeight, imageWidth, batchStride, rowStride, colStride, batch, $y, $x, channel, fillValue);
+ }
+ function bilinearInterpolation(imageVals, imageHeight, imageWidth, batchStride, rowStride, colStride, batch, y, x, channel, fillValue) {
+ var yFloor = Math.floor(y);
+ var xFloor = Math.floor(x);
+ var yCeil = yFloor + 1;
+ var xCeil = xFloor + 1;
+ // f(x, yFloor) = (xCeil - x) / (xCeil - xFloor) * f(xFloor, yFloor)
+ // + (x - xFloor) / (xCeil - xFloor) * f(xCeil, yFloor)
+ var valueYFloor = (xCeil - x) *
+ readWithFillValue(imageVals, imageHeight, imageWidth, batchStride, rowStride, colStride, batch, yFloor, xFloor, channel, fillValue) +
+ (x - xFloor) *
+ readWithFillValue(imageVals, imageHeight, imageWidth, batchStride, rowStride, colStride, batch, yFloor, xCeil, channel, fillValue);
+ // f(x, yCeil) = (xCeil - x) / (xCeil - xFloor) * f(xFloor, yCeil)
+ // + (x - xFloor) / (xCeil - xFloor) * f(xCeil, yCeil)
+ var valueYCeil = (xCeil - x) *
+ readWithFillValue(imageVals, imageHeight, imageWidth, batchStride, rowStride, colStride, batch, yCeil, xFloor, channel, fillValue) +
+ (x - xFloor) *
+ readWithFillValue(imageVals, imageHeight, imageWidth, batchStride, rowStride, colStride, batch, yCeil, xCeil, channel, fillValue);
+ // f(x, y) = (yCeil - y) / (yCeil - yFloor) * f(x, yFloor)
+ // + (y - yFloor) / (yCeil - yFloor) * f(x, yCeil)
+ return (yCeil - y) * valueYFloor + (y - yFloor) * valueYCeil;
+ }
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ function unique(args) {
+ var inputs = args.inputs, attrs = args.attrs, backend = args.backend;
+ var axis = attrs.axis;
+ var x = inputs.x;
+ assertNotComplex(x, 'unique');
+ var values = backend.data.get(x.dataId).values;
+ var _a = uniqueImpl(values, axis, x.shape, x.dtype), outputValues = _a.outputValues, outputShape = _a.outputShape, indices = _a.indices;
+ return [
+ backend.makeTensorInfo(outputShape, x.dtype, outputValues),
+ backend.makeTensorInfo([indices.length], 'int32', indices),
+ ];
+ }
+ var uniqueConfig = {
+ kernelName: tfjsCore.Unique,
+ backendName: 'cpu',
+ kernelFunc: unique,
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ function unpack(args) {
+ var inputs = args.inputs, backend = args.backend, attrs = args.attrs;
+ var value = inputs.value;
+ var axis = attrs.axis;
+ if (axis < 0) {
+ axis += value.shape.length;
+ }
+ var valueRank = value.shape.length;
+ var num = value.shape[axis];
+ var outShape = new Array(valueRank - 1);
+ var outIndex = 0;
+ for (var i = 0; i < valueRank; i++) {
+ if (i !== axis) {
+ outShape[outIndex++] = value.shape[i];
+ }
+ }
+ var begin = new Array(valueRank).fill(0);
+ var size = value.shape.slice();
+ size[axis] = 1;
+ var res = new Array(num);
+ for (var i = 0; i < res.length; i++) {
+ begin[axis] = i;
+ var tempRes = slice({ inputs: { x: value }, backend: backend, attrs: { begin: begin, size: size } });
+ res[i] = reshape({ inputs: { x: tempRes }, backend: backend, attrs: { shape: outShape } });
+ backend.disposeIntermediateTensorInfo(tempRes);
+ }
+ return res;
+ }
+ var unpackConfig = {
+ kernelName: tfjsCore.Unpack,
+ backendName: 'cpu',
+ kernelFunc: unpack
+ };
+
+ /**
+ * @license
+ * Copyright 2020 Google LLC. All Rights Reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =============================================================================
+ */
+ function unsortedSegmentSum(args) {
+ var inputs = args.inputs, backend = args.backend, attrs = args.attrs;
+ var x = inputs.x, segmentIds = inputs.segmentIds;
+ var numSegments = attrs.numSegments;
+ assertNotComplex(x, 'unsortedSegmentSum');
+ var xRank = x.shape.length;
+ var segmentIdsRank = segmentIds.shape.length;
+ var res = [];
+ var intermediates = [];
+ // Reshape the segment id's so that they can be broadcast with
+ // x. The new shape should be [segmentIds.shape, 1, ..., 1]
+ var numIters = xRank - segmentIdsRank;
+ var $segmentIds = segmentIds;
+ for (var i = 0; i < numIters; ++i) {
+ var expanded = expandDims({ inputs: { input: $segmentIds }, backend: backend, attrs: { dim: i + 1 } });
+ $segmentIds = expanded;
+ intermediates.push(expanded);
+ }
+ for (var i = 0; i < numSegments; ++i) {
+ var scalarValue = tfjsCore.util.createScalarValue(i, 'int32');
+ var segmentId = backend.makeTensorInfo([], 'int32', scalarValue);
+ var mask = equal({ inputs: { a: segmentId, b: $segmentIds }, backend: backend });
+ var maskCasted = cast({ inputs: { x: mask }, backend: backend, attrs: { dtype: 'float32' } });
+ var mul = multiply({ inputs: { a: maskCasted, b: x }, backend: backend });
+ var sumTensorInfo = sum({ inputs: { x: mul }, backend: backend, attrs: { axis: 0, keepDims: false } });
+ res.push(sumTensorInfo);
+ intermediates.push(segmentId);
+ intermediates.push(mask);
+ intermediates.push(maskCasted);
+ intermediates.push(mul);
+ intermediates.push(sumTensorInfo);
+ }
+ var result = pack({ inputs: res, backend: backend, attrs: { axis: 0 } });
+ intermediates.forEach(function (t) { return backend.disposeIntermediateTensorInfo(t); });
+ return result;
+ }
+ var unsortedSegmentSumConfig = {
+ kernelName: tfjsCore.UnsortedSegmentSum,
+ backendName: 'cpu',
+ kernelFunc: unsortedSegmentSum
+ };
+
+ var e_1, _a;
+ // List all kernel configs here
+ var kernelConfigs = [
+ _fusedMatMulConfig,
+ absConfig,
+ acosConfig,
+ acoshConfig,
+ addConfig,
+ addNConfig,
+ allConfig,
+ anyConfig,
+ argMaxConfig,
+ argMinConfig,
+ asinConfig,
+ asinhConfig,
+ atanConfig,
+ atan2Config,
+ atanhConfig,
+ avgPoolConfig,
+ avgPool3DConfig,
+ avgPool3DGradConfig,
+ avgPoolGradConfig,
+ batchMatMulConfig,
+ batchNormConfig,
+ batchToSpaceNDConfig,
+ bincountConfig,
+ broadcastArgsConfig,
+ castConfig,
+ ceilConfig,
+ clipConfig,
+ complexConfig,
+ complexAbsConfig,
+ concatConfig,
+ conv2DBackpropFilterConfig,
+ conv2DBackpropInputConfig,
+ conv2DConfig,
+ conv3DBackpropFilterV2Config,
+ conv3DBackpropInputV2Config,
+ conv3DConfig,
+ cosConfig,
+ coshConfig,
+ cropAndResizeConfig,
+ cumsumConfig,
+ denseBincountConfig,
+ depthToSpaceConfig,
+ depthwiseConv2dNativeConfig,
+ depthwiseConv2dNativeBackpropFilterConfig,
+ depthwiseConv2dNativeBackpropInputConfig,
+ diagConfig,
+ dilation2dConfig,
+ dilation2dBackpropInputConfig,
+ dilation2dBackpropFilterConfig,
+ realDivConfig,
+ einsumConfig,
+ eluConfig,
+ eluGradConfig,
+ equalConfig,
+ erfConfig,
+ expConfig,
+ expandDimsConfig,
+ expm1Config,
+ fftConfig,
+ fillConfig,
+ flipLeftRightConfig,
+ floorConfig,
+ floorDivConfig,
+ fusedConv2DConfig,
+ fusedDepthwiseConv2DConfig,
+ gatherNdConfig,
+ gatherV2Config,
+ greaterConfig,
+ greaterEqualConfig,
+ identityConfig,
+ ifftConfig,
+ imagConfig,
+ isFiniteConfig,
+ isInfConfig,
+ isNaNConfig,
+ leakyReluConfig,
+ lessConfig,
+ lessEqualConfig,
+ linSpaceConfig,
+ logConfig,
+ log1pConfig,
+ logicalAndConfig,
+ logicalNotConfig,
+ logicalOrConfig,
+ lRNConfig,
+ lRNGradConfig,
+ maximumConfig,
+ maxPoolConfig,
+ maxPool3DConfig,
+ maxPool3DGradConfig,
+ maxPoolGradConfig,
+ maxPoolWithArgmaxConfig,
+ maxConfig,
+ meanConfig,
+ minConfig,
+ minimumConfig,
+ mirrorPadConfig,
+ modConfig,
+ multinomialConfig,
+ multiplyConfig,
+ negConfig,
+ nonMaxSuppressionV3Config,
+ nonMaxSuppressionV4Config,
+ nonMaxSuppressionV5Config,
+ notEqualConfig,
+ oneHotConfig,
+ onesLikeConfig,
+ packConfig,
+ padV2Config,
+ powConfig,
+ preluConfig,
+ prodConfig,
+ rangeConfig,
+ realConfig,
+ reciprocalConfig,
+ reluConfig,
+ relu6Config,
+ reshapeConfig,
+ resizeBilinearConfig,
+ resizeBilinearGradConfig,
+ resizeNearestNeighborConfig,
+ resizeNearestNeighborGradConfig,
+ reverseConfig,
+ rotateWithOffsetConfig,
+ roundConfig,
+ rsqrtConfig,
+ scatterNdConfig,
+ selectConfig,
+ seluConfig,
+ sigmoidConfig,
+ signConfig,
+ sinConfig,
+ sinhConfig,
+ sliceConfig,
+ softmaxConfig,
+ softplusConfig,
+ spaceToBatchNDConfig,
+ sparseFillEmptyRowsConfig,
+ sparseReshapeConfig,
+ sparseSegmentMeanConfig,
+ sparseSegmentSumConfig,
+ sparseToDenseConfig,
+ splitVConfig,
+ sqrtConfig,
+ squareConfig,
+ squaredDifferenceConfig,
+ stepConfig,
+ stridedSliceConfig,
+ stringNGramsConfig,
+ stringSplitConfig,
+ stringToHashBucketFastConfig,
+ subConfig,
+ sumConfig,
+ tanConfig,
+ tanhConfig,
+ tileConfig,
+ topKConfig,
+ transposeConfig,
+ transformConfig,
+ uniqueConfig,
+ unpackConfig,
+ unsortedSegmentSumConfig,
+ zerosLikeConfig
+ ];
+ try {
+ for (var kernelConfigs_1 = __values(kernelConfigs), kernelConfigs_1_1 = kernelConfigs_1.next(); !kernelConfigs_1_1.done; kernelConfigs_1_1 = kernelConfigs_1.next()) {
+ var kernelConfig = kernelConfigs_1_1.value;
+ tfjsCore.registerKernel(kernelConfig);
+ }
+ }
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
+ finally {
+ try {
+ if (kernelConfigs_1_1 && !kernelConfigs_1_1.done && (_a = kernelConfigs_1.return)) _a.call(kernelConfigs_1);
+ }
+ finally { if (e_1) throw e_1.error; }
+ }
+
+ exports.MathBackendCPU = MathBackendCPU;
+ exports.shared = shared;
+ exports.version_cpu = version;
+
+ Object.defineProperty(exports, '__esModule', { value: true });
+
+})));
+//# sourceMappingURL=tf-backend-cpu.js.map