mirror of
https://github.com/josdejong/mathjs.git
synced 2026-01-18 14:59:29 +00:00
Refactored concat and flatten to typed-functions
This commit is contained in:
parent
af5d978de4
commit
952ec790cf
4
index.js
4
index.js
@ -128,13 +128,13 @@ function create (config) {
|
||||
math.import(require('./lib/function/logical/xor'));
|
||||
|
||||
// functions - matrix
|
||||
require('./lib/function/matrix/concat')(math, _config);
|
||||
math.import(require('./lib/function/matrix/concat'));
|
||||
math.import(require('./lib/function/matrix/cross'));
|
||||
math.import(require('./lib/function/matrix/det'));
|
||||
math.import(require('./lib/function/matrix/diag'));
|
||||
math.import(require('./lib/function/matrix/dot'));
|
||||
math.import(require('./lib/function/matrix/eye'));
|
||||
require('./lib/function/matrix/flatten')(math, _config);
|
||||
math.import(require('./lib/function/matrix/flatten'));
|
||||
math.import(require('./lib/function/matrix/inv'));
|
||||
require('./lib/function/matrix/ones')(math, _config);
|
||||
require('./lib/function/matrix/range')(math, _config);
|
||||
|
||||
@ -1,17 +1,13 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = function (math) {
|
||||
var util = require('../../util/index');
|
||||
var clone = require('../../util/object').clone;
|
||||
var isInteger = require('../../util/number').isInteger;
|
||||
var array = require('../../util/array');
|
||||
var IndexError = require('../../error/IndexError');
|
||||
var DimensionError = require('../../error/DimensionError');
|
||||
|
||||
var BigNumber = require('decimal.js');
|
||||
var Matrix = math.type.Matrix;
|
||||
var collection = math.collection;
|
||||
|
||||
var object = util.object;
|
||||
var array = util.array;
|
||||
var isNumber = util.number.isNumber;
|
||||
var isInteger = util.number.isInteger;
|
||||
var isCollection = collection.isCollection;
|
||||
function factory (type, config, load, typed) {
|
||||
var matrix = load(require('../construction/matrix'));
|
||||
|
||||
/**
|
||||
* Concatenate two or more matrices.
|
||||
@ -41,96 +37,103 @@ module.exports = function (math) {
|
||||
* @param {... Array | Matrix} args Two or more matrices
|
||||
* @return {Array | Matrix} Concatenated matrix
|
||||
*/
|
||||
math.concat = function concat (args) {
|
||||
var i,
|
||||
len = arguments.length,
|
||||
dim = -1, // zero-based dimension
|
||||
prevDim,
|
||||
asMatrix = false,
|
||||
matrices = []; // contains multi dimensional arrays
|
||||
return typed('concat', {
|
||||
// TODO: change signature to '...Array | Matrix, dim?' when supported
|
||||
'...Array | Matrix | number | BigNumber': function (args) {
|
||||
var i;
|
||||
var len = args.length;
|
||||
var dim = -1; // zero-based dimension
|
||||
var prevDim;
|
||||
var asMatrix = false;
|
||||
var matrices = []; // contains multi dimensional arrays
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
var arg = arguments[i];
|
||||
for (i = 0; i < len; i++) {
|
||||
var arg = args[i];
|
||||
|
||||
// test whether we need to return a Matrix (if not we return an Array)
|
||||
if (arg instanceof Matrix) {
|
||||
asMatrix = true;
|
||||
}
|
||||
|
||||
if ((i == len - 1) && (isNumber(arg) || arg instanceof BigNumber)) {
|
||||
// last argument contains the dimension on which to concatenate
|
||||
prevDim = dim;
|
||||
dim = arg.valueOf(); // change bignumber to number
|
||||
|
||||
if (!isInteger(dim)) {
|
||||
throw new TypeError('Integer number expected for dimension');
|
||||
// test whether we need to return a Matrix (if not we return an Array)
|
||||
if (arg instanceof type.Matrix) {
|
||||
asMatrix = true;
|
||||
}
|
||||
|
||||
if (dim < 0) {
|
||||
// TODO: would be more clear when throwing a DimensionError here
|
||||
throw new math.error.IndexError(dim);
|
||||
if (typeof arg === 'number' || arg instanceof type.BigNumber) {
|
||||
if (i !== len - 1) {
|
||||
throw new Error('Dimension must be specified as last argument');
|
||||
}
|
||||
|
||||
// last argument contains the dimension on which to concatenate
|
||||
prevDim = dim;
|
||||
dim = arg.valueOf(); // change BigNumber to number
|
||||
|
||||
if (!isInteger(dim)) {
|
||||
throw new TypeError('Integer number expected for dimension');
|
||||
}
|
||||
|
||||
if (dim < 0) {
|
||||
// TODO: would be more clear when throwing a DimensionError here
|
||||
throw new IndexError(dim);
|
||||
}
|
||||
if (i > 0 && dim > prevDim) {
|
||||
// TODO: would be more clear when throwing a DimensionError here
|
||||
throw new IndexError(dim, prevDim + 1);
|
||||
}
|
||||
}
|
||||
if (i > 0 && dim > prevDim) {
|
||||
// TODO: would be more clear when throwing a DimensionError here
|
||||
throw new math.error.IndexError(dim, prevDim + 1);
|
||||
else {
|
||||
// this is a matrix or array
|
||||
var m = clone(arg).valueOf();
|
||||
var size = array.size(m);
|
||||
matrices[i] = m;
|
||||
prevDim = dim;
|
||||
dim = size.length - 1;
|
||||
|
||||
// verify whether each of the matrices has the same number of dimensions
|
||||
if (i > 0 && dim != prevDim) {
|
||||
throw new DimensionError(prevDim + 1, dim + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (isCollection(arg)) {
|
||||
// this is a matrix or array
|
||||
var matrix = object.clone(arg).valueOf();
|
||||
var size = array.size(arg.valueOf());
|
||||
matrices[i] = matrix;
|
||||
prevDim = dim;
|
||||
dim = size.length - 1;
|
||||
|
||||
// verify whether each of the matrices has the same number of dimensions
|
||||
if (i > 0 && dim != prevDim) {
|
||||
throw new math.error.DimensionError(prevDim + 1, dim + 1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw new math.error.UnsupportedTypeError('concat', math['typeof'](arg));
|
||||
}
|
||||
}
|
||||
|
||||
if (matrices.length == 0) {
|
||||
throw new SyntaxError('At least one matrix expected');
|
||||
}
|
||||
|
||||
var res = matrices.shift();
|
||||
while (matrices.length) {
|
||||
res = _concat(res, matrices.shift(), dim, 0);
|
||||
}
|
||||
|
||||
return asMatrix ? math.matrix(res) : res;
|
||||
};
|
||||
|
||||
/**
|
||||
* Recursively concatenate two matrices.
|
||||
* The contents of the matrices is not cloned.
|
||||
* @param {Array} a Multi dimensional array
|
||||
* @param {Array} b Multi dimensional array
|
||||
* @param {Number} concatDim The dimension on which to concatenate (zero-based)
|
||||
* @param {Number} dim The current dim (zero-based)
|
||||
* @return {Array} c The concatenated matrix
|
||||
* @private
|
||||
*/
|
||||
function _concat(a, b, concatDim, dim) {
|
||||
if (dim < concatDim) {
|
||||
// recurse into next dimension
|
||||
if (a.length != b.length) {
|
||||
throw new math.error.DimensionError(a.length, b.length);
|
||||
if (matrices.length == 0) {
|
||||
throw new SyntaxError('At least one matrix expected');
|
||||
}
|
||||
|
||||
var c = [];
|
||||
for (var i = 0; i < a.length; i++) {
|
||||
c[i] = _concat(a[i], b[i], concatDim, dim + 1);
|
||||
var res = matrices.shift();
|
||||
while (matrices.length) {
|
||||
res = _concat(res, matrices.shift(), dim, 0);
|
||||
}
|
||||
return c;
|
||||
|
||||
return asMatrix ? matrix(res) : res;
|
||||
}
|
||||
else {
|
||||
// concatenate this dimension
|
||||
return a.concat(b);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively concatenate two matrices.
|
||||
* The contents of the matrices is not cloned.
|
||||
* @param {Array} a Multi dimensional array
|
||||
* @param {Array} b Multi dimensional array
|
||||
* @param {Number} concatDim The dimension on which to concatenate (zero-based)
|
||||
* @param {Number} dim The current dim (zero-based)
|
||||
* @return {Array} c The concatenated matrix
|
||||
* @private
|
||||
*/
|
||||
function _concat(a, b, concatDim, dim) {
|
||||
if (dim < concatDim) {
|
||||
// recurse into next dimension
|
||||
if (a.length != b.length) {
|
||||
throw new DimensionError(a.length, b.length);
|
||||
}
|
||||
|
||||
var c = [];
|
||||
for (var i = 0; i < a.length; i++) {
|
||||
c[i] = _concat(a[i], b[i], concatDim, dim + 1);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
};
|
||||
else {
|
||||
// concatenate this dimension
|
||||
return a.concat(b);
|
||||
}
|
||||
}
|
||||
|
||||
exports.name = 'concat';
|
||||
exports.factory = factory;
|
||||
|
||||
@ -1,13 +1,10 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = function (math, config) {
|
||||
var util = require('../../util/index');
|
||||
var clone = require('../../util/object').clone;
|
||||
var _flatten = require('../../util/array').flatten;
|
||||
|
||||
var Matrix = math.type.Matrix;
|
||||
|
||||
var object = util.object;
|
||||
var array = util.array;
|
||||
var isArray = Array.isArray;
|
||||
function factory (type, config, load, typed) {
|
||||
var matrix = load(require('../construction/matrix'));
|
||||
|
||||
/**
|
||||
* Flatten a multi dimensional matrix into a single dimensional matrix.
|
||||
@ -27,21 +24,18 @@ module.exports = function (math, config) {
|
||||
* @param {Matrix | Array} x Matrix to be flattened
|
||||
* @return {Matrix | Array} Returns the flattened matrix
|
||||
*/
|
||||
math.flatten = function flatten (x) {
|
||||
if (arguments.length !== 1) {
|
||||
throw new math.error.ArgumentsError('flatten', arguments.length, 1);
|
||||
}
|
||||
return typed('flatten', {
|
||||
'Array': function (x) {
|
||||
return _flatten(clone(x));
|
||||
},
|
||||
|
||||
if (x instanceof Matrix) {
|
||||
var clone = object.clone(x.toArray());
|
||||
var flat = array.flatten(clone);
|
||||
return math.matrix(flat);
|
||||
'Matrix': function (x) {
|
||||
var flat = _flatten(clone(x.toArray()));
|
||||
// TODO: return the same matrix type as x
|
||||
return matrix(flat);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (isArray(x)) {
|
||||
return array.flatten(object.clone(x));
|
||||
}
|
||||
|
||||
throw new math.error.UnsupportedTypeError('flatten', math['typeof'](x));
|
||||
};
|
||||
};
|
||||
exports.name = 'flatten';
|
||||
exports.factory = factory;
|
||||
|
||||
@ -60,9 +60,7 @@ function factory (type, config, load, typed) {
|
||||
return c;
|
||||
},
|
||||
|
||||
'any': function (x) {
|
||||
return clone(x);
|
||||
}
|
||||
'any': clone
|
||||
});
|
||||
|
||||
var _denseTrace = function (m) {
|
||||
|
||||
@ -94,7 +94,7 @@ describe('concat', function() {
|
||||
});
|
||||
|
||||
it('should throw an error in case of invalid type of argument', function() {
|
||||
assert.throws(function () {math.concat(math.complex(2,3))}, math.error.UnsupportedTypeError);
|
||||
assert.throws(function () {math.concat(math.complex(2,3))}, /TypeError: Unexpected type of argument/);
|
||||
});
|
||||
|
||||
it('should throw an error when called without matrices as argument', function() {
|
||||
|
||||
@ -42,9 +42,9 @@ describe('flatten', function() {
|
||||
});
|
||||
|
||||
it('should throw an error on invalid arguments', function () {
|
||||
assert.throws(function () {flatten()}, /ArgumentsError/);
|
||||
assert.throws(function () {flatten([],2)}, /ArgumentsError/);
|
||||
assert.throws(function () {flatten("str")}, /TypeError/);
|
||||
assert.throws(function () {flatten()}, /TypeError: Too few arguments/);
|
||||
assert.throws(function () {flatten([],2)}, /TypeError: Too many arguments/);
|
||||
assert.throws(function () {flatten("str")}, /TypeError: Unexpected type of argument/);
|
||||
});
|
||||
|
||||
it('should LaTeX flatten', function () {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user