UNPKG

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