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
85 lines (78 loc) • 1.89 kB
JavaScript
const arraySize = require('../array').size
const isMatrix = require('../collection/isMatrix')
const IndexError = require('../../error/IndexError')
/**
* Reduce a given matrix or array to a new matrix or
* array with one less dimension, applying the given
* callback in the selected dimension.
* @param {Array | Matrix} mat
* @param {number} dim
* @param {Function} callback
* @return {Array | Matrix} res
*/
module.exports = function (mat, dim, callback) {
const size = Array.isArray(mat) ? arraySize(mat) : mat.size()
if (dim < 0 || (dim >= size.length)) {
// TODO: would be more clear when throwing a DimensionError here
throw new IndexError(dim, size.length)
}
if (isMatrix(mat)) {
return mat.create(_reduce(mat.valueOf(), dim, callback))
} else {
return _reduce(mat, dim, callback)
}
}
/**
* Recursively reduce a matrix
* @param {Array} mat
* @param {number} dim
* @param {Function} callback
* @returns {Array} ret
* @private
*/
function _reduce (mat, dim, callback) {
let i, ret, val, tran
if (dim <= 0) {
if (!Array.isArray(mat[0])) {
val = mat[0]
for (i = 1; i < mat.length; i++) {
val = callback(val, mat[i])
}
return val
} else {
tran = _switch(mat)
ret = []
for (i = 0; i < tran.length; i++) {
ret[i] = _reduce(tran[i], dim - 1, callback)
}
return ret
}
} else {
ret = []
for (i = 0; i < mat.length; i++) {
ret[i] = _reduce(mat[i], dim - 1, callback)
}
return ret
}
}
/**
* Transpose a matrix
* @param {Array} mat
* @returns {Array} ret
* @private
*/
function _switch (mat) {
const I = mat.length
const J = mat[0].length
let i, j
const ret = []
for (j = 0; j < J; j++) {
const tmp = []
for (i = 0; i < I; i++) {
tmp.push(mat[i][j])
}
ret.push(tmp)
}
return ret
}