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
113 lines (105 loc) • 2.96 kB
JavaScript
import { factory } from '../../utils/factory'
import { arraySize } from '../../utils/array'
import { isMatrix } from '../../utils/is'
import { IndexError } from '../../error/IndexError'
const name = 'apply'
const dependencies = ['typed', 'isInteger']
export const createApply = /* #__PURE__ */ factory(name, dependencies, ({ typed, isInteger }) => {
/**
* Apply a function that maps an array to a scalar
* along a given axis of a matrix or array.
* Returns a new matrix or array with one less dimension than the input.
*
* Syntax:
*
* math.apply(A, dim, callback)
*
* Where:
*
* - `dim: number` is a zero-based dimension over which to concatenate the matrices.
*
* Examples:
*
* const A = [[1, 2], [3, 4]]
* const sum = math.sum
*
* math.apply(A, 0, sum) // returns [4, 6]
* math.apply(A, 1, sum) // returns [3, 7]
*
* See also:
*
* map, filter, forEach
*
* @param {Array | Matrix} array The input Matrix
* @param {number} dim The dimension along which the callback is applied
* @param {Function} callback The callback function that is applied. This Function
* should take an array or 1-d matrix as an input and
* return a number.
* @return {Array | Matrix} res The residual matrix with the function applied over some dimension.
*/
return typed(name, {
'Array | Matrix, number | BigNumber, function': function (mat, dim, callback) {
if (!isInteger(dim)) {
throw new TypeError('Integer number expected for dimension')
}
const size = Array.isArray(mat) ? arraySize(mat) : mat.size()
if (dim < 0 || (dim >= size.length)) {
throw new IndexError(dim, size.length)
}
if (isMatrix(mat)) {
return mat.create(_apply(mat.valueOf(), dim, callback))
} else {
return _apply(mat, dim, callback)
}
}
})
})
/**
* Recursively reduce a matrix
* @param {Array} mat
* @param {number} dim
* @param {Function} callback
* @returns {Array} ret
* @private
*/
function _apply (mat, dim, callback) {
let i, ret, tran
if (dim <= 0) {
if (!Array.isArray(mat[0])) {
return callback(mat)
} else {
tran = _switch(mat)
ret = []
for (i = 0; i < tran.length; i++) {
ret[i] = _apply(tran[i], dim - 1, callback)
}
return ret
}
} else {
ret = []
for (i = 0; i < mat.length; i++) {
ret[i] = _apply(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
}