"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.createQuantileSeq = void 0; var _is = require("../../utils/is.js"); var _array = require("../../utils/array.js"); var _factory = require("../../utils/factory.js"); var _apply = require("../matrix/apply.js"); const name = 'quantileSeq'; const dependencies = ['typed', '?bignumber', 'add', 'subtract', 'divide', 'multiply', 'partitionSelect', 'compare', 'isInteger', 'smaller', 'smallerEq', 'larger']; const createQuantileSeq = exports.createQuantileSeq = /* #__PURE__ */(0, _factory.factory)(name, dependencies, _ref => { let { typed, bignumber, add, subtract, divide, multiply, partitionSelect, compare, isInteger, smaller, smallerEq, larger } = _ref; const apply = (0, _apply.createApply)({ typed, isInteger }); /** * Compute the prob order quantile of a matrix or a list with values. * The sequence is sorted and the middle value is returned. * Supported types of sequence values are: Number, BigNumber, Unit * Supported types of probability are: Number, BigNumber * * In case of a multidimensional array or matrix, the prob order quantile * of all elements will be calculated. * * Syntax: * * math.quantileSeq(A, prob[, sorted]) * math.quantileSeq(A, [prob1, prob2, ...][, sorted]) * math.quantileSeq(A, N[, sorted]) * * Examples: * * math.quantileSeq([3, -1, 5, 7], 0.5) // returns 4 * math.quantileSeq([3, -1, 5, 7], [1/3, 2/3]) // returns [3, 5] * math.quantileSeq([3, -1, 5, 7], 2) // returns [3, 5] * math.quantileSeq([-1, 3, 5, 7], 0.5, true) // returns 4 * * See also: * * median, mean, min, max, sum, prod, std, variance * * @param {Array, Matrix} data A single matrix or Array * @param {Number, BigNumber, Array} probOrN prob is the order of the quantile, while N is * the amount of evenly distributed steps of * probabilities; only one of these options can * be provided * @param {Boolean} sorted=false is data sorted in ascending order * @return {Number, BigNumber, Unit, Array} Quantile(s) */ return typed(name, { 'Array | Matrix, number | BigNumber': (data, p) => _quantileSeqProbNumber(data, p, false), 'Array | Matrix, number | BigNumber, number': (data, prob, dim) => _quantileSeqDim(data, prob, false, dim, _quantileSeqProbNumber), 'Array | Matrix, number | BigNumber, boolean': _quantileSeqProbNumber, 'Array | Matrix, number | BigNumber, boolean, number': (data, prob, sorted, dim) => _quantileSeqDim(data, prob, sorted, dim, _quantileSeqProbNumber), 'Array | Matrix, Array | Matrix': (data, p) => _quantileSeqProbCollection(data, p, false), 'Array | Matrix, Array | Matrix, number': (data, prob, dim) => _quantileSeqDim(data, prob, false, dim, _quantileSeqProbCollection), 'Array | Matrix, Array | Matrix, boolean': _quantileSeqProbCollection, 'Array | Matrix, Array | Matrix, boolean, number': (data, prob, sorted, dim) => _quantileSeqDim(data, prob, sorted, dim, _quantileSeqProbCollection) }); function _quantileSeqDim(data, prob, sorted, dim, fn) { return apply(data, dim, x => fn(x, prob, sorted)); } function _quantileSeqProbNumber(data, probOrN, sorted) { let probArr; const dataArr = data.valueOf(); if (smaller(probOrN, 0)) { throw new Error('N/prob must be non-negative'); } if (smallerEq(probOrN, 1)) { // quantileSeq([a, b, c, d, ...], prob[,sorted]) return (0, _is.isNumber)(probOrN) ? _quantileSeq(dataArr, probOrN, sorted) : bignumber(_quantileSeq(dataArr, probOrN, sorted)); } if (larger(probOrN, 1)) { // quantileSeq([a, b, c, d, ...], N[,sorted]) if (!isInteger(probOrN)) { throw new Error('N must be a positive integer'); } // largest possible Array length is 2^32-1 // 2^32 < 10^15, thus safe conversion guaranteed if (larger(probOrN, 4294967295)) { throw new Error('N must be less than or equal to 2^32-1, as that is the maximum length of an Array'); } const nPlusOne = add(probOrN, 1); probArr = []; for (let i = 0; smaller(i, probOrN); i++) { const prob = divide(i + 1, nPlusOne); probArr.push(_quantileSeq(dataArr, prob, sorted)); } return (0, _is.isNumber)(probOrN) ? probArr : bignumber(probArr); } } /** * Calculate the prob order quantile of an n-dimensional array. * * @param {Array, Matrix} array * @param {Array, Matrix} prob * @param {Boolean} sorted * @return {Number, BigNumber, Unit} prob order quantile * @private */ function _quantileSeqProbCollection(data, probOrN, sorted) { const dataArr = data.valueOf(); // quantileSeq([a, b, c, d, ...], [prob1, prob2, ...][,sorted]) const probOrNArr = probOrN.valueOf(); const probArr = []; for (let i = 0; i < probOrNArr.length; ++i) { probArr.push(_quantileSeq(dataArr, probOrNArr[i], sorted)); } return probArr; } /** * Calculate the prob order quantile of an n-dimensional array. * * @param {Array} array * @param {Number, BigNumber} prob * @param {Boolean} sorted * @return {Number, BigNumber, Unit} prob order quantile * @private */ function _quantileSeq(array, prob, sorted) { const flat = (0, _array.flatten)(array); const len = flat.length; if (len === 0) { throw new Error('Cannot calculate quantile of an empty sequence'); } const index = (0, _is.isNumber)(prob) ? prob * (len - 1) : prob.times(len - 1); const integerPart = (0, _is.isNumber)(prob) ? Math.floor(index) : index.floor().toNumber(); const fracPart = (0, _is.isNumber)(prob) ? index % 1 : index.minus(integerPart); if (isInteger(index)) { return sorted ? flat[index] : partitionSelect(flat, (0, _is.isNumber)(prob) ? index : index.valueOf()); } let left; let right; if (sorted) { left = flat[integerPart]; right = flat[integerPart + 1]; } else { right = partitionSelect(flat, integerPart + 1); // max of partition is kth largest left = flat[integerPart]; for (let i = 0; i < integerPart; ++i) { if (compare(flat[i], left) > 0) { left = flat[i]; } } } // Q(prob) = (1-f)*A[floor(index)] + f*A[floor(index)+1] return add(multiply(left, subtract(1, fracPart)), multiply(right, fracPart)); } });