UNPKG

als-statistics

Version:

Modular JS statistics toolkit for Node.js and the browser: descriptive stats, correlations (Pearson/Spearman/Kendall), t-tests & ANOVA (Student/Welch), reliability (Cronbach’s alpha), regression (linear/logistic), clustering (DBSCAN/HDBSCAN), and table/co

49 lines (42 loc) 2.2 kB
import { betacfNR } from './betacfNR.js'; import { gammaLn } from './gammaLn.js'; import { constants } from './constants.js'; export default class CDF { static constants = constants static regularizedIncompleteBeta(x, a, b) { const { constants } = CDF if (x <= 0) return 0; if (x >= 1) return 1; const betaLn = gammaLn(a, constants) + gammaLn(b, constants) - gammaLn(a + b, constants) const bt = Math.exp(a * Math.log(x) + b * Math.log(1 - x) - betaLn); let sym = false, xx = x, aa = a, bb = b; if (x > (a + 1) / (a + b + 2)) { sym = true; xx = 1 - x; aa = b; bb = a; } let val = bt / aa * betacfNR(xx, aa, bb, constants); if (sym) val = 1 - val; return val; } static t(t, df) { // tCDF if (df <= 0) throw new Error("Degrees of freedom must be positive"); if (t === 0) return 0.5; const x = df / (df + t * t), a = df / 2, b = 0.5; const ibeta = CDF.regularizedIncompleteBeta(x, a, b); return (t >= 0) ? 1 - 0.5 * ibeta : 0.5 * ibeta; } static f(F, df1, df2) { // fCDF if (F < 0 || df1 <= 0 || df2 <= 0) throw new Error("Invalid input for F-distribution"); const x = (df1 * F) / (df1 * F + df2), a = df1 / 2, b = df2 / 2; return CDF.regularizedIncompleteBeta(x, a, b); } static phi(x) { // standard normal CDF Φ(x) if (!Number.isFinite(x)) return x === Infinity ? 1 : x === -Infinity ? 0 : NaN; if (x > 8) return 1; // далеко в правом хвосте if (x < -8) return 0; // далеко в левом хвосте // Φ(x) = 0.5 * (1 + erf(x / sqrt(2))) аппроксимация erf по Abramowitz & Stegun 7.1.26 (ошибка ~1e-7) const y = Math.abs(x) / Math.SQRT2; const t = 1 / (1 + 0.3275911 * y); const a1 = 0.254829592, a2 = -0.284496736, a3 = 1.421413741, a4 = -1.453152027, a5 = 1.061405429; const poly = (((((a5 * t) + a4) * t) + a3) * t + a2) * t + a1; const erf_abs = 1 - poly * t * Math.exp(-y * y); // erf(|x|/√2), положительный const erf = x < 0 ? -erf_abs : erf_abs; return 0.5 * (1 + erf); } }