UNPKG

jora

Version:

JavaScript object query engine

207 lines (161 loc) 5.06 kB
'use strict'; const compare = require('./compare.cjs'); const percentile$1 = require('./percentile.cjs'); const processNumericArray = require('./process-numeric-array.cjs'); const misc = require('./misc.cjs'); const self = value => value; function sumAndCount(current, getter) { let sum = undefined; let correction = 0; let count = 0; processNumericArray.processNumericArray(current, getter, num => { count++; if (sum === undefined) { sum = num; } else { // Kahan–Babuška summation with respect for Infinity // https://en.wikipedia.org/wiki/Kahan_summation_algorithm const transition = sum; const absTransition = Math.abs(transition); const absNum = Math.abs(num); sum += num; if (absTransition !== Infinity && absNum !== Infinity) { if (absTransition >= absNum) { correction += (transition - sum) + num; } else { correction += (num - sum) + transition; } } } }); if (sum !== undefined) { sum += correction; } return { sum, count }; } function numbers(current, getter) { // if (current && hasOwn(current, STAT_MARKER)) { // return current.input; // } const result = []; processNumericArray.processNumericArray(current, getter, result.push.bind(result)); return result; } function count(current, getter) { let count = 0; if (misc.isArrayLike(current)) { if (typeof getter !== 'function') { getter = self; } for (const value of current) { if (getter(value) !== undefined) { count++; } } } return count; } function sum(current, getter) { return sumAndCount(current, getter).sum; } function numbersSum(numbers) { if (numbers.length === 0) { return; } let sum = numbers[0]; let correction = 0; for (let i = 1; i < numbers.length; i++) { const num = numbers[i]; // Kahan–Babuška summation with respect for Infinity // https://en.wikipedia.org/wiki/Kahan_summation_algorithm const transition = sum; const absTransition = Math.abs(transition); const absNum = Math.abs(num); sum += num; if (absTransition !== Infinity && absNum !== Infinity) { if (absTransition >= absNum) { correction += (transition - sum) + num; } else { correction += (num - sum) + transition; } } } return sum + correction; } function mean(current, getter) { const { sum, count } = sumAndCount(current, getter); if (count > 0) { return sum / count; } } function variance(current, getter) { let count = 0; let mean = 0; let M2 = 0; // Welford's online algorithm // https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#Welford%27s_online_algorithm processNumericArray.processNumericArray(current, getter, num => { count += 1; let delta = num - mean; mean += delta / count; M2 += delta * (num - mean); }); if (count > 0) { return M2 / count; } } function stdev(current, getter) { const v = variance(current, getter); if (v !== undefined) { return Math.sqrt(v); } } function min(current, cmp = compare.cmpNatural) { let min; if (current && isFinite(current.length) && typeof cmp === 'function') { cmp = compare.getterToCmp(cmp, compare.cmpNatural); for (let i = 0; i < current.length; i++) { const value = current[i]; if ((min === undefined || cmp(value, min) < 0) && cmp(value, undefined) !== 0) { min = value; } } } return min; } function max(current, cmp = compare.cmpNatural) { let max; if (current && isFinite(current.length) && typeof cmp === 'function') { cmp = compare.getterToCmp(cmp, compare.cmpNatural); for (let i = 0; i < current.length; i++) { const value = current[i]; if ((max === undefined || cmp(value, max) >= 0) && cmp(value, undefined) !== 0) { max = value; } } } return max; } function percentile(current, p, getter) { // if (current && hasOwn(current, STAT_MARKER)) { // return numbersPercentile(current.input, p, getter); // } if (misc.isArrayLike(current)) { return percentile$1.percentile(current, p, getter); } } function median(current, getter) { return percentile(current, 50, getter); } exports.count = count; exports.max = max; exports.mean = mean; exports.median = median; exports.min = min; exports.numbers = numbers; exports.numbersSum = numbersSum; exports.percentile = percentile; exports.stdev = stdev; exports.sum = sum; exports.sumAndCount = sumAndCount; exports.variance = variance;