mathjs/lib/type/collection.js

189 lines
4.5 KiB
JavaScript

var util = require('../util/index.js'),
options = require('../options.js'),
Matrix = require('./Matrix.js'),
isArray = Array.isArray,
isString = util.string.isString;
// utility methods for strings, objects, and arrays
/**
* Convert function arguments to an array. Arguments can have the following
* signature:
* fn()
* fn(n)
* fn(m, n, p, ...)
* fn([m, n, p, ...])
* @param {...Number | Array | Matrix} args
* @returns {Array} array
*/
exports.argsToArray = function argsToArray(args) {
var array;
if (args.length == 0) {
// fn()
array = [];
}
else if (args.length == 1) {
// fn(n)
// fn([m, n, p, ...])
array = args[0];
if (array instanceof Matrix) {
array = array.toVector();
}
if (!isArray(array)) {
array = [array];
}
}
else {
// fn(m, n, p, ...)
array = Array.prototype.slice.apply(args);
}
return array;
};
/**
* Test whether a value is a collection: an Array or Matrix
* @param {*} x
* @returns {boolean} isCollection
*/
exports.isCollection = function isCollection (x) {
return (isArray(x) || (x instanceof Matrix));
};
/**
* Execute function fn element wise for each element in array and any nested
* array
* Returns an array with the results
* @param {Array | Matrix} array
* @param {function} fn
* @return {Array | Matrix} res
*/
exports.deepMap = function deepMap(array, fn) {
if (array && (typeof array.map === 'function')) {
return array.map(function (x) {
return deepMap(x, fn);
});
}
else {
return fn(array);
}
};
/**
* Execute function fn element wise for each entry in two given arrays,
* and for any nested array. Objects can also be scalar objects.
* Returns an array with the results.
* @param {Array | Matrix | Object} array1
* @param {Array | Matrix | Object} array2
* @param {function} fn
* @return {Array | Matrix} res
*/
exports.deepMap2 = function deepMap2(array1, array2, fn) {
var res, len, i;
if (isArray(array1)) {
if (isArray(array2)) {
// fn(array, array)
if (array1.length != array2.length) {
throw new RangeError('Dimension mismatch ' +
'(' + array1.length + ' != ' + array2.length + ')');
}
res = [];
len = array1.length;
for (i = 0; i < len; i++) {
res[i] = deepMap2(array1[i], array2[i], fn);
}
}
else if (array2 instanceof Matrix) {
// fn(array, matrix)
res = deepMap2(array1, array2.valueOf(), fn);
return (options.matrix.default === 'array') ? res : new Matrix(res);
}
else {
// fn(array, object)
res = [];
len = array1.length;
for (i = 0; i < len; i++) {
res[i] = deepMap2(array1[i], array2, fn);
}
}
}
else if (array1 instanceof Matrix) {
if (array2 instanceof Matrix) {
// fn(matrix, matrix)
res = deepMap2(array1.valueOf(), array2.valueOf(), fn);
return new Matrix(res);
}
else {
// fn(matrix, array)
// fn(matrix, object)
res = deepMap2(array1.valueOf(), array2, fn);
return (options.matrix.default === 'array') ? res : new Matrix(res);
}
}
else {
if (isArray(array2)) {
// fn(object, array)
res = [];
len = array2.length;
for (i = 0; i < len; i++) {
res[i] = deepMap2(array1, array2[i], fn);
}
}
else {
// fn(object, object)
res = fn(array1, array2);
}
}
return res;
};
/**
* Convert a given array or matrix to the specified output type for matrices,
* as defined by options.output.matrix
* @param {Matrix | Array} coll
* @return {Matrix | Array} coll
*/
// TODO: throw away toCollection
exports.toCollection = function toCollection (coll) {
switch (options.output.matrix) {
case 'array':
// convert to Array when needed
if (isArray(coll)) {
return coll;
}
else if (coll instanceof Matrix) {
return coll.valueOf();
}
else {
throw new TypeError('Unsupported type of array (' + util.types.type(coll) + ')');
}
break;
case 'matrix':
// convert to Matrix when needed
if (isArray(coll)) {
return new Matrix(coll);
}
else if (coll instanceof Matrix) {
return coll;
}
else {
throw new TypeError('Unsupported type of array (' + util.types.type(coll) + ')');
}
break;
default:
throw new TypeError('options.output.matrix has an unsupported value ' +
'(' + options.output.matrix + '). Available values: "array", "matrix".');
break;
}
};