collection.js (4962B)
1 import { isCollection, isMatrix } from './is.js'; 2 import { IndexError } from '../error/IndexError.js'; 3 import { arraySize } from './array.js'; 4 import { _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 12 export 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 29 export 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 57 export 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 77 export 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 100 function _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 134 export 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 }