jora
Version:
JavaScript object query engine
207 lines (161 loc) • 5.06 kB
JavaScript
;
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;