UNPKG

mathjs

Version:

Math.js is an extensive math library for JavaScript and Node.js. It features a flexible expression parser with support for symbolic computation, comes with a large set of built-in functions and constants, and offers an integrated solution to work with dif

1,007 lines (935 loc) 32.3 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.createDenseMatrixClass = void 0; var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator")); var _is = require("../../utils/is.js"); var _array = require("../../utils/array.js"); var _string = require("../../utils/string.js"); var _number = require("../../utils/number.js"); var _object = require("../../utils/object.js"); var _DimensionError = require("../../error/DimensionError.js"); var _factory = require("../../utils/factory.js"); var _function = require("../../utils/function.js"); function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it["return"] != null) it["return"](); } finally { if (didErr) throw err; } } }; } function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; } var name = 'DenseMatrix'; var dependencies = ['Matrix']; var createDenseMatrixClass = exports.createDenseMatrixClass = /* #__PURE__ */(0, _factory.factory)(name, dependencies, function (_ref) { var Matrix = _ref.Matrix; /** * Dense Matrix implementation. A regular, dense matrix, supporting multi-dimensional matrices. This is the default matrix type. * @class DenseMatrix * @enum {{ value, index: number[] }} */ function DenseMatrix(data, datatype) { if (!(this instanceof DenseMatrix)) { throw new SyntaxError('Constructor must be called with the new operator'); } if (datatype && !(0, _is.isString)(datatype)) { throw new Error('Invalid datatype: ' + datatype); } if ((0, _is.isMatrix)(data)) { // check data is a DenseMatrix if (data.type === 'DenseMatrix') { // clone data & size this._data = (0, _object.clone)(data._data); this._size = (0, _object.clone)(data._size); this._datatype = datatype || data._datatype; } else { // build data from existing matrix this._data = data.toArray(); this._size = data.size(); this._datatype = datatype || data._datatype; } } else if (data && (0, _is.isArray)(data.data) && (0, _is.isArray)(data.size)) { // initialize fields from JSON representation this._data = data.data; this._size = data.size; // verify the dimensions of the array (0, _array.validate)(this._data, this._size); this._datatype = datatype || data.datatype; } else if ((0, _is.isArray)(data)) { // replace nested Matrices with Arrays this._data = preprocess(data); // get the dimensions of the array this._size = (0, _array.arraySize)(this._data); // verify the dimensions of the array, TODO: compute size while processing array (0, _array.validate)(this._data, this._size); // data type unknown this._datatype = datatype; } else if (data) { // unsupported type throw new TypeError('Unsupported type of data (' + (0, _is.typeOf)(data) + ')'); } else { // nothing provided this._data = []; this._size = [0]; this._datatype = datatype; } } DenseMatrix.prototype = new Matrix(); /** * Create a new DenseMatrix */ DenseMatrix.prototype.createDenseMatrix = function (data, datatype) { return new DenseMatrix(data, datatype); }; /** * Attach type information */ Object.defineProperty(DenseMatrix, 'name', { value: 'DenseMatrix' }); DenseMatrix.prototype.constructor = DenseMatrix; DenseMatrix.prototype.type = 'DenseMatrix'; DenseMatrix.prototype.isDenseMatrix = true; /** * Get the matrix type * * Usage: * const matrixType = matrix.getDataType() // retrieves the matrix type * * @memberOf DenseMatrix * @return {string} type information; if multiple types are found from the Matrix, it will return "mixed" */ DenseMatrix.prototype.getDataType = function () { return (0, _array.getArrayDataType)(this._data, _is.typeOf); }; /** * Get the storage format used by the matrix. * * Usage: * const format = matrix.storage() // retrieve storage format * * @memberof DenseMatrix * @return {string} The storage format. */ DenseMatrix.prototype.storage = function () { return 'dense'; }; /** * Get the datatype of the data stored in the matrix. * * Usage: * const format = matrix.datatype() // retrieve matrix datatype * * @memberof DenseMatrix * @return {string} The datatype. */ DenseMatrix.prototype.datatype = function () { return this._datatype; }; /** * Create a new DenseMatrix * @memberof DenseMatrix * @param {Array} data * @param {string} [datatype] */ DenseMatrix.prototype.create = function (data, datatype) { return new DenseMatrix(data, datatype); }; /** * Get a subset of the matrix, or replace a subset of the matrix. * * Usage: * const subset = matrix.subset(index) // retrieve subset * const value = matrix.subset(index, replacement) // replace subset * * @memberof DenseMatrix * @param {Index} index * @param {Array | Matrix | *} [replacement] * @param {*} [defaultValue=0] Default value, filled in on new entries when * the matrix is resized. If not provided, * new matrix elements will be filled with zeros. */ DenseMatrix.prototype.subset = function (index, replacement, defaultValue) { switch (arguments.length) { case 1: return _get(this, index); // intentional fall through case 2: case 3: return _set(this, index, replacement, defaultValue); default: throw new SyntaxError('Wrong number of arguments'); } }; /** * Get a single element from the matrix. * @memberof DenseMatrix * @param {number[]} index Zero-based index * @return {*} value */ DenseMatrix.prototype.get = function (index) { if (!(0, _is.isArray)(index)) { throw new TypeError('Array expected'); } if (index.length !== this._size.length) { throw new _DimensionError.DimensionError(index.length, this._size.length); } // check index for (var x = 0; x < index.length; x++) { (0, _array.validateIndex)(index[x], this._size[x]); } var data = this._data; for (var i = 0, ii = index.length; i < ii; i++) { var indexI = index[i]; (0, _array.validateIndex)(indexI, data.length); data = data[indexI]; } return data; }; /** * Replace a single element in the matrix. * @memberof DenseMatrix * @param {number[]} index Zero-based index * @param {*} value * @param {*} [defaultValue] Default value, filled in on new entries when * the matrix is resized. If not provided, * new matrix elements will be left undefined. * @return {DenseMatrix} self */ DenseMatrix.prototype.set = function (index, value, defaultValue) { if (!(0, _is.isArray)(index)) { throw new TypeError('Array expected'); } if (index.length < this._size.length) { throw new _DimensionError.DimensionError(index.length, this._size.length, '<'); } var i, ii, indexI; // enlarge matrix when needed var size = index.map(function (i) { return i + 1; }); _fit(this, size, defaultValue); // traverse over the dimensions var data = this._data; for (i = 0, ii = index.length - 1; i < ii; i++) { indexI = index[i]; (0, _array.validateIndex)(indexI, data.length); data = data[indexI]; } // set new value indexI = index[index.length - 1]; (0, _array.validateIndex)(indexI, data.length); data[indexI] = value; return this; }; /** * Get a submatrix of this matrix * @memberof DenseMatrix * @param {DenseMatrix} matrix * @param {Index} index Zero-based index * @private */ function _get(matrix, index) { if (!(0, _is.isIndex)(index)) { throw new TypeError('Invalid index'); } var isScalar = index.isScalar(); if (isScalar) { // return a scalar return matrix.get(index.min()); } else { // validate dimensions var size = index.size(); if (size.length !== matrix._size.length) { throw new _DimensionError.DimensionError(size.length, matrix._size.length); } // validate if any of the ranges in the index is out of range var min = index.min(); var max = index.max(); for (var i = 0, ii = matrix._size.length; i < ii; i++) { (0, _array.validateIndex)(min[i], matrix._size[i]); (0, _array.validateIndex)(max[i], matrix._size[i]); } // retrieve submatrix // TODO: more efficient when creating an empty matrix and setting _data and _size manually return new DenseMatrix(_getSubmatrix(matrix._data, index, size.length, 0), matrix._datatype); } } /** * Recursively get a submatrix of a multi dimensional matrix. * Index is not checked for correct number or length of dimensions. * @memberof DenseMatrix * @param {Array} data * @param {Index} index * @param {number} dims Total number of dimensions * @param {number} dim Current dimension * @return {Array} submatrix * @private */ function _getSubmatrix(data, index, dims, dim) { var last = dim === dims - 1; var range = index.dimension(dim); if (last) { return range.map(function (i) { (0, _array.validateIndex)(i, data.length); return data[i]; }).valueOf(); } else { return range.map(function (i) { (0, _array.validateIndex)(i, data.length); var child = data[i]; return _getSubmatrix(child, index, dims, dim + 1); }).valueOf(); } } /** * Replace a submatrix in this matrix * Indexes are zero-based. * @memberof DenseMatrix * @param {DenseMatrix} matrix * @param {Index} index * @param {DenseMatrix | Array | *} submatrix * @param {*} defaultValue Default value, filled in on new entries when * the matrix is resized. * @return {DenseMatrix} matrix * @private */ function _set(matrix, index, submatrix, defaultValue) { if (!index || index.isIndex !== true) { throw new TypeError('Invalid index'); } // get index size and check whether the index contains a single value var iSize = index.size(); var isScalar = index.isScalar(); // calculate the size of the submatrix, and convert it into an Array if needed var sSize; if ((0, _is.isMatrix)(submatrix)) { sSize = submatrix.size(); submatrix = submatrix.valueOf(); } else { sSize = (0, _array.arraySize)(submatrix); } if (isScalar) { // set a scalar // check whether submatrix is a scalar if (sSize.length !== 0) { throw new TypeError('Scalar expected'); } matrix.set(index.min(), submatrix, defaultValue); } else { // set a submatrix // broadcast submatrix if (!(0, _object.deepStrictEqual)(sSize, iSize)) { try { if (sSize.length === 0) { submatrix = (0, _array.broadcastTo)([submatrix], iSize); } else { submatrix = (0, _array.broadcastTo)(submatrix, iSize); } sSize = (0, _array.arraySize)(submatrix); } catch (_unused) {} } // validate dimensions if (iSize.length < matrix._size.length) { throw new _DimensionError.DimensionError(iSize.length, matrix._size.length, '<'); } if (sSize.length < iSize.length) { // calculate number of missing outer dimensions var i = 0; var outer = 0; while (iSize[i] === 1 && sSize[i] === 1) { i++; } while (iSize[i] === 1) { outer++; i++; } // unsqueeze both outer and inner dimensions submatrix = (0, _array.unsqueeze)(submatrix, iSize.length, outer, sSize); } // check whether the size of the submatrix matches the index size if (!(0, _object.deepStrictEqual)(iSize, sSize)) { throw new _DimensionError.DimensionError(iSize, sSize, '>'); } // enlarge matrix when needed var size = index.max().map(function (i) { return i + 1; }); _fit(matrix, size, defaultValue); // insert the sub matrix var dims = iSize.length; var dim = 0; _setSubmatrix(matrix._data, index, submatrix, dims, dim); } return matrix; } /** * Replace a submatrix of a multi dimensional matrix. * @memberof DenseMatrix * @param {Array} data * @param {Index} index * @param {Array} submatrix * @param {number} dims Total number of dimensions * @param {number} dim * @private */ function _setSubmatrix(data, index, submatrix, dims, dim) { var last = dim === dims - 1; var range = index.dimension(dim); if (last) { range.forEach(function (dataIndex, subIndex) { (0, _array.validateIndex)(dataIndex); data[dataIndex] = submatrix[subIndex[0]]; }); } else { range.forEach(function (dataIndex, subIndex) { (0, _array.validateIndex)(dataIndex); _setSubmatrix(data[dataIndex], index, submatrix[subIndex[0]], dims, dim + 1); }); } } /** * Resize the matrix to the given size. Returns a copy of the matrix when * `copy=true`, otherwise return the matrix itself (resize in place). * * @memberof DenseMatrix * @param {number[] || Matrix} size The new size the matrix should have. * @param {*} [defaultValue=0] Default value, filled in on new entries. * If not provided, the matrix elements will * be filled with zeros. * @param {boolean} [copy] Return a resized copy of the matrix * * @return {Matrix} The resized matrix */ DenseMatrix.prototype.resize = function (size, defaultValue, copy) { // validate arguments if (!(0, _is.isCollection)(size)) { throw new TypeError('Array or Matrix expected'); } // SparseMatrix input is always 2d, flatten this into 1d if it's indeed a vector var sizeArray = size.valueOf().map(function (value) { return Array.isArray(value) && value.length === 1 ? value[0] : value; }); // matrix to resize var m = copy ? this.clone() : this; // resize matrix return _resize(m, sizeArray, defaultValue); }; function _resize(matrix, size, defaultValue) { // check size if (size.length === 0) { // first value in matrix var v = matrix._data; // go deep while ((0, _is.isArray)(v)) { v = v[0]; } return v; } // resize matrix matrix._size = size.slice(0); // copy the array matrix._data = (0, _array.resize)(matrix._data, matrix._size, defaultValue); // return matrix return matrix; } /** * Reshape the matrix to the given size. Returns a copy of the matrix when * `copy=true`, otherwise return the matrix itself (reshape in place). * * NOTE: This might be better suited to copy by default, instead of modifying * in place. For now, it operates in place to remain consistent with * resize(). * * @memberof DenseMatrix * @param {number[]} size The new size the matrix should have. * @param {boolean} [copy] Return a reshaped copy of the matrix * * @return {Matrix} The reshaped matrix */ DenseMatrix.prototype.reshape = function (size, copy) { var m = copy ? this.clone() : this; m._data = (0, _array.reshape)(m._data, size); var currentLength = m._size.reduce(function (length, size) { return length * size; }); m._size = (0, _array.processSizesWildcard)(size, currentLength); return m; }; /** * Enlarge the matrix when it is smaller than given size. * If the matrix is larger or equal sized, nothing is done. * @memberof DenseMatrix * @param {DenseMatrix} matrix The matrix to be resized * @param {number[]} size * @param {*} defaultValue Default value, filled in on new entries. * @private */ function _fit(matrix, size, defaultValue) { var // copy the array newSize = matrix._size.slice(0); var changed = false; // add dimensions when needed while (newSize.length < size.length) { newSize.push(0); changed = true; } // enlarge size when needed for (var i = 0, ii = size.length; i < ii; i++) { if (size[i] > newSize[i]) { newSize[i] = size[i]; changed = true; } } if (changed) { // resize only when size is changed _resize(matrix, newSize, defaultValue); } } /** * Create a clone of the matrix * @memberof DenseMatrix * @return {DenseMatrix} clone */ DenseMatrix.prototype.clone = function () { var m = new DenseMatrix({ data: (0, _object.clone)(this._data), size: (0, _object.clone)(this._size), datatype: this._datatype }); return m; }; /** * Retrieve the size of the matrix. * @memberof DenseMatrix * @returns {number[]} size */ DenseMatrix.prototype.size = function () { return this._size.slice(0); // return a clone of _size }; /** * Create a new matrix with the results of the callback function executed on * each entry of the matrix. * @memberof DenseMatrix * @param {Function} callback The callback function is invoked with three * parameters: the value of the element, the index * of the element, and the Matrix being traversed. * * @return {DenseMatrix} matrix */ DenseMatrix.prototype.map = function (callback) { // matrix instance var me = this; var args = (0, _function.maxArgumentCount)(callback); var recurse = function recurse(value, index) { if ((0, _is.isArray)(value)) { return value.map(function (child, i) { return recurse(child, index.concat(i)); }); } else { // invoke the callback function with the right number of arguments if (args === 1) { return callback(value); } else if (args === 2) { return callback(value, index); } else { // 3 or -1 return callback(value, index, me); } } }; // determine the new datatype when the original matrix has datatype defined // TODO: should be done in matrix constructor instead var data = recurse(this._data, []); var datatype = this._datatype !== undefined ? (0, _array.getArrayDataType)(data, _is.typeOf) : undefined; return new DenseMatrix(data, datatype); }; /** * Execute a callback function on each entry of the matrix. * @memberof DenseMatrix * @param {Function} callback The callback function is invoked with three * parameters: the value of the element, the index * of the element, and the Matrix being traversed. */ DenseMatrix.prototype.forEach = function (callback) { // matrix instance var me = this; var recurse = function recurse(value, index) { if ((0, _is.isArray)(value)) { value.forEach(function (child, i) { recurse(child, index.concat(i)); }); } else { callback(value, index, me); } }; recurse(this._data, []); }; /** * Iterate over the matrix elements * @return {Iterable<{ value, index: number[] }>} */ DenseMatrix.prototype[Symbol.iterator] = /*#__PURE__*/_regenerator["default"].mark(function _callee() { var recurse; return _regenerator["default"].wrap(function _callee$(_context2) { while (1) switch (_context2.prev = _context2.next) { case 0: recurse = /*#__PURE__*/_regenerator["default"].mark(function recurse(value, index) { var i; return _regenerator["default"].wrap(function recurse$(_context) { while (1) switch (_context.prev = _context.next) { case 0: if (!(0, _is.isArray)(value)) { _context.next = 9; break; } i = 0; case 2: if (!(i < value.length)) { _context.next = 7; break; } return _context.delegateYield(recurse(value[i], index.concat(i)), "t0", 4); case 4: i++; _context.next = 2; break; case 7: _context.next = 11; break; case 9: _context.next = 11; return { value: value, index: index }; case 11: case "end": return _context.stop(); } }, recurse); }); return _context2.delegateYield(recurse(this._data, []), "t0", 2); case 2: case "end": return _context2.stop(); } }, _callee, this); }); /** * Returns an array containing the rows of a 2D matrix * @returns {Array<Matrix>} */ DenseMatrix.prototype.rows = function () { var result = []; var s = this.size(); if (s.length !== 2) { throw new TypeError('Rows can only be returned for a 2D matrix.'); } var data = this._data; var _iterator = _createForOfIteratorHelper(data), _step; try { for (_iterator.s(); !(_step = _iterator.n()).done;) { var row = _step.value; result.push(new DenseMatrix([row], this._datatype)); } } catch (err) { _iterator.e(err); } finally { _iterator.f(); } return result; }; /** * Returns an array containing the columns of a 2D matrix * @returns {Array<Matrix>} */ DenseMatrix.prototype.columns = function () { var _this = this; var result = []; var s = this.size(); if (s.length !== 2) { throw new TypeError('Rows can only be returned for a 2D matrix.'); } var data = this._data; var _loop = function _loop(i) { var col = data.map(function (row) { return [row[i]]; }); result.push(new DenseMatrix(col, _this._datatype)); }; for (var i = 0; i < s[1]; i++) { _loop(i); } return result; }; /** * Create an Array with a copy of the data of the DenseMatrix * @memberof DenseMatrix * @returns {Array} array */ DenseMatrix.prototype.toArray = function () { return (0, _object.clone)(this._data); }; /** * Get the primitive value of the DenseMatrix: a multidimensional array * @memberof DenseMatrix * @returns {Array} array */ DenseMatrix.prototype.valueOf = function () { return this._data; }; /** * Get a string representation of the matrix, with optional formatting options. * @memberof DenseMatrix * @param {Object | number | Function} [options] Formatting options. See * lib/utils/number:format for a * description of the available * options. * @returns {string} str */ DenseMatrix.prototype.format = function (options) { return (0, _string.format)(this._data, options); }; /** * Get a string representation of the matrix * @memberof DenseMatrix * @returns {string} str */ DenseMatrix.prototype.toString = function () { return (0, _string.format)(this._data); }; /** * Get a JSON representation of the matrix * @memberof DenseMatrix * @returns {Object} */ DenseMatrix.prototype.toJSON = function () { return { mathjs: 'DenseMatrix', data: this._data, size: this._size, datatype: this._datatype }; }; /** * Get the kth Matrix diagonal. * * @memberof DenseMatrix * @param {number | BigNumber} [k=0] The kth diagonal where the vector will retrieved. * * @returns {Matrix} The matrix with the diagonal values. */ DenseMatrix.prototype.diagonal = function (k) { // validate k if any if (k) { // convert BigNumber to a number if ((0, _is.isBigNumber)(k)) { k = k.toNumber(); } // is must be an integer if (!(0, _is.isNumber)(k) || !(0, _number.isInteger)(k)) { throw new TypeError('The parameter k must be an integer number'); } } else { // default value k = 0; } var kSuper = k > 0 ? k : 0; var kSub = k < 0 ? -k : 0; // rows & columns var rows = this._size[0]; var columns = this._size[1]; // number diagonal values var n = Math.min(rows - kSub, columns - kSuper); // x is a matrix get diagonal from matrix var data = []; // loop rows for (var i = 0; i < n; i++) { data[i] = this._data[i + kSub][i + kSuper]; } // create DenseMatrix return new DenseMatrix({ data: data, size: [n], datatype: this._datatype }); }; /** * Create a diagonal matrix. * * @memberof DenseMatrix * @param {Array} size The matrix size. * @param {number | Matrix | Array } value The values for the diagonal. * @param {number | BigNumber} [k=0] The kth diagonal where the vector will be filled in. * @param {number} [defaultValue] The default value for non-diagonal * @param {string} [datatype] The datatype for the diagonal * * @returns {DenseMatrix} */ DenseMatrix.diagonal = function (size, value, k, defaultValue) { if (!(0, _is.isArray)(size)) { throw new TypeError('Array expected, size parameter'); } if (size.length !== 2) { throw new Error('Only two dimensions matrix are supported'); } // map size & validate size = size.map(function (s) { // check it is a big number if ((0, _is.isBigNumber)(s)) { // convert it s = s.toNumber(); } // validate arguments if (!(0, _is.isNumber)(s) || !(0, _number.isInteger)(s) || s < 1) { throw new Error('Size values must be positive integers'); } return s; }); // validate k if any if (k) { // convert BigNumber to a number if ((0, _is.isBigNumber)(k)) { k = k.toNumber(); } // is must be an integer if (!(0, _is.isNumber)(k) || !(0, _number.isInteger)(k)) { throw new TypeError('The parameter k must be an integer number'); } } else { // default value k = 0; } var kSuper = k > 0 ? k : 0; var kSub = k < 0 ? -k : 0; // rows and columns var rows = size[0]; var columns = size[1]; // number of non-zero items var n = Math.min(rows - kSub, columns - kSuper); // value extraction function var _value; // check value if ((0, _is.isArray)(value)) { // validate array if (value.length !== n) { // number of values in array must be n throw new Error('Invalid value array length'); } // define function _value = function _value(i) { // return value @ i return value[i]; }; } else if ((0, _is.isMatrix)(value)) { // matrix size var ms = value.size(); // validate matrix if (ms.length !== 1 || ms[0] !== n) { // number of values in array must be n throw new Error('Invalid matrix length'); } // define function _value = function _value(i) { // return value @ i return value.get([i]); }; } else { // define function _value = function _value() { // return value return value; }; } // discover default value if needed if (!defaultValue) { // check first value in array defaultValue = (0, _is.isBigNumber)(_value(0)) ? _value(0).mul(0) // trick to create a BigNumber with value zero : 0; } // empty array var data = []; // check we need to resize array if (size.length > 0) { // resize array data = (0, _array.resize)(data, size, defaultValue); // fill diagonal for (var d = 0; d < n; d++) { data[d + kSub][d + kSuper] = _value(d); } } // create DenseMatrix return new DenseMatrix({ data: data, size: [rows, columns] }); }; /** * Generate a matrix from a JSON object * @memberof DenseMatrix * @param {Object} json An object structured like * `{"mathjs": "DenseMatrix", data: [], size: []}`, * where mathjs is optional * @returns {DenseMatrix} */ DenseMatrix.fromJSON = function (json) { return new DenseMatrix(json); }; /** * Swap rows i and j in Matrix. * * @memberof DenseMatrix * @param {number} i Matrix row index 1 * @param {number} j Matrix row index 2 * * @return {Matrix} The matrix reference */ DenseMatrix.prototype.swapRows = function (i, j) { // check index if (!(0, _is.isNumber)(i) || !(0, _number.isInteger)(i) || !(0, _is.isNumber)(j) || !(0, _number.isInteger)(j)) { throw new Error('Row index must be positive integers'); } // check dimensions if (this._size.length !== 2) { throw new Error('Only two dimensional matrix is supported'); } // validate index (0, _array.validateIndex)(i, this._size[0]); (0, _array.validateIndex)(j, this._size[0]); // swap rows DenseMatrix._swapRows(i, j, this._data); // return current instance return this; }; /** * Swap rows i and j in Dense Matrix data structure. * * @param {number} i Matrix row index 1 * @param {number} j Matrix row index 2 * @param {Array} data Matrix data */ DenseMatrix._swapRows = function (i, j, data) { // swap values i <-> j var vi = data[i]; data[i] = data[j]; data[j] = vi; }; /** * Preprocess data, which can be an Array or DenseMatrix with nested Arrays and * Matrices. Clones all (nested) Arrays, and replaces all nested Matrices with Arrays * @memberof DenseMatrix * @param {Array | Matrix} data * @return {Array} data */ function preprocess(data) { if ((0, _is.isMatrix)(data)) { return preprocess(data.valueOf()); } if ((0, _is.isArray)(data)) { return data.map(preprocess); } return data; } return DenseMatrix; }, { isClass: true });