median.js 3.4 KB

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