UNPKG

2.96 kBJavaScriptView Raw
1import { factory } from '../../utils/factory'
2import { arraySize } from '../../utils/array'
3import { isMatrix } from '../../utils/is'
4import { IndexError } from '../../error/IndexError'
5
6const name = 'apply'
7const dependencies = ['typed', 'isInteger']
8
9export const createApply = /* #__PURE__ */ factory(name, dependencies, ({ typed, isInteger }) => {
10 /**
11 * Apply a function that maps an array to a scalar
12 * along a given axis of a matrix or array.
13 * Returns a new matrix or array with one less dimension than the input.
14 *
15 * Syntax:
16 *
17 * math.apply(A, dim, callback)
18 *
19 * Where:
20 *
21 * - `dim: number` is a zero-based dimension over which to concatenate the matrices.
22 *
23 * Examples:
24 *
25 * const A = [[1, 2], [3, 4]]
26 * const sum = math.sum
27 *
28 * math.apply(A, 0, sum) // returns [4, 6]
29 * math.apply(A, 1, sum) // returns [3, 7]
30 *
31 * See also:
32 *
33 * map, filter, forEach
34 *
35 * @param {Array | Matrix} array The input Matrix
36 * @param {number} dim The dimension along which the callback is applied
37 * @param {Function} callback The callback function that is applied. This Function
38 * should take an array or 1-d matrix as an input and
39 * return a number.
40 * @return {Array | Matrix} res The residual matrix with the function applied over some dimension.
41 */
42 return typed(name, {
43 'Array | Matrix, number | BigNumber, function': function (mat, dim, callback) {
44 if (!isInteger(dim)) {
45 throw new TypeError('Integer number expected for dimension')
46 }
47
48 const size = Array.isArray(mat) ? arraySize(mat) : mat.size()
49 if (dim < 0 || (dim >= size.length)) {
50 throw new IndexError(dim, size.length)
51 }
52
53 if (isMatrix(mat)) {
54 return mat.create(_apply(mat.valueOf(), dim, callback))
55 } else {
56 return _apply(mat, dim, callback)
57 }
58 }
59 })
60})
61
62/**
63 * Recursively reduce a matrix
64 * @param {Array} mat
65 * @param {number} dim
66 * @param {Function} callback
67 * @returns {Array} ret
68 * @private
69 */
70function _apply (mat, dim, callback) {
71 let i, ret, tran
72
73 if (dim <= 0) {
74 if (!Array.isArray(mat[0])) {
75 return callback(mat)
76 } else {
77 tran = _switch(mat)
78 ret = []
79 for (i = 0; i < tran.length; i++) {
80 ret[i] = _apply(tran[i], dim - 1, callback)
81 }
82 return ret
83 }
84 } else {
85 ret = []
86 for (i = 0; i < mat.length; i++) {
87 ret[i] = _apply(mat[i], dim - 1, callback)
88 }
89 return ret
90 }
91}
92
93/**
94 * Transpose a matrix
95 * @param {Array} mat
96 * @returns {Array} ret
97 * @private
98 */
99function _switch (mat) {
100 const I = mat.length
101 const J = mat[0].length
102 let i, j
103 const ret = []
104 for (j = 0; j < J; j++) {
105 const tmp = []
106 for (i = 0; i < I; i++) {
107 tmp.push(mat[i][j])
108 }
109 ret.push(tmp)
110 }
111 return ret
112}