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 });