UNPKG

5.26 kBJavaScriptView Raw
1import { isCollection, isMatrix } from './is.js';
2import { IndexError } from '../error/IndexError.js';
3import { arraySize } from './array.js';
4/**
5 * Test whether an array contains collections
6 * @param {Array} array
7 * @returns {boolean} Returns true when the array contains one or multiple
8 * collections (Arrays or Matrices). Returns false otherwise.
9 */
10
11export function containsCollections(array) {
12 for (var i = 0; i < array.length; i++) {
13 if (isCollection(array[i])) {
14 return true;
15 }
16 }
17
18 return false;
19}
20/**
21 * Recursively loop over all elements in a given multi dimensional array
22 * and invoke the callback on each of the elements.
23 * @param {Array | Matrix} array
24 * @param {Function} callback The callback method is invoked with one
25 * parameter: the current element in the array
26 */
27
28export function deepForEach(array, callback) {
29 if (isMatrix(array)) {
30 array = array.valueOf();
31 }
32
33 for (var i = 0, ii = array.length; i < ii; i++) {
34 var value = array[i];
35
36 if (Array.isArray(value)) {
37 deepForEach(value, callback);
38 } else {
39 callback(value);
40 }
41 }
42}
43/**
44 * Execute the callback function element wise for each element in array and any
45 * nested array
46 * Returns an array with the results
47 * @param {Array | Matrix} array
48 * @param {Function} callback The callback is called with two parameters:
49 * value1 and value2, which contain the current
50 * element of both arrays.
51 * @param {boolean} [skipZeros] Invoke callback function for non-zero values only.
52 *
53 * @return {Array | Matrix} res
54 */
55
56export function deepMap(array, callback, skipZeros) {
57 if (array && typeof array.map === 'function') {
58 // TODO: replace array.map with a for loop to improve performance
59 return array.map(function (x) {
60 return deepMap(x, callback, skipZeros);
61 });
62 } else {
63 return callback(array);
64 }
65}
66/**
67 * Reduce a given matrix or array to a new matrix or
68 * array with one less dimension, applying the given
69 * callback in the selected dimension.
70 * @param {Array | Matrix} mat
71 * @param {number} dim
72 * @param {Function} callback
73 * @return {Array | Matrix} res
74 */
75
76export function reduce(mat, dim, callback) {
77 var size = Array.isArray(mat) ? arraySize(mat) : mat.size();
78
79 if (dim < 0 || dim >= size.length) {
80 // TODO: would be more clear when throwing a DimensionError here
81 throw new IndexError(dim, size.length);
82 }
83
84 if (isMatrix(mat)) {
85 return mat.create(_reduce(mat.valueOf(), dim, callback));
86 } else {
87 return _reduce(mat, dim, callback);
88 }
89}
90/**
91 * Recursively reduce a matrix
92 * @param {Array} mat
93 * @param {number} dim
94 * @param {Function} callback
95 * @returns {Array} ret
96 * @private
97 */
98
99function _reduce(mat, dim, callback) {
100 var i, ret, val, tran;
101
102 if (dim <= 0) {
103 if (!Array.isArray(mat[0])) {
104 val = mat[0];
105
106 for (i = 1; i < mat.length; i++) {
107 val = callback(val, mat[i]);
108 }
109
110 return val;
111 } else {
112 tran = _switch(mat);
113 ret = [];
114
115 for (i = 0; i < tran.length; i++) {
116 ret[i] = _reduce(tran[i], dim - 1, callback);
117 }
118
119 return ret;
120 }
121 } else {
122 ret = [];
123
124 for (i = 0; i < mat.length; i++) {
125 ret[i] = _reduce(mat[i], dim - 1, callback);
126 }
127
128 return ret;
129 }
130}
131/**
132 * Transpose a matrix
133 * @param {Array} mat
134 * @returns {Array} ret
135 * @private
136 */
137
138
139function _switch(mat) {
140 var I = mat.length;
141 var J = mat[0].length;
142 var i, j;
143 var ret = [];
144
145 for (j = 0; j < J; j++) {
146 var tmp = [];
147
148 for (i = 0; i < I; i++) {
149 tmp.push(mat[i][j]);
150 }
151
152 ret.push(tmp);
153 }
154
155 return ret;
156} // TODO: document function scatter
157
158
159export function scatter(a, j, w, x, u, mark, cindex, f, inverse, update, value) {
160 // a arrays
161 var avalues = a._values;
162 var aindex = a._index;
163 var aptr = a._ptr; // vars
164
165 var k, k0, k1, i; // check we need to process values (pattern matrix)
166
167 if (x) {
168 // values in j
169 for (k0 = aptr[j], k1 = aptr[j + 1], k = k0; k < k1; k++) {
170 // row
171 i = aindex[k]; // check value exists in current j
172
173 if (w[i] !== mark) {
174 // i is new entry in j
175 w[i] = mark; // add i to pattern of C
176
177 cindex.push(i); // x(i) = A, check we need to call function this time
178
179 if (update) {
180 // copy value to workspace calling callback function
181 x[i] = inverse ? f(avalues[k], value) : f(value, avalues[k]); // function was called on current row
182
183 u[i] = mark;
184 } else {
185 // copy value to workspace
186 x[i] = avalues[k];
187 }
188 } else {
189 // i exists in C already
190 x[i] = inverse ? f(avalues[k], x[i]) : f(x[i], avalues[k]); // function was called on current row
191
192 u[i] = mark;
193 }
194 }
195 } else {
196 // values in j
197 for (k0 = aptr[j], k1 = aptr[j + 1], k = k0; k < k1; k++) {
198 // row
199 i = aindex[k]; // check value exists in current j
200
201 if (w[i] !== mark) {
202 // i is new entry in j
203 w[i] = mark; // add i to pattern of C
204
205 cindex.push(i);
206 } else {
207 // indicate function was called on current row
208 u[i] = mark;
209 }
210 }
211 }
212}
\No newline at end of file