UNPKG

mathjs

Version:

Math.js is an extensive math library for JavaScript and Node.js. It features a flexible expression parser and offers an integrated solution to work with numbers, big numbers, complex numbers, units, and matrices.

239 lines (207 loc) 6.42 kB
'use strict'; var clone = require('../../utils/object').clone; var isInteger = require('../../utils/number').isInteger; function factory (type) { /** * @Constructor Index * Create an index. An Index can store ranges and sets for multiple dimensions. * Matrix.get, Matrix.set, and math.subset accept an Index as input. * * Usage: * var index = new Index(range1, range2, matrix1, array1, ...); * * Where each parameter can be any of: * A number * An instance of Range * An Array with the Set values * A Matrix with the Set values * * The parameters start, end, and step must be integer numbers. * * @param {...*} ranges */ function Index(ranges) { if (!(this instanceof Index)) { throw new SyntaxError('Constructor must be called with the new operator'); } this._dimensions = []; this._isScalar = true; for (var i = 0, ii = arguments.length; i < ii; i++) { var arg = arguments[i]; if (arg && (arg.isRange === true)) { this._dimensions.push(arg); this._isScalar = false; } else if (arg && (Array.isArray(arg) || arg.isMatrix === true)) { // create matrix var m = _createImmutableMatrix(arg.valueOf()); this._dimensions.push(m); // size var size = m.size(); // scalar this._isScalar = size.length === 1 && size[0] === 1; } else if (typeof arg === 'number') { this._dimensions.push(_createImmutableMatrix([arg])); } // TODO: implement support for wildcard '*' else { throw new TypeError('Dimension must be an Array, Matrix, Number or Range'); } } } /** * Attach type information */ Index.prototype.type = 'Index'; Index.prototype.isIndex = true; function _createImmutableMatrix(arg) { // loop array elements for (var i = 0, l = arg.length; i < l; i++) { if (typeof arg[i] !== 'number' || !isInteger(arg[i])) { throw new TypeError('Index parameters must be positive integer numbers'); } } // create matrix return new type.ImmutableDenseMatrix(arg); } /** * Create a clone of the index * @return {Index} clone */ Index.prototype.clone = function () { var index = new Index(); index._dimensions = clone(this._dimensions); index._isScalar = this._isScalar; return index; }; /** * Create an index from an array with ranges/numbers * @param {Array.<Array | number>} ranges * @return {Index} index * @private */ Index.create = function (ranges) { var index = new Index(); Index.apply(index, ranges); return index; }; /** * Retrieve the size of the index, the number of elements for each dimension. * @returns {number[]} size */ Index.prototype.size = function () { var size = []; for (var i = 0, ii = this._dimensions.length; i < ii; i++) { var d = this._dimensions[i]; size[i] = d.size()[0]; } return size; }; /** * Get the maximum value for each of the indexes ranges. * @returns {number[]} max */ Index.prototype.max = function () { var values = []; for (var i = 0, ii = this._dimensions.length; i < ii; i++) { var range = this._dimensions[i]; values[i] = range.max(); } return values; }; /** * Get the minimum value for each of the indexes ranges. * @returns {number[]} min */ Index.prototype.min = function () { var values = []; for (var i = 0, ii = this._dimensions.length; i < ii; i++) { var range = this._dimensions[i]; values[i] = range.min(); } return values; }; /** * Loop over each of the ranges of the index * @param {Function} callback Called for each range with a Range as first * argument, the dimension as second, and the * index object as third. */ Index.prototype.forEach = function (callback) { for (var i = 0, ii = this._dimensions.length; i < ii; i++) { callback(this._dimensions[i], i, this); } }; /** * Retrieve the dimension for the given index * @param {Number} dim Number of the dimension * @returns {Range | null} range */ Index.prototype.dimension = function (dim) { return this._dimensions[dim] || null; }; /** * Test whether this index contains only a single value. * * This is the case when the index is created with only scalar values as ranges, * not for ranges resolving into a single value. * @return {boolean} isScalar */ Index.prototype.isScalar = function () { return this._isScalar; }; /** * Expand the Index into an array. * For example new Index([0,3], [2,7]) returns [[0,1,2], [2,3,4,5,6]] * @returns {Array} array */ Index.prototype.toArray = function () { var array = []; for (var i = 0, ii = this._dimensions.length; i < ii; i++) { array.push(this._dimensions[i].toArray()); } return array; }; /** * Get the primitive value of the Index, a two dimensional array. * Equivalent to Index.toArray(). * @returns {Array} array */ Index.prototype.valueOf = Index.prototype.toArray; /** * Get the string representation of the index, for example '[2:6]' or '[0:2:10, 4:7, [1,2,3]]' * @returns {String} str */ Index.prototype.toString = function () { var strings = []; for (var i = 0, ii = this._dimensions.length; i < ii; i++) { strings.push(this._dimensions[i].toString()); } return '[' + strings.join(', ') + ']'; }; /** * Get a JSON representation of the Index * @returns {Object} Returns a JSON object structured as: * `{"mathjs": "Index", "ranges": [{"mathjs": "Range", start: 0, end: 10, step:1}, ...]}` */ Index.prototype.toJSON = function () { return { mathjs: 'Index', dimensions: this._dimensions }; }; /** * Instantiate an Index from a JSON object * @param {Object} json A JSON object structured as: * `{"mathjs": "Index", "dimensions": [{"mathjs": "Range", start: 0, end: 10, step:1}, ...]}` * @return {Index} */ Index.fromJSON = function (json) { return Index.create(json.dimensions); }; return Index; } exports.name = 'Index'; exports.path = 'type'; exports.factory = factory;