median.js 3.6 KB

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