123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177 |
- import { isCollection, isMatrix } from './is.js';
- import { IndexError } from '../error/IndexError.js';
- import { arraySize } from './array.js';
- import { _switch } from './switch.js';
- /**
- * Test whether an array contains collections
- * @param {Array} array
- * @returns {boolean} Returns true when the array contains one or multiple
- * collections (Arrays or Matrices). Returns false otherwise.
- */
- export function containsCollections(array) {
- for (var i = 0; i < array.length; i++) {
- if (isCollection(array[i])) {
- return true;
- }
- }
- return false;
- }
- /**
- * Recursively loop over all elements in a given multi dimensional array
- * and invoke the callback on each of the elements.
- * @param {Array | Matrix} array
- * @param {Function} callback The callback method is invoked with one
- * parameter: the current element in the array
- */
- export function deepForEach(array, callback) {
- if (isMatrix(array)) {
- array = array.valueOf();
- }
- for (var i = 0, ii = array.length; i < ii; i++) {
- var value = array[i];
- if (Array.isArray(value)) {
- deepForEach(value, callback);
- } else {
- callback(value);
- }
- }
- }
- /**
- * Execute the callback function element wise for each element in array and any
- * nested array
- * Returns an array with the results
- * @param {Array | Matrix} array
- * @param {Function} callback The callback is called with two parameters:
- * value1 and value2, which contain the current
- * element of both arrays.
- * @param {boolean} [skipZeros] Invoke callback function for non-zero values only.
- *
- * @return {Array | Matrix} res
- */
- export function deepMap(array, callback, skipZeros) {
- if (array && typeof array.map === 'function') {
- // TODO: replace array.map with a for loop to improve performance
- return array.map(function (x) {
- return deepMap(x, callback, skipZeros);
- });
- } else {
- return callback(array);
- }
- }
- /**
- * Reduce a given matrix or array to a new matrix or
- * array with one less dimension, applying the given
- * callback in the selected dimension.
- * @param {Array | Matrix} mat
- * @param {number} dim
- * @param {Function} callback
- * @return {Array | Matrix} res
- */
- export function reduce(mat, dim, callback) {
- var size = Array.isArray(mat) ? arraySize(mat) : mat.size();
- if (dim < 0 || dim >= size.length) {
- // TODO: would be more clear when throwing a DimensionError here
- throw new IndexError(dim, size.length);
- }
- if (isMatrix(mat)) {
- return mat.create(_reduce(mat.valueOf(), dim, callback));
- } else {
- return _reduce(mat, dim, callback);
- }
- }
- /**
- * Recursively reduce a matrix
- * @param {Array} mat
- * @param {number} dim
- * @param {Function} callback
- * @returns {Array} ret
- * @private
- */
- function _reduce(mat, dim, callback) {
- var i, ret, val, tran;
- if (dim <= 0) {
- if (!Array.isArray(mat[0])) {
- val = mat[0];
- for (i = 1; i < mat.length; i++) {
- val = callback(val, mat[i]);
- }
- return val;
- } else {
- tran = _switch(mat);
- ret = [];
- for (i = 0; i < tran.length; i++) {
- ret[i] = _reduce(tran[i], dim - 1, callback);
- }
- return ret;
- }
- } else {
- ret = [];
- for (i = 0; i < mat.length; i++) {
- ret[i] = _reduce(mat[i], dim - 1, callback);
- }
- return ret;
- }
- }
- // TODO: document function scatter
- export function scatter(a, j, w, x, u, mark, cindex, f, inverse, update, value) {
- // a arrays
- var avalues = a._values;
- var aindex = a._index;
- var aptr = a._ptr;
- // vars
- var k, k0, k1, i;
- // check we need to process values (pattern matrix)
- if (x) {
- // values in j
- for (k0 = aptr[j], k1 = aptr[j + 1], k = k0; k < k1; k++) {
- // row
- i = aindex[k];
- // check value exists in current j
- if (w[i] !== mark) {
- // i is new entry in j
- w[i] = mark;
- // add i to pattern of C
- cindex.push(i);
- // x(i) = A, check we need to call function this time
- if (update) {
- // copy value to workspace calling callback function
- x[i] = inverse ? f(avalues[k], value) : f(value, avalues[k]);
- // function was called on current row
- u[i] = mark;
- } else {
- // copy value to workspace
- x[i] = avalues[k];
- }
- } else {
- // i exists in C already
- x[i] = inverse ? f(avalues[k], x[i]) : f(x[i], avalues[k]);
- // function was called on current row
- u[i] = mark;
- }
- }
- } else {
- // values in j
- for (k0 = aptr[j], k1 = aptr[j + 1], k = k0; k < k1; k++) {
- // row
- i = aindex[k];
- // check value exists in current j
- if (w[i] !== mark) {
- // i is new entry in j
- w[i] = mark;
- // add i to pattern of C
- cindex.push(i);
- } else {
- // indicate function was called on current row
- u[i] = mark;
- }
- }
- }
- }
|