@tensorflow/tfjs-core
Version:
Hardware-accelerated JavaScript library for machine intelligence
1,139 lines (1,138 loc) • 158 kB
JavaScript
"use strict";
/**
* @license
* Copyright 2017 Google Inc. 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 __extends = (this && this.__extends) || (function () {
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);
};
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
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) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (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 };
}
};
Object.defineProperty(exports, "__esModule", { value: true });
var seedrandom = require("seedrandom");
var engine_1 = require("../../engine");
var environment_1 = require("../../environment");
var log_1 = require("../../log");
var array_ops_util = require("../../ops/array_ops_util");
var axis_util = require("../../ops/axis_util");
var broadcast_util = require("../../ops/broadcast_util");
var complex_ops_1 = require("../../ops/complex_ops");
var concat_util = require("../../ops/concat_util");
var erf_util = require("../../ops/erf_util");
var gather_nd_util = require("../../ops/gather_nd_util");
var ops = require("../../ops/ops");
var ops_1 = require("../../ops/ops");
var scatter_nd_util = require("../../ops/scatter_nd_util");
var selu_util = require("../../ops/selu_util");
var slice_util_1 = require("../../ops/slice_util");
var tensor_1 = require("../../tensor");
var types_1 = require("../../types");
var util = require("../../util");
var util_1 = require("../../util");
var backend_1 = require("../backend");
var backend_util = require("../backend_util");
var complex_util = require("../complex_util");
var non_max_suppression_impl_1 = require("../non_max_suppression_impl");
var split_shared_1 = require("../split_shared");
var tile_impl_1 = require("../tile_impl");
var topk_impl_1 = require("../topk_impl");
var where_impl_1 = require("../where_impl");
var cpu_util_1 = require("./cpu_util");
function mapActivation(backend, x, activation, preluActivationWeights) {
if (activation === 'linear') {
return backend.linear(x);
}
else if (activation === 'relu') {
return backend.relu(x);
}
else if (activation === 'elu') {
return backend.elu(x);
}
else if (activation === 'relu6') {
return backend.relu6(x);
}
else if (activation === 'prelu') {
return backend.prelu(x, preluActivationWeights);
}
throw new Error("Activation " + activation + " has not been implemented for the CPU backend.");
}
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 backend_1.DataStorage(_this, engine_1.ENGINE);
return _this;
}
MathBackendCPU.prototype.write = function (values, shape, dtype) {
if (this.firstUse) {
this.firstUse = false;
if (environment_1.env().get('IS_NODE')) {
log_1.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 = {};
this.data.set(dataId, { values: values, dtype: dtype });
return dataId;
};
MathBackendCPU.prototype.move = function (dataId, values, shape, dtype) {
this.data.set(dataId, { values: values, dtype: dtype });
};
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 (_a) {
return [2 /*return*/, this.readSync(dataId)];
});
});
};
MathBackendCPU.prototype.readSync = function (dataId) {
var _a = this.data.get(dataId), dtype = _a.dtype, complexTensors = _a.complexTensors;
if (dtype === 'complex64') {
var realValues = this.readSync(complexTensors.real.dataId);
var imagValues = this.readSync(complexTensors.imag.dataId);
return complex_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 util.decodeString(d); });
}
catch (_a) {
throw new Error('Failed to decode encoded string bytes into utf-8');
}
}
return ops_1.buffer(t.shape, t.dtype, decodedData);
};
MathBackendCPU.prototype.makeOutput = function (values, shape, dtype) {
var dataId = this.write(values, shape, dtype);
return engine_1.ENGINE.makeTensorFromDataId(dataId, shape, dtype, this);
};
MathBackendCPU.prototype.disposeData = function (dataId) {
if (this.data.has(dataId)) {
var complexTensors = this.data.get(dataId).complexTensors;
if (complexTensors != null) {
complexTensors.real.dispose();
complexTensors.imag.dispose();
}
this.data.delete(dataId);
}
};
MathBackendCPU.prototype.time = function (f) {
return __awaiter(this, void 0, void 0, function () {
var start, kernelMs;
return __generator(this, function (_a) {
start = util_1.now();
f();
kernelMs = util_1.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.complex = function (real, imag) {
var result = this.makeOutput(null, real.shape, 'complex64');
var resultData = this.data.get(result.dataId);
// The backend owns the reference to the underlying real and imaginary
// clones. These will explicitly get disposed when the complex tensor is
// disposed.
resultData.complexTensors = {
real: engine_1.ENGINE.keep(real.clone()),
imag: engine_1.ENGINE.keep(imag.clone())
};
return result;
};
MathBackendCPU.prototype.real = function (input) {
var resultData = this.data.get(input.dataId);
return resultData.complexTensors.real.clone();
};
MathBackendCPU.prototype.imag = function (input) {
var resultData = this.data.get(input.dataId);
return resultData.complexTensors.imag.clone();
};
MathBackendCPU.prototype.slice = function (x, begin, size) {
cpu_util_1.assertNotComplex(x, 'slice');
var isContinous = slice_util_1.isSliceContinous(x.shape, begin, size);
if (isContinous) {
var flatOffset = slice_util_1.computeFlatOffset(begin, x.strides);
var length_1 = util.sizeFromShape(size);
var vals = this.readSync(x.dataId);
return ops_1.tensor(vals.subarray(flatOffset, flatOffset + length_1), size, x.dtype);
}
var buffer = ops.buffer(size, x.dtype);
var xBuf = this.bufferSync(x);
for (var i = 0; i < buffer.size; ++i) {
var loc = buffer.indexToLoc(i);
var xLoc = loc.map(function (idx, j) { return idx + begin[j]; });
buffer.values[i] = xBuf.get.apply(xBuf, xLoc);
}
return buffer.toTensor();
};
MathBackendCPU.prototype.stridedSlice = function (x, begin, end, strides) {
cpu_util_1.assertNotComplex(x, 'stridedSlice');
var outShape = slice_util_1.computeOutShape(begin, end, strides);
if (outShape.some(function (axis) { return axis === 0; })) {
return ops.tensor([], outShape);
}
var buffer = ops.buffer(outShape, x.dtype);
var xBuf = this.bufferSync(x);
for (var i = 0; i < buffer.size; i++) {
var loc = buffer.indexToLoc(i);
var newLoc = new Array(loc.length);
for (var j = 0; j < newLoc.length; j++) {
newLoc[j] = loc[j] * strides[j] + begin[j];
}
buffer.set.apply(buffer, [xBuf.get.apply(xBuf, newLoc)].concat(loc));
}
return buffer.toTensor();
};
MathBackendCPU.prototype.diag = function (x) {
var xVals = this.readSync(x.dataId);
var buffer = ops.buffer([x.size, x.size], x.dtype);
var vals = buffer.values;
for (var i = 0; i < xVals.length; i++) {
vals[i * x.size + i] = xVals[i];
}
return buffer.toTensor();
};
MathBackendCPU.prototype.unstack = function (x, axis) {
var num = x.shape[axis];
var outShape = new Array(x.rank - 1);
var outIndex = 0;
for (var i = 0; i < x.rank; i++) {
if (i !== axis) {
outShape[outIndex++] = x.shape[i];
}
}
var begin = new Array(x.rank).fill(0);
var size = x.shape.slice();
size[axis] = 1;
var res = new Array(num);
for (var i = 0; i < res.length; i++) {
begin[axis] = i;
res[i] = this.slice(x, begin, size).reshape(outShape);
}
return res;
};
MathBackendCPU.prototype.reverse = function (x, axis) {
cpu_util_1.assertNotComplex(x, 'reverse');
var buffer = ops.buffer(x.shape, x.dtype);
var xBuf = this.bufferSync(x);
var _loop_1 = function (i) {
var outLoc = buffer.indexToLoc(i);
var inLoc = outLoc.slice();
axis.forEach(function (ax) { return inLoc[ax] = x.shape[ax] - 1 - inLoc[ax]; });
buffer.set.apply(buffer, [xBuf.get.apply(xBuf, inLoc)].concat(outLoc));
};
for (var i = 0; i < buffer.size; i++) {
_loop_1(i);
}
return buffer.toTensor();
};
MathBackendCPU.prototype.concat = function (tensors, axis) {
var _this = this;
if (tensors[0].dtype === 'complex64') {
var reals = tensors.map(function (t) { return complex_ops_1.real(t); });
var imags = tensors.map(function (t) { return complex_ops_1.imag(t); });
return complex_ops_1.complex(this.concat(reals, axis), this.concat(imags, axis));
}
var tensors2D = tensors.map(function (t) {
var innerSize = util.sizeFromShape(t.shape.slice(axis));
return t.as2D(-1, innerSize);
});
var outShape = concat_util.computeOutShape(tensors2D.map(function (t) { return t.shape; }), 1 /* axis */);
var values = ops.buffer(outShape, tensors[0].dtype)
.values;
if (tensors2D[0].shape[0] === 1) {
// Use built-in TypedArray.set() method for speed.
var offset_1 = 0;
tensors2D.forEach(function (t) {
values.set(_this.readSync(t.dataId), offset_1);
offset_1 += t.size;
});
}
else {
var colOffset_1 = 0;
tensors2D.forEach(function (t) {
var tVals = _this.readSync(t.dataId);
var tIdx = 0;
for (var row = 0; row < t.shape[0]; ++row) {
var resIdx = row * outShape[1] + colOffset_1;
for (var col = 0; col < t.shape[1]; ++col) {
values[resIdx + col] = tVals[tIdx++];
}
}
colOffset_1 += t.shape[1];
});
}
var finalOutShape = concat_util.computeOutShape(tensors.map(function (t) { return t.shape; }), axis);
return ops_1.tensor(values, finalOutShape, tensors[0].dtype);
};
MathBackendCPU.prototype.neg = function (x) {
cpu_util_1.assertNotComplex(x, 'neg');
return this.multiply(ops.scalar(-1), x);
};
MathBackendCPU.prototype.add = function (a, b) {
if (a.dtype === 'complex64' || b.dtype === 'complex64') {
return this.broadcastedBinaryComplexOp(a.cast('complex64'), b.cast('complex64'), function (aReal, aImag, bReal, bImag) {
return { real: aReal + bReal, imag: aImag + bImag };
});
}
return this.broadcastedBinaryOp(a, b, types_1.upcastType(a.dtype, b.dtype), function (aValue, bValue) { return aValue + bValue; });
};
MathBackendCPU.prototype.addN = function (tensors) {
var _this = this;
cpu_util_1.assertNotComplex(tensors, 'addN');
var vals = tensors.map(function (t) { return _this.readSync(t.dataId); });
var result = ops.buffer(tensors[0].shape, tensors[0].dtype);
var resultVals = result.values;
for (var i = 0; i < tensors.length; i++) {
var currVals = vals[i];
for (var j = 0; j < resultVals.length; j++) {
resultVals[j] += currVals[j];
}
}
return result.toTensor();
};
MathBackendCPU.prototype.subtract = function (a, b) {
if (a.dtype === 'complex64' || b.dtype === 'complex64') {
return this.broadcastedBinaryComplexOp(a.cast('complex64'), b.cast('complex64'), function (aReal, aImag, bReal, bImag) {
return { real: aReal - bReal, imag: aImag - bImag };
});
}
return this.broadcastedBinaryOp(a, b, types_1.upcastType(a.dtype, b.dtype), function (aValue, bValue) { return aValue - bValue; });
};
MathBackendCPU.prototype.pow = function (a, b) {
cpu_util_1.assertNotComplex([a, b], 'pow');
return this.broadcastedBinaryOp(a, b, a.dtype, function (aValue, bValue) { return Math.pow(aValue, bValue); });
};
MathBackendCPU.prototype.batchMatMul = function (a, b, transposeA, transposeB) {
cpu_util_1.assertNotComplex([a, b], 'matMul');
var sharedDim = transposeA ? a.shape[1] : a.shape[2];
var leftDim = transposeA ? a.shape[2] : a.shape[1];
var rightDim = transposeB ? b.shape[1] : b.shape[2];
var batchDim = a.shape[0];
var aValues = this.readSync(a.dataId);
var bValues = this.readSync(b.dataId);
var _a = transposeA ?
[a.strides[0], 1, a.strides[1]] :
[a.strides[0], a.strides[1], 1], aBatch = _a[0], aOuterStep = _a[1], aInnerStep = _a[2];
var _b = transposeB ?
[1, b.strides[1], b.strides[0]] :
[b.strides[1], 1, b.strides[0]], bInnerStep = _b[0], bOuterStep = _b[1], bBatch = _b[2];
var size = leftDim * rightDim;
var result = ops_1.buffer([batchDim, leftDim, rightDim], a.dtype);
var resVals = result.values;
var blockSize = this.blockSize;
for (var b_1 = 0; b_1 < batchDim; b_1++) {
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++) {
sum += aValues[b_1 * aBatch + i * aOuterStep + k * aInnerStep] *
bValues[k * bInnerStep + j * bOuterStep + b_1 * bBatch];
}
resVals[b_1 * size + (i * rightDim + j)] += sum;
}
}
}
}
}
}
return result.toTensor();
};
MathBackendCPU.prototype.fusedBatchMatMul = function (_a) {
var a = _a.a, b = _a.b, transposeA = _a.transposeA, transposeB = _a.transposeB, bias = _a.bias, activation = _a.activation, preluActivationWeights = _a.preluActivationWeights;
var result = this.batchMatMul(a, b, transposeA, transposeB);
if (bias) {
result = this.add(result, bias);
}
if (activation) {
result =
mapActivation(this, result, activation, preluActivationWeights);
}
return result;
};
MathBackendCPU.prototype.multiply = function (a, b) {
if (a.dtype === 'complex64' || b.dtype === 'complex64') {
return this.broadcastedBinaryComplexOp(a.cast('complex64'), b.cast('complex64'), function (aReal, aImag, bReal, bImag) {
return {
real: aReal * bReal - aImag * bImag,
imag: aReal * bImag + aImag * bReal
};
});
}
return this.broadcastedBinaryOp(a, b, types_1.upcastType(a.dtype, b.dtype), function (aValue, bValue) { return aValue * bValue; });
};
MathBackendCPU.prototype.realDivide = function (a, b) {
cpu_util_1.assertNotComplex([a, b], 'realDivide');
var op = function (a, b) { return a / b; };
var outputDtype = 'float32';
return this.broadcastedBinaryOp(a, b, outputDtype, op);
};
MathBackendCPU.prototype.floorDiv = function (a, b) {
cpu_util_1.assertNotComplex([a, b], 'floorDiv');
var op = function (a, b) { return Math.floor(a / b); };
var outputDtype = 'int32';
return this.broadcastedBinaryOp(a, b, outputDtype, op);
};
MathBackendCPU.prototype.sum = function (x, axes) {
cpu_util_1.assertNotComplex(x, 'sum');
axis_util.assertAxesAreInnerMostDims('sum', axes, x.rank);
var _a = axis_util.computeOutAndReduceShapes(x.shape, axes), outShape = _a[0], reduceShape = _a[1];
var resultDtype = types_1.upcastType(x.dtype, 'int32');
var result = ops.zeros(outShape, resultDtype);
var reduceSize = util.sizeFromShape(reduceShape);
var vals = this.readSync(result.dataId);
var aVals = this.readSync(x.dataId);
for (var i = 0; i < vals.length; ++i) {
var offset = i * reduceSize;
var sum = 0;
for (var j = 0; j < reduceSize; ++j) {
sum += aVals[offset + j];
}
vals[i] = sum;
}
return result;
};
MathBackendCPU.prototype.prod = function (x, axes) {
cpu_util_1.assertNotComplex(x, 'sum');
var _a = axis_util.computeOutAndReduceShapes(x.shape, axes), outShape = _a[0], reduceShape = _a[1];
var resultDtype = types_1.upcastType(x.dtype, 'int32');
var result = ops.zeros(outShape, resultDtype);
var reduceSize = util.sizeFromShape(reduceShape);
var vals = this.readSync(result.dataId);
var aVals = this.readSync(x.dataId);
for (var i = 0; i < vals.length; ++i) {
var offset = i * reduceSize;
var prod = 1;
for (var j = 0; j < reduceSize; ++j) {
prod *= aVals[offset + j];
}
vals[i] = prod;
}
return result;
};
MathBackendCPU.prototype.unsortedSegmentSum = function (x, segmentIds, numSegments) {
cpu_util_1.assertNotComplex(x, 'unsortedSegmentSum');
var res = [];
// Reshape the segment id's so that they can be broadcast with
// x. The new shape should be [segmentIds.shape, 1, ..., 1]
var numIters = x.rank - segmentIds.rank;
for (var i = 0; i < numIters; ++i) {
segmentIds = segmentIds.expandDims(i + 1);
}
for (var i = 0; i < numSegments; ++i) {
var segmentId = ops.scalar(i, 'int32');
var mask = ops.equal(segmentId, segmentIds).asType('float32');
var sum = mask.mul(x).sum(0);
res.push(sum);
}
return ops.stack(res);
};
MathBackendCPU.prototype.argMin = function (x, axis) {
cpu_util_1.assertNotComplex(x, 'argMin');
var axes = [axis];
axis_util.assertAxesAreInnerMostDims('argMin', axes, x.rank);
var _a = axis_util.computeOutAndReduceShapes(x.shape, axes), outShape = _a[0], reduceShape = _a[1];
var result = ops.zeros(outShape, 'int32');
var reduceSize = util.sizeFromShape(reduceShape);
var vals = this.readSync(result.dataId);
var aVals = this.readSync(x.dataId);
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;
}
return result;
};
MathBackendCPU.prototype.argMax = function (x, axis) {
cpu_util_1.assertNotComplex(x, 'argMax');
var axes = [axis];
axis_util.assertAxesAreInnerMostDims('argMax', axes, x.rank);
var _a = axis_util.computeOutAndReduceShapes(x.shape, axes), outShape = _a[0], reduceShape = _a[1];
var result = ops.zeros(outShape, 'int32');
var reduceSize = util.sizeFromShape(reduceShape);
var vals = this.readSync(result.dataId);
var aVals = this.readSync(x.dataId);
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;
}
return result;
};
MathBackendCPU.prototype.cumsum = function (x, axis, exclusive, reverse) {
cpu_util_1.assertNotComplex(x, 'cumsum');
if (axis !== x.rank - 1) {
throw new Error("backend.cumsum in CPU expects an inner-most axis=" + (x.rank - 1) + " " +
("but got axis=" + axis));
}
var resultDtype = types_1.upcastType(x.dtype, 'int32');
var result = ops.zeros(x.shape, resultDtype);
var vals = this.readSync(result.dataId);
var aVals = this.readSync(x.dataId);
var finalDim = x.shape[x.rank - 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];
}
}
}
return result;
};
MathBackendCPU.prototype.equal = function (a, b) {
cpu_util_1.assertNotComplex([a, b], 'equal');
return this.broadcastedBinaryOp(a, b, 'bool', function (aVal, bVal) {
return (aVal === bVal) ? 1 : 0;
});
};
MathBackendCPU.prototype.notEqual = function (a, b) {
cpu_util_1.assertNotComplex([a, b], 'notEqual');
return this.broadcastedBinaryOp(a, b, 'bool', function (aVal, bVal) {
return (aVal !== bVal) ? 1 : 0;
});
};
MathBackendCPU.prototype.less = function (a, b) {
cpu_util_1.assertNotComplex([a, b], 'less');
return this.broadcastedBinaryOp(a, b, 'bool', function (aVal, bVal) {
return (aVal < bVal) ? 1 : 0;
});
};
MathBackendCPU.prototype.lessEqual = function (a, b) {
cpu_util_1.assertNotComplex([a, b], 'lessEqual');
return this.broadcastedBinaryOp(a, b, 'bool', function (aVal, bVal) {
return (aVal <= bVal) ? 1 : 0;
});
};
MathBackendCPU.prototype.greater = function (a, b) {
cpu_util_1.assertNotComplex([a, b], 'greater');
return this.broadcastedBinaryOp(a, b, 'bool', function (aVal, bVal) {
return (aVal > bVal) ? 1 : 0;
});
};
MathBackendCPU.prototype.greaterEqual = function (a, b) {
cpu_util_1.assertNotComplex([a, b], 'greaterEqual');
return this.broadcastedBinaryOp(a, b, 'bool', function (aVal, bVal) {
return (aVal >= bVal) ? 1 : 0;
});
};
MathBackendCPU.prototype.logicalNot = function (x) {
cpu_util_1.assertNotComplex(x, 'logicalNot');
var values = this.readSync(x.dataId);
var newValues = new Uint8Array(values.length);
for (var i = 0; i < values.length; ++i) {
newValues[i] = values[i] ? 0 : 1;
}
return this.makeOutput(newValues, x.shape, 'bool');
};
MathBackendCPU.prototype.logicalAnd = function (a, b) {
cpu_util_1.assertNotComplex([a, b], 'logicalAnd');
return this.broadcastedBinaryOp(a, b, 'bool', function (aVal, bVal) {
return aVal && bVal;
});
};
MathBackendCPU.prototype.logicalOr = function (a, b) {
cpu_util_1.assertNotComplex([a, b], 'logicalOr');
return this.broadcastedBinaryOp(a, b, 'bool', function (aVal, bVal) {
return aVal || bVal;
});
};
MathBackendCPU.prototype.select = function (condition, a, b) {
cpu_util_1.assertNotComplex([condition, a, b], 'select');
var values = this.readSync(condition.dataId);
var aValues = this.readSync(a.dataId);
var bValues = this.readSync(b.dataId);
var result = ops.zeros(a.shape, types_1.upcastType(a.dtype, b.dtype));
var newValues = this.readSync(result.dataId);
var index = 0;
var offset = condition.rank === 0 || condition.rank > 1 || a.rank === 1 ?
1 :
util.sizeFromShape(a.shape.slice(1));
for (var i = 0; i < values.length; i++) {
for (var j = 0; j < offset; j++) {
if (values[i] === 1) {
newValues[index++] = aValues[i];
}
else {
newValues[index++] = bValues[i];
}
}
}
return result;
};
MathBackendCPU.prototype.where = function (condition) {
cpu_util_1.assertNotComplex([condition], 'where');
var condVals = this.readSync(condition.dataId);
return where_impl_1.whereImpl(condition.shape, condVals);
};
MathBackendCPU.prototype.topk = function (x, k, sorted) {
cpu_util_1.assertNotComplex(x, 'topk');
var xVals = this.readSync(x.dataId);
return topk_impl_1.topkImpl(xVals, x.shape, x.dtype, k, sorted);
};
MathBackendCPU.prototype.min = function (x, axes) {
cpu_util_1.assertNotComplex(x, 'min');
axis_util.assertAxesAreInnerMostDims('min', axes, x.rank);
var _a = axis_util.computeOutAndReduceShapes(x.shape, axes), outShape = _a[0], reduceShape = _a[1];
var result = ops.zeros(outShape, x.dtype);
var reduceSize = util.sizeFromShape(reduceShape);
var vals = this.readSync(result.dataId);
var aVals = this.readSync(x.dataId);
for (var i = 0; i < vals.length; ++i) {
var offset = i * reduceSize;
var min = aVals[offset];
for (var j = 0; j < reduceSize; ++j) {
var value = aVals[offset + j];
if (value < min) {
min = value;
}
}
vals[i] = min;
}
return result;
};
MathBackendCPU.prototype.minimum = function (a, b) {
cpu_util_1.assertNotComplex([a, b], 'minimum');
return this.broadcastedBinaryOp(a, b, a.dtype, function (aVal, bVal) { return Math.min(aVal, bVal); });
};
MathBackendCPU.prototype.mod = function (a, b) {
cpu_util_1.assertNotComplex([a, b], 'mod');
return this.broadcastedBinaryOp(a, b, a.dtype, function (aVal, bVal) {
var rem = aVal % bVal;
if ((aVal < 0 && bVal < 0) || (aVal >= 0 && bVal >= 0)) {
return rem;
}
else {
return (rem + bVal) % bVal;
}
});
};
MathBackendCPU.prototype.max = function (x, axes) {
cpu_util_1.assertNotComplex(x, 'max');
axis_util.assertAxesAreInnerMostDims('max', axes, x.rank);
var _a = axis_util.computeOutAndReduceShapes(x.shape, axes), outShape = _a[0], reduceShape = _a[1];
var result = ops.zeros(outShape, x.dtype);
var reduceSize = util.sizeFromShape(reduceShape);
var vals = this.readSync(result.dataId);
var aVals = this.readSync(x.dataId);
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 (value > max) {
max = value;
}
}
vals[i] = max;
}
return result;
};
MathBackendCPU.prototype.maximum = function (a, b) {
cpu_util_1.assertNotComplex([a, b], 'maximum');
return this.broadcastedBinaryOp(a, b, a.dtype, function (aVal, bVal) { return Math.max(aVal, bVal); });
};
MathBackendCPU.prototype.all = function (x, axes) {
cpu_util_1.assertNotComplex(x, 'all');
axis_util.assertAxesAreInnerMostDims('all', axes, x.rank);
var _a = axis_util.computeOutAndReduceShapes(x.shape, axes), outShape = _a[0], reduceShape = _a[1];
var result = ops.zeros(outShape, x.dtype);
var reduceSize = util.sizeFromShape(reduceShape);
var vals = this.readSync(result.dataId);
var aVals = this.readSync(x.dataId);
for (var i = 0; i < vals.length; ++i) {
var offset = i * reduceSize;
var all = aVals[offset];
for (var j = 0; j < reduceSize; ++j) {
var value = aVals[offset + j];
all = all && value;
}
vals[i] = all;
}
return result;
};
MathBackendCPU.prototype.any = function (x, axes) {
cpu_util_1.assertNotComplex(x, 'any');
axis_util.assertAxesAreInnerMostDims('any', axes, x.rank);
var _a = axis_util.computeOutAndReduceShapes(x.shape, axes), outShape = _a[0], reduceShape = _a[1];
var result = ops.zeros(outShape, x.dtype);
var reduceSize = util.sizeFromShape(reduceShape);
var vals = this.readSync(result.dataId);
var aVals = this.readSync(x.dataId);
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;
}
return result;
};
MathBackendCPU.prototype.squaredDifference = function (a, b) {
cpu_util_1.assertNotComplex([a, b], 'squaredDifference');
return this.broadcastedBinaryOp(a, b, a.dtype, function (aVal, bVal) {
var diff = aVal - bVal;
return diff * diff;
});
};
MathBackendCPU.prototype.ceil = function (x) {
cpu_util_1.assertNotComplex(x, 'ceil');
var values = this.readSync(x.dataId);
var newValues = new Float32Array(values.length);
for (var i = 0; i < values.length; ++i) {
newValues[i] = Math.ceil(values[i]);
}
return this.makeOutput(newValues, x.shape, 'float32');
};
MathBackendCPU.prototype.floor = function (x) {
cpu_util_1.assertNotComplex(x, 'floor');
var values = this.readSync(x.dataId);
var newValues = new Float32Array(values.length);
for (var i = 0; i < values.length; ++i) {
newValues[i] = Math.floor(values[i]);
}
return this.makeOutput(newValues, x.shape, 'float32');
};
MathBackendCPU.prototype.sign = function (x) {
cpu_util_1.assertNotComplex(x, 'x');
var values = this.readSync(x.dataId);
var newValues = new Float32Array(values.length);
for (var i = 0; i < values.length; ++i) {
if (values[i] < 0) {
newValues[i] = -1;
}
else if (values[i] > 0) {
newValues[i] = 1;
}
else {
newValues[i] = 0;
}
}
return this.makeOutput(newValues, x.shape, 'float32');
};
MathBackendCPU.prototype.isNaN = function (x) {
cpu_util_1.assertNotComplex(x, 'x');
var values = this.readSync(x.dataId);
var newValues = new Uint8Array(values.length);
for (var i = 0; i < values.length; ++i) {
if (Number.isNaN(values[i])) {
newValues[i] = 1;
}
}
return this.makeOutput(newValues, x.shape, 'bool');
};
MathBackendCPU.prototype.isInf = function (x) {
cpu_util_1.assertNotComplex(x, 'x');
var values = this.readSync(x.dataId);
var newValues = new Uint8Array(values.length);
for (var i = 0; i < values.length; ++i) {
if (Math.abs(values[i]) === Infinity) {
newValues[i] = 1;
}
}
return this.makeOutput(newValues, x.shape, 'bool');
};
MathBackendCPU.prototype.isFinite = function (x) {
cpu_util_1.assertNotComplex(x, 'x');
var values = this.readSync(x.dataId);
var newValues = new Uint8Array(values.length);
for (var i = 0; i < values.length; ++i) {
if (Number.isFinite(values[i])) {
newValues[i] = 1;
}
}
return this.makeOutput(newValues, x.shape, 'bool');
};
MathBackendCPU.prototype.round = function (x) {
cpu_util_1.assertNotComplex(x, 'round');
var values = this.readSync(x.dataId);
var newValues = new Float32Array(values.length);
for (var i = 0; i < values.length; ++i) {
// The algorithm is based on banker's rounding.
var base = Math.floor(values[i]);
if (values[i] - base < 0.5) {
newValues[i] = Math.floor(values[i]);
}
else if (values[i] - base > 0.5) {
newValues[i] = Math.ceil(values[i]);
}
else {
if (base % 2.0 === 0.0) {
newValues[i] = base;
}
else {
newValues[i] = base + 1.0;
}
}
}
return this.makeOutput(newValues, x.shape, 'float32');
};
MathBackendCPU.prototype.exp = function (x) {
cpu_util_1.assertNotComplex(x, 'exp');
var values = this.readSync(x.dataId);
var newValues = new Float32Array(values.length);
for (var i = 0; i < values.length; ++i) {
newValues[i] = Math.exp(values[i]);
}
return this.makeOutput(newValues, x.shape, 'float32');
};
MathBackendCPU.prototype.expm1 = function (x) {
cpu_util_1.assertNotComplex(x, 'expm1');
var values = this.readSync(x.dataId);
var newValues = new Float32Array(values.length);
for (var i = 0; i < values.length; ++i) {
newValues[i] = Math.expm1(values[i]);
}
return this.makeOutput(newValues, x.shape, 'float32');
};
MathBackendCPU.prototype.log = function (x) {
cpu_util_1.assertNotComplex(x, 'log');
var values = this.readSync(x.dataId);
var newValues = new Float32Array(values.length);
for (var i = 0; i < values.length; ++i) {
var value = values[i];
newValues[i] = Math.log(value);
}
return this.makeOutput(newValues, x.shape, 'float32');
};
MathBackendCPU.prototype.log1p = function (x) {
cpu_util_1.assertNotComplex(x, 'log1p');
var values = this.readSync(x.dataId);
var newValues = new Float32Array(values.length);
for (var i = 0; i < values.length; ++i) {
var value = values[i];
newValues[i] = Math.log1p(value);
}
return this.makeOutput(newValues, x.shape, 'float32');
};
MathBackendCPU.prototype.sqrt = function (x) {
cpu_util_1.assertNotComplex(x, 'sqrt');
var values = this.readSync(x.dataId);
var newValues = new Float32Array(values.length);
for (var i = 0; i < values.length; ++i) {
var value = values[i];
newValues[i] = Math.sqrt(value);
}
return this.makeOutput(newValues, x.shape, 'float32');
};
MathBackendCPU.prototype.rsqrt = function (x) {
cpu_util_1.assertNotComplex(x, 'rsqrt');
var values = this.readSync(x.dataId);
var newValues = new Float32Array(values.length);
for (var i = 0; i < values.length; ++i) {
var value = values[i];
newValues[i] = 1 / Math.sqrt(value);
}
return this.makeOutput(newValues, x.shape, 'float32');
};
MathBackendCPU.prototype.reciprocal = function (x) {
cpu_util_1.assertNotComplex(x, 'reciprocal');
var values = this.readSync(x.dataId);
var newValues = new Float32Array(values.length);
for (var i = 0; i < values.length; ++i) {
newValues[i] = 1 / values[i];
}
return this.makeOutput(newValues, x.shape, 'float32');
};
MathBackendCPU.prototype.linear = function (x) {
return x;
};
MathBackendCPU.prototype.relu = function (x) {
cpu_util_1.assertNotComplex(x, 'relu');
var res = ops.zeros(x.shape, x.dtype);
var resVals = this.readSync(res.dataId);
var inVals = this.readSync(x.dataId);
for (var i = 0; i < inVals.length; ++i) {
resVals[i] = Math.max(0, inVals[i]);
}
return res;
};
MathBackendCPU.prototype.relu6 = function (x) {
cpu_util_1.assertNotComplex(x, 'relu');
var res = ops.zeros(x.shape, x.dtype);
var resVals = this.readSync(res.dataId);
var inVals = this.readSync(x.dataId);
for (var i = 0; i < inVals.length; ++i) {
resVals[i] = Math.min(Math.max(0, inVals[i]), 6);
}
return res;
};
MathBackendCPU.prototype.prelu = function (x, a) {
cpu_util_1.assertNotComplex([x, a], 'prelu');
return this.broadcastedBinaryOp(x, a, x.dtype, function (xValue, aValue) { return xValue < 0 ? aValue * xValue : xValue; });
};
MathBackendCPU.prototype.elu = function (x) {
cpu_util_1.assertNotComplex(x, 'elu');
var resultValues = new Float32Array(x.size);
var values = this.readSync(x.dataId);
for (var i = 0; i < values.length; ++i) {
var v = values[i];
if (v >= 0) {
resultValues[i] = v;
}
else {
resultValues[i] = (Math.exp(v) - 1);
}
}
return this.makeOutput(resultValues, x.shape, 'float32');
};
MathBackendCPU.prototype.eluDer = function (dy, y) {
cpu_util_1.assertNotComplex([dy, y], 'eluDer');
var resultValues = new Float32Array(y.size);
var values = this.readSync(y.dataId);
var dyValues = this.readSync(dy.dataId);
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 this.makeOutput(resultValues, y.shape, 'float32');
};
MathBackendCPU.prototype.selu = function (x) {
cpu_util_1.assertNotComplex(x, 'selu');
// Stable and Attracting Fixed Point (0, 1) for Normalized Weights.
// see: https://arxiv.org/abs/1706.02515
var scaleAlpha = selu_util.SELU_SCALEALPHA;
var scale = selu_util.SELU_SCALE;
var resultValues = new Float32Array(x.size);
var values = this.readSync(x.dataId);
for (var i = 0; i < values.length; ++i) {
var v = values[i];
if (v >= 0) {
resultValues[i] = scale * v;
}
else {
resultValues[i] = scaleAlpha * (Math.exp(v) - 1);
}
}
return this.makeOutput(resultValues, x.shape, 'float32');
};
MathBackendCPU.prototype.clip = function (x, min, max) {
cpu_util_1.assertNotComplex(x, 'clip');
var resultValues = new Float32Array(x.size);
var values = this.readSync(x.dataId);
for (var i = 0; i < values.length; ++i) {
var v = values[i];
resultValues[i] = v > max ? max : (v < min ? min : v);
}
return this.makeOutput(resultValues, x.shape, 'float32');
};
MathBackendCPU.prototype.abs = function (x) {
var resultValues = new Float32Array(x.size);
var values = this.readSync(x.dataId);
for (var i = 0; i < values.length; ++i) {
resultValues[i] = Math.abs(values[i]);
}
return this.makeOutput(resultValues, x.shape, 'float32');
};
MathBackendCPU.prototype.complexAbs = function (x) {
var resultValues = new Float32Array(x.size);
var values = this.readSync(x.dataId);
for (var i = 0; i < x.size; ++i) {
var real_1 = values[i * 2];
var imag_1 = values[i * 2 + 1];
resultValues[i] = Math.hypot(real_1, imag_1);
}
return this.makeOutput(resultValues, x.shape, 'float32');
};
MathBackendCPU.prototype.int = function (x) {
cpu_util_1.assertNotComplex(x, 'int');
var resultValues = new Int32Array(x.size);
var values = this.readSync(x.dataId);
for (var i = 0; i < values.length; ++i) {
resultValues[i] = values[i];
}
return this.makeOutput(resultValues, x.shape, 'int32');
};
MathBackendCPU.prototype.sigmoid = function (x) {
cpu_util_1.assertNotComplex(x, 'sigmoid');
var resultValues = new Float32Array(x.size);
var values = this.readSync(x.dataId);
for (var i = 0; i < values.length; ++i) {
resultValues[i] = 1 / (1 + Math.exp(-values[i]));
}
return this.makeOutput(resultValues, x.shape, 'float32');
};
MathBackendCPU.prototype.softplus = function (x) {
cpu_util_1.assertNotComplex(x, 'softplus');
// 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 resultValues = new Float32Array(x.size);
var values = this.readSync(x.dataId);
for (var i = 0; i < values.length; ++i) {
// Value above which exp(x) may overflow, but softplus(x) == x
// is within machine epsilon.
var tooLarge = values[i] > -threshold;
// Value below which exp(x) may underflow, but softplus(x) == exp(x)
// is within machine epsilon.
var tooSmall = values[i] < threshold;
var expX = Math.exp(values[i]);
var result = void 0;
if (tooSmall) {
result = expX;
}
else if (tooLarge) {
result = values[i];
}
else {
result = Math.log(1.0 + expX);
}
resultValues[i] = result;
}
return this.makeOutput(resultValues, x.shape, 'float32');
};
MathBackendCPU.prototype.sin = function (x) {
cpu_util_1.assertNotComplex(x, 'sin');
var resultValues = new Float32Array(x.size);
var values = this.readSync(x.dataId);
for (var i = 0; i < values.length; ++i) {
resultValues[i] = Math.sin(values[i]);
}
return this.makeOutput(resultValues, x.shape, 'float32');
};
MathBackendCPU.prototype.cos = function (x) {
cpu_util_1.assertNotComplex(x, 'cos');
var resultValues = new Float32Array(x.size);
var values = this.readSync(x.dataId);
for (var i = 0; i < values.length; ++i) {
resultValues[i] = Math.cos(values[i]);
}
return this.makeOutput(resultValues, x.shape, 'float32');
};
MathBackendCPU.prototype.tan = function (x) {
cpu_util_1.assertNotComplex(x, 'tan');
var resultValues = new Float32Array(x.size);
var values = this.readSync(x.dataId);
for (var i = 0; i < values.length; ++i) {
resultValues[i] = Math.tan(values[i]);
}
return this.makeOutput(resultValues, x.shape, 'float32');
};
MathBackendCPU.prototype.asin = function (x) {
cpu_util_1.assertNotComplex(x, 'asin');
var resultValues = new Float32Array(x.size);
var values = this.readSync(x.dataId);
for (var i = 0; i < values.length; ++i) {