UNPKG

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