simple-squiggle

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

median.js (3421B)


      1 import { containsCollections } from '../../utils/collection.js';
      2 import { flatten } from '../../utils/array.js';
      3 import { factory } from '../../utils/factory.js';
      4 import { improveErrorMessage } from './utils/improveErrorMessage.js';
      5 var name = 'median';
      6 var dependencies = ['typed', 'add', 'divide', 'compare', 'partitionSelect'];
      7 export var createMedian = /* #__PURE__ */factory(name, dependencies, _ref => {
      8   var {
      9     typed,
     10     add,
     11     divide,
     12     compare,
     13     partitionSelect
     14   } = _ref;
     15 
     16   /**
     17    * Recursively calculate the median of an n-dimensional array
     18    * @param {Array} array
     19    * @return {Number} median
     20    * @private
     21    */
     22   function _median(array) {
     23     try {
     24       array = flatten(array.valueOf());
     25       var num = array.length;
     26 
     27       if (num === 0) {
     28         throw new Error('Cannot calculate median of an empty array');
     29       }
     30 
     31       if (num % 2 === 0) {
     32         // even: return the average of the two middle values
     33         var mid = num / 2 - 1;
     34         var right = partitionSelect(array, mid + 1); // array now partitioned at mid + 1, take max of left part
     35 
     36         var left = array[mid];
     37 
     38         for (var i = 0; i < mid; ++i) {
     39           if (compare(array[i], left) > 0) {
     40             left = array[i];
     41           }
     42         }
     43 
     44         return middle2(left, right);
     45       } else {
     46         // odd: return the middle value
     47         var m = partitionSelect(array, (num - 1) / 2);
     48         return middle(m);
     49       }
     50     } catch (err) {
     51       throw improveErrorMessage(err, 'median');
     52     }
     53   } // helper function to type check the middle value of the array
     54 
     55 
     56   var middle = typed({
     57     'number | BigNumber | Complex | Unit': function numberBigNumberComplexUnit(value) {
     58       return value;
     59     }
     60   }); // helper function to type check the two middle value of the array
     61 
     62   var middle2 = typed({
     63     'number | BigNumber | Complex | Unit, number | BigNumber | Complex | Unit': function numberBigNumberComplexUnitNumberBigNumberComplexUnit(left, right) {
     64       return divide(add(left, right), 2);
     65     }
     66   });
     67   /**
     68    * Compute the median of a matrix or a list with values. The values are
     69    * sorted and the middle value is returned. In case of an even number of
     70    * values, the average of the two middle values is returned.
     71    * Supported types of values are: Number, BigNumber, Unit
     72    *
     73    * In case of a (multi dimensional) array or matrix, the median of all
     74    * elements will be calculated.
     75    *
     76    * Syntax:
     77    *
     78    *     math.median(a, b, c, ...)
     79    *     math.median(A)
     80    *
     81    * Examples:
     82    *
     83    *     math.median(5, 2, 7)        // returns 5
     84    *     math.median([3, -1, 5, 7])  // returns 4
     85    *
     86    * See also:
     87    *
     88    *     mean, min, max, sum, prod, std, variance, quantileSeq
     89    *
     90    * @param {... *} args  A single matrix or or multiple scalar values
     91    * @return {*} The median
     92    */
     93 
     94   return typed(name, {
     95     // median([a, b, c, d, ...])
     96     'Array | Matrix': _median,
     97     // median([a, b, c, d, ...], dim)
     98     'Array | Matrix, number | BigNumber': function ArrayMatrixNumberBigNumber(array, dim) {
     99       // TODO: implement median(A, dim)
    100       throw new Error('median(A, dim) is not yet supported'); // return reduce(arguments[0], arguments[1], ...)
    101     },
    102     // median(a, b, c, d, ...)
    103     '...': function _(args) {
    104       if (containsCollections(args)) {
    105         throw new TypeError('Scalar values expected in function median');
    106       }
    107 
    108       return _median(args);
    109     }
    110   });
    111 });