UNPKG

1.89 kBJavaScriptView Raw
1'use strict'
2
3const arraySize = require('../array').size
4const isMatrix = require('../collection/isMatrix')
5const IndexError = require('../../error/IndexError')
6
7/**
8 * Reduce a given matrix or array to a new matrix or
9 * array with one less dimension, applying the given
10 * callback in the selected dimension.
11 * @param {Array | Matrix} mat
12 * @param {number} dim
13 * @param {Function} callback
14 * @return {Array | Matrix} res
15 */
16module.exports = function (mat, dim, callback) {
17 const size = Array.isArray(mat) ? arraySize(mat) : mat.size()
18 if (dim < 0 || (dim >= size.length)) {
19 // TODO: would be more clear when throwing a DimensionError here
20 throw new IndexError(dim, size.length)
21 }
22
23 if (isMatrix(mat)) {
24 return mat.create(_reduce(mat.valueOf(), dim, callback))
25 } else {
26 return _reduce(mat, dim, callback)
27 }
28}
29
30/**
31 * Recursively reduce a matrix
32 * @param {Array} mat
33 * @param {number} dim
34 * @param {Function} callback
35 * @returns {Array} ret
36 * @private
37 */
38function _reduce (mat, dim, callback) {
39 let i, ret, val, tran
40
41 if (dim <= 0) {
42 if (!Array.isArray(mat[0])) {
43 val = mat[0]
44 for (i = 1; i < mat.length; i++) {
45 val = callback(val, mat[i])
46 }
47 return val
48 } else {
49 tran = _switch(mat)
50 ret = []
51 for (i = 0; i < tran.length; i++) {
52 ret[i] = _reduce(tran[i], dim - 1, callback)
53 }
54 return ret
55 }
56 } else {
57 ret = []
58 for (i = 0; i < mat.length; i++) {
59 ret[i] = _reduce(mat[i], dim - 1, callback)
60 }
61 return ret
62 }
63}
64
65/**
66 * Transpose a matrix
67 * @param {Array} mat
68 * @returns {Array} ret
69 * @private
70 */
71function _switch (mat) {
72 const I = mat.length
73 const J = mat[0].length
74 let i, j
75 const ret = []
76 for (j = 0; j < J; j++) {
77 const tmp = []
78 for (i = 0; i < I; i++) {
79 tmp.push(mat[i][j])
80 }
81 ret.push(tmp)
82 }
83 return ret
84}