als-statistics
Version:
A powerful and lightweight JavaScript library for descriptive statistics, regression, clustering, outlier detection, and noise analysis using a flexible table/column architecture.
91 lines (79 loc) • 2.62 kB
JavaScript
const EPS = 3e-14;
const FPMIN = 1e-30;
const P = [676.5203681218851, -1259.1392167224028, 771.32342877765313, -176.61502916214059, 12.507343278686905, -0.13857109526572012, 9.9843695780195716e-6, 1.5056327351493116e-7];
const G = 7;
function betacfNR(x, a, b) {
const MAXIT = 200;
let qab = a + b;
let qap = a + 1;
let qam = a - 1; // используется только для инициализации, но оставим для ясности
let c = 1.0;
let d = 1.0 - (qab * x) / qap;
if (Math.abs(d) < FPMIN) d = FPMIN;
d = 1.0 / d;
let h = d;
for (let m = 1; m <= MAXIT; m++) {
const m2 = 2 * m;
// Even step
let aa = m * (b - m) * x / ((a + m2 - 1) * (a + m2));
d = 1.0 + aa * d;
if (Math.abs(d) < FPMIN) d = FPMIN;
c = 1.0 + aa / c;
if (Math.abs(c) < FPMIN) c = FPMIN;
d = 1.0 / d;
h *= (d * c);
// Odd step
aa = - (a + m) * (qab + m) * x / ((a + m2) * (a + m2 + 1));
d = 1.0 + aa * d;
if (Math.abs(d) < FPMIN) d = FPMIN;
c = 1.0 + aa / c;
if (Math.abs(c) < FPMIN) c = FPMIN;
d = 1.0 / d;
let delta = d * c;
h *= delta;
if (Math.abs(delta - 1.0) < EPS) {
break;
}
}
return h;
}
function gammaLn(z) {
if (z < 0.5) return Math.log(Math.PI) - Math.log(Math.sin(Math.PI * z)) - gammaLn(1 - z);
else {
z -= 1;
let x = 0.99999999999980993;
for (let i = 0; i < P.length; i++) {
x += P[i] / (z + i + 1);
}
const t = z + G + 0.5;
return 0.5 * Math.log(2 * Math.PI) + (z + 0.5) * Math.log(t) - t + Math.log(x);
}
}
function betaLn(a, b) { return gammaLn(a) + gammaLn(b) - gammaLn(a + b) }
function regularizedIncompleteBeta(x, a, b) {
if (x <= 0) return 0;
if (x >= 1) return 1;
const bt = Math.exp(a * Math.log(x) + b * Math.log(1 - x) - betaLn(a, b));
let sym = false;
let xx = x, aa = a, bb = b;
if (x > (a + 1) / (a + b + 2)) {
sym = true;
xx = 1 - x;
aa = b;
bb = a;
}
const cf = betacfNR(xx, aa, bb);
let val = bt / aa * cf;
if (sym) val = 1 - val;
return val;
}
function tCDF(t, df) {
if (df <= 0) throw new Error("Degrees of freedom must be positive");
if (t === 0) return 0.5;
const x = df / (df + t * t);
const a = df / 2;
const b = 0.5;
const ibeta = regularizedIncompleteBeta(x, a, b);
return (t >= 0) ? 1 - 0.5 * ibeta : 0.5 * ibeta;
}
module.exports = { gammaLn, betaLn, regularizedIncompleteBeta, tCDF };