UNPKG

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
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 };