@statili/math
v1.0.0-rc.1
Published
Descriptive statistics, the Student t distribution, Gaussian elimination and numeric helpers. Zero dependencies.
Downloads
140
Maintainers
Readme
@statili/math
The numerical primitives the rest of statili is built on: descriptive statistics, the Student's t distribution, Gaussian elimination and a handful of numeric helpers. No dependencies.
Every function is pure, takes plain arrays, and returns NaN rather than throwing when a result is genuinely undefined — so a degenerate input is something you can test for, not something that unwinds your stack.
Install
npm install @statili/mathUsage
import { mean, standardDeviation, pearsonCorrelation } from '@statili/math'
const data = [2, 4, 4, 4, 5, 5, 7, 9]
mean(data) // 5
standardDeviation(data) // 2.138… (sample, n − 1)
standardDeviation(data, 0) // 2 (population, n)
pearsonCorrelation([1, 2, 3], [4, 5, 6]) // 1Descriptive statistics
| Function | Returns | Empty input |
|---|---|---|
| sum(numbers) | Total | 0 |
| mean(numbers) | Arithmetic mean | NaN |
| median(numbers) | Middle value; mean of the two middle for even counts | NaN |
| variance(numbers, ddof?) | Sample variance; ddof: 0 for population | NaN |
| standardDeviation(numbers, ddof?) | Sample std dev; ddof: 0 for population | NaN |
| min(numbers) / max(numbers) | Extremes | NaN |
| range(numbers) | max − min | NaN |
| quantile(p, numbers) | Quantile at p, linearly interpolated | NaN |
| mad(numbers) | Median absolute deviation | NaN |
| covariance(xs, ys) | Sample covariance | NaN |
| pearsonCorrelation(xs, ys) | Pearson r in [−1, 1] | NaN |
Input need not be sorted. sum returns 0 for an empty array because that is the additive identity; everything else returns NaN, because there is no meaningful average of nothing.
quantile matches R's Type 7 and NumPy's default, and takes p first so it partially applies:
import { quantile } from '@statili/math'
const q1 = (data: number[]) => quantile(0.25, data)
const q3 = (data: number[]) => quantile(0.75, data)
const iqr = (data: number[]) => q3(data) - q1(data)
q1([1, 2, 3, 4]) // 1.75
q3([1, 2, 3, 4]) // 3.25p outside [0, 1] throws a RangeError — that is a caller bug, not a degenerate dataset.
mad is the robust alternative to standardDeviation. 1.4826 × mad estimates the standard deviation of normally-distributed data while ignoring outliers, so median ± 3 × 1.4826 × mad is a distribution-agnostic outlier threshold.
Distributions
The machinery behind significance testing. @statili/stats uses these to attach p-values and confidence intervals to a regression slope.
import { studentTTwoTailedP, studentTQuantile } from '@statili/math'
// p-value for a t-statistic
studentTTwoTailedP(10, 2.228) // ≈ 0.05 — the classic 5% critical value
// The multiplier behind a 95% interval: estimate ± t · standardError
studentTQuantile(10, 0.975) // ≈ 2.228| Function | Returns |
|---|---|
| studentTCdf(df, t) | P(T ≤ t) |
| studentTTwoTailedP(df, t) | P(\|T\| > \|t\|) — the reported p-value |
| studentTQuantile(df, p) | Inverse CDF, by bisection |
| regularizedIncompleteBeta(a, b, x) | I_x(a, b), the Beta CDF |
| logGamma(x) | ln Γ(x) via Lanczos |
df comes first throughout, matching round(precision, value) and quantile(p, numbers): the slowly-varying parameter leads, so the function curries usefully. All five return NaN for out-of-domain parameters.
logGamma is the log form because Γ(x) overflows a double above about 171, and every consumer here needs ratios of gamma functions — which become differences of logs and stay in range.
Linear algebra
import { gaussianElimination } from '@statili/math'
// Solve 2x + y = 5, x + 3y = 10 — pass the augmented matrix [A | b]
gaussianElimination([[2, 1, 5], [1, 3, 10]], 2) // [1, 3]
// Singular system, no unique solution
gaussianElimination([[1, 2, 3], [2, 4, 6]], 2) // [NaN, NaN]Partial pivoting, no mutation of the input. Polynomial and multilinear regression both build a normal-equations matrix (XᵀX | Xᵀy) and call this to recover the coefficient vector.
Numeric helpers
import { round, isFiniteNumber, clamp, lerp } from '@statili/math'
round(2, 1.2345) // 1.23 — precision first, so `round(2)` curries
isFiniteNumber(NaN) // false — also rejects ±Infinity, null, undefined
clamp(0, 1, 1.7) // 1
lerp(0, 10, 0.5) // 5 — t outside [0, 1] extrapolatesround returns value unchanged when precision is not a finite number, rather than producing NaN.
Activation
import { sigmoid } from '@statili/math'
sigmoid(0) // 0.5
sigmoid(2) // ≈ 0.8808σ(z) = 1 / (1 + e⁻ᶻ). Logistic regression applies it to the linear predictor to get P(y = 1 | x).
See also
@statili/stats— regression and smoothing models built on these primitives@statili/forge— turns those results into readable, auditable statements
License
MIT
