simple-squiggle

A restricted subset of Squiggle
Log | Files | Refs | README

collection.js (5221B)


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