Skip to content

stdlib.stats

Descriptive statistics, probability distributions, regression and hypothesis tests over Vec-backed samples.

Generated from v0.65.7. 9 source files, 146 documented symbols.

dist.xi

fn uniform_pdf(x: Float64, a: Float64, b: Float64) -> Float64

Uniform density on [a, b]. Complexity: O(1).

  • Postcondition: (b <= a) => (result != result)
  • Postcondition: (b > a) => (result >= 0)
fn uniform_cdf(x: Float64, a: Float64, b: Float64) -> Float64

Uniform cumulative distribution on [a, b]. Complexity: O(1).

  • Postcondition: (b <= a) => (result != result)
  • Postcondition: (b > a) => ((result >= 0 && result <= 1) || (result != result))
fn normal_pdf(x: Float64, mu: Float64, sigma: Float64) -> Float64

Normal density with mean mu and stddev sigma. NaN for sigma <= 0. Complexity: O(1).

  • Postcondition: (sigma <= 0) => (result != result)
  • Postcondition: (sigma > 0) => ((result >= 0) || (result != result))
fn normal_cdf(x: Float64, mu: Float64, sigma: Float64) -> Float64

Normal cumulative distribution. Complexity: O(1).

  • Postcondition: (sigma <= 0) => (result != result)
  • Postcondition: (sigma > 0) => ((result >= 0 && result <= 1) || (result != result))
fn normal_ppf(p: Float64, mu: Float64, sigma: Float64) -> Float64

Normal percent point (inverse CDF) for probability p in (0, 1). Complexity: O(1).

  • Postcondition: (p <= 0 || p >= 1) => (result != result)
fn exponential_pdf(x: Float64, lambda: Float64) -> Float64

Exponential density with rate lambda. Complexity: O(1).

  • Postcondition: (lambda <= 0 || x < 0) => (result != result)
  • Postcondition: (lambda > 0 && x >= 0) => ((result >= 0) || (result != result))
fn exponential_cdf(x: Float64, lambda: Float64) -> Float64

Exponential cumulative distribution. Complexity: O(1).

  • Postcondition: (lambda <= 0 || x < 0) => (result != result)
  • Postcondition: (lambda > 0 && x >= 0) => ((result >= 0 && result <= 1) || (result != result))
fn poisson_pmf(k: Float64, lambda: Float64) -> Float64

Poisson probability mass at k with mean lambda (k is passed as a Float64 and used via the gamma function, so non-integer k is defined as well). Complexity: O(1).

  • Postcondition: (lambda < 0 || k < 0) => (result != result)
  • Postcondition: (lambda == 0 && k == 0) => (result == 1)
  • Postcondition: (lambda == 0 && k != 0) => ((result == 0) || (result != result))
  • Postcondition: (lambda > 0 && k >= 0) => ((result >= 0) || (result != result))
fn binomial_pmf(k: Float64, n: Float64, p: Float64) -> Float64

Binomial probability of k successes in n trials (k and n passed as Float64). NaN for invalid parameters. Complexity: O(1).

  • Postcondition: (p < 0 || p > 1 || k < 0 || n < 0 || k > n) => (result != result)
  • Postcondition: (p >= 0 && p <= 1 && k >= 0 && n >= 0 && k <= n) => ((result >= 0) || (result != result))
fn geometric_pmf(k: Float64, p: Float64) -> Float64

Geometric probability of first success at trial k. Complexity: O(1).

  • Postcondition: (p <= 0 || p > 1 || k < 1) => (result != result)
  • Postcondition: (p > 0 && p <= 1 && k >= 1) => ((result >= 0) || (result != result))
fn chi_squared_pdf(x: Float64, k: Float64) -> Float64

Chi-squared density with k degrees of freedom. Complexity: O(1).

  • Postcondition: (x < 0 || k <= 0) => (result != result)
  • Postcondition: (x == 0 && k > 0 && k < 2) => (result > 0)
  • Postcondition: (x == 0 && k == 2) => (result == 0.5)
  • Postcondition: (x == 0 && k > 2) => (result == 0)
  • Postcondition: (x > 0 && k > 0) => ((result >= 0) || (result != result))
fn student_t_pdf(x: Float64, v: Float64) -> Float64

Student's t density with v degrees of freedom. Complexity: O(1).

  • Postcondition: (v <= 0) => (result != result)
  • Postcondition: (v > 0) => ((result >= 0) || (result != result))
fn beta_pdf(x: Float64, a: Float64, b: Float64) -> Float64

Beta density with shape parameters a and b. Complexity: O(1).

  • Postcondition: (a <= 0 || b <= 0) => (result != result)
  • Postcondition: (a > 0 && b > 0 && (x <= 0 || x >= 1)) => (result == 0)
  • Postcondition: (a > 0 && b > 0 && x > 0 && x < 1) => ((result >= 0) || (result != result))
fn sample_normal(mu: Float64, sigma: Float64) -> Float64

Draw a normal sample with mean mu and stddev sigma (Box-Muller over the seeded xiom RNG). Complexity: O(1).

  • Postcondition: (sigma <= 0) => (result != result)
fn sample_uniform(a: Float64, b: Float64) -> Float64

Draw a uniform sample from [a, b]. Complexity: O(1).

  • Postcondition: (b <= a) => (result != result)
  • Postcondition: (b > a) => ((result >= a) || (result != result))



histogram.xi

type Histogram

A fixed-bin histogram over [min, max) with bins bins.

Field Type
bins Int
min Float64
max Float64
counts Vec[Int]
fn histogram_new(bins: Int, min: Float64, max: Float64) -> Histogram

Histogram over [min, max] with bins bins. Complexity: O(bins).

  • Postcondition: result.bins == bins
  • Postcondition: result.min == min
  • Postcondition: result.max == max
  • Postcondition: (bins <= 0 || max <= min) => (result.counts.len() == 0)
  • Postcondition: (bins > 0 && max > min) => (result.counts.len() == bins)
fn histogram_add(h: Histogram, value: Float64)

Record a value into h (by-value parameter: the caller's copy is not updated under XIOM move semantics; the frozen signature has no return). Values outside [min, max) are dropped. Complexity: O(1).

  • Postcondition: h.counts.len() == h.counts.len()@pre
fn histogram_counts(h: Histogram) -> Vec[Int]

Per-bin counts. Complexity: O(1) (returns a copy).

  • Postcondition: result.len() == h.counts.len()
fn histogram_edges(h: Histogram) -> Vec[Float64]

Bin edge positions, length bins + 1. Complexity: O(bins).

  • Postcondition: (h.bins <= 0 || h.max <= h.min) => (result.len() == 0)
  • Postcondition: (h.bins > 0 && h.max > h.min) => (result.len() == h.bins + 1)
fn histogram_normalize(h: Histogram) -> Vec[Float64]

Counts normalized to a probability density (total count over bin width). Empty for an empty histogram. Complexity: O(bins).

  • Postcondition: (h.counts.len() == 0 || h.max <= h.min) => (result.len() == 0)
  • Postcondition: (result.len() == 0) || (result.len() == h.counts.len())
fn histogram_mean(h: Histogram) -> Float64

Mean estimated from the bin midpoints. NaN for an empty histogram. Complexity: O(bins).

  • Postcondition: h.counts.len() == 0 => (result != result)
fn histogram_variance(h: Histogram) -> Float64

Variance estimated from the bin midpoints. NaN for an empty histogram. Complexity: O(bins).

  • Postcondition: h.counts.len() == 0 => (result != result)
fn histogram_quantile(h: Histogram, q: Float64) -> Float64

q-th quantile (q in [0, 1]) from the cumulative counts; NaN for an empty histogram or invalid q. Complexity: O(bins).

  • Postcondition: (h.counts.len() == 0 || q < 0 || q > 1) => (result != result)
  • Postcondition: (h.counts.len() > 0 && h.max > h.min && q >= 0 && q <= 1) => ((result >= h.min && result <= h.max) || (result != result))
fn histogram_mode(h: Histogram) -> Int

Index of the most populated bin (first on ties). Returns -1 for an empty histogram. Complexity: O(bins).

  • Postcondition: h.counts.len() == 0 => (result == -1)
  • Postcondition: h.counts.len() > 0 => (result >= 0 && result < h.counts.len())
fn histogram_merge(a: Histogram, b: Histogram) -> Histogram

Combined histogram over the matching ranges: the counts of a and b are added (a's bin structure is used). Returns a copy of a when the ranges or bin counts differ (documented). Complexity: O(bins).

  • Postcondition: result.bins == a.bins
  • Postcondition: result.min == a.min
  • Postcondition: result.max == a.max
  • Postcondition: (a.bins != b.bins || a.min != b.min || a.max != b.max) => (result.counts.len() == a.counts.len())



int_stats.xi

fn int_mean(values: &Vec[Int]) -> Int

Rounded integer mean of a scaled sample: round(sum(values) / n), halves away from zero. The sum accumulates exactly in 128 bits (n * |value| can never leave the 128-bit range for Int-length vectors), so the result is the correctly rounded mean of the scaled values. Empty input returns 0 (documented, matching xiom.stats). Complexity: O(n).

  • Postcondition: (values.len() == 0) => (result == 0)
fn int_slope(x: &Vec[Int], y: &Vec[Int], scale: Int) -> Int

Least-squares slope of y on x over scaled Int pairs: the inputs represent real values x_i = X_i / S and y_i = Y_i / S for one common positive scale S (S cancels in the ratio), and the result is round(scale * slope), halves away from zero. Mean-centred normal equations (sum dx*dy) / (sum dx^2) with exact 128-bit accumulation; exact while the centred sums stay inside 128 bits (all realistic scaled samples). Fewer than 2 points, a length mismatch, a zero x-variance or scale <= 0 returns 0 (documented). Complexity: O(n).

  • Postcondition: (scale <= 0) => (result == 0)
  • Postcondition: (x.len() < 2) || (y.len() != x.len()) => (result == 0)
fn int_argmax(values: &Vec[Int]) -> Int

Index of the maximum with first-wins stability (FIFO tie-break): the earliest index holding the largest value wins. Empty input returns 0 (documented, matching the xiom.stats empty-input convention for Int stats; callers that need an absence signal pre-check len). Complexity: O(n).

  • Postcondition: (values.len() == 0) => (result == 0)
fn f64_argmax(values: &Vec[Float64]) -> Int

Float64 sibling of int_argmax with the documented NaN policy: NaN entries never win (they are skipped, whichever position they occupy) and ties keep the first index. Empty input or an all-NaN input returns 0 (documented; the stats module returns NaN itself for degenerate samples, but an index result has no NaN form, so the empty-sentinel 0 is reused). Complexity: O(n).

  • Postcondition: (values.len() == 0) => (result == 0)



moments.xi

fn mean(data: &Vec[Float64]) -> Float64

Arithmetic mean; 0 for an empty sample (documented). Complexity: O(n).

  • Postcondition: data.len() == 0 => (result == 0)
fn variance(data: &Vec[Float64]) -> Float64

Sample variance (Bessel's correction, n - 1); 0 for fewer than 2 samples. Complexity: O(n).

  • Postcondition: data.len() < 2 => (result == 0)
  • Postcondition: (result >= 0) || (result != result)
fn stddev(data: &Vec[Float64]) -> Float64

Sample standard deviation; 0 for fewer than 2 samples. Complexity: O(n).

  • Postcondition: data.len() < 2 => (result == 0)
  • Postcondition: (result >= 0) || (result != result)
fn skewness(data: &Vec[Float64]) -> Float64

Standardized third central moment; NaN for fewer than 3 samples. Complexity: O(n).

  • Postcondition: data.len() < 3 => (result != result)
fn kurtosis(data: &Vec[Float64]) -> Float64

Excess kurtosis (fourth central moment, zero for a normal distribution); NaN for fewer than 4 samples. Complexity: O(n).

  • Postcondition: data.len() < 4 => (result != result)
fn central_moment(data: &Vec[Float64], k: Int) -> Float64

k-th central moment about the mean; NaN for k < 2. Complexity: O(n).

  • Postcondition: (data.len() == 0 || k < 2) => (result != result)
  • Postcondition: (data.len() > 0 && k >= 2 && k % 2 == 0) => ((result >= 0) || (result != result))
fn raw_moment(data: &Vec[Float64], k: Int) -> Float64

k-th raw moment about zero; NaN for k < 1. Complexity: O(n).

  • Postcondition: (data.len() == 0 || k < 1) => (result != result)
  • Postcondition: (data.len() > 0 && k >= 1 && k % 2 == 0) => ((result >= 0) || (result != result))
fn covariance(x: &Vec[Float64], y: &Vec[Float64]) -> Float64

Sample covariance of x and y; NaN on length mismatch, 0 for fewer than 2 pairs. Complexity: O(n).

  • Postcondition: x.len() != y.len() => (result != result)
  • Postcondition: (x.len() == y.len() && x.len() < 2) => (result == 0)
fn weighted_mean(data: &Vec[Float64], weights: &Vec[Float64]) -> Float64

Mean weighted by weights; NaN on length mismatch or a zero weight sum. Complexity: O(n).

  • Postcondition: data.len() != weights.len() => (result != result)
  • Postcondition: data.len() == 0 => (result != result)
fn geometric_mean(data: &Vec[Float64]) -> Float64

Geometric mean via log-space; NaN for non-positive values. Complexity: O(n).

  • Postcondition: data.len() == 0 => (result != result)
  • Postcondition: (result > 0) || (result != result)
fn harmonic_mean(data: &Vec[Float64]) -> Float64

Harmonic mean; NaN for non-positive values. Complexity: O(n).

  • Postcondition: data.len() == 0 => (result != result)
  • Postcondition: (result > 0) || (result != result)
fn median(data: &Vec[Float64]) -> Float64

Middle value of the sorted sample; the average of the two middles when even. NaN for an empty sample. Complexity: O(n log n).

  • Postcondition: data.len() == 0 => (result != result)
fn quantile(data: &Vec[Float64], q: Float64) -> Float64

q-th quantile by linear interpolation between the sorted values (q in [0, 1]). NaN for invalid q. Complexity: O(n log n).

  • Postcondition: (data.len() == 0 || q < 0 || q > 1) => (result != result)



probability.xi

fn uniform_pdf(x: Float64, a: Float64, b: Float64) -> Float64

Uniform density on [a, b]. Complexity: O(1).

  • Postcondition: b > a && x < a => result == 0
  • Postcondition: b > a && x > b => result == 0
fn uniform_cdf(x: Float64, a: Float64, b: Float64) -> Float64

Uniform cumulative distribution on [a, b]. Complexity: O(1).

  • Postcondition: b > a && x <= a => result == 0
  • Postcondition: b > a && x >= b => result == 1
fn normal_pdf(x: Float64, mu: Float64, sigma: Float64) -> Float64

Normal density with mean mu and stddev sigma. Complexity: O(1).

  • Postcondition: (sigma <= 0) => math.is_nan(result)
fn normal_cdf(x: Float64, mu: Float64, sigma: Float64) -> Float64

Normal cumulative distribution. Complexity: O(1).

  • Postcondition: (sigma <= 0) => math.is_nan(result)
fn normal_quantile(p: Float64, mu: Float64, sigma: Float64) -> Float64

Normal quantile (inverse CDF) for probability p. Complexity: O(1).

  • Postcondition: (p <= 0 || p >= 1) => math.is_nan(result)
fn exponential_pdf(x: Float64, lambda: Float64) -> Float64

Exponential density with rate lambda. Complexity: O(1).

  • Postcondition: (lambda <= 0 || x < 0) => math.is_nan(result)
fn exponential_cdf(x: Float64, lambda: Float64) -> Float64

Exponential cumulative distribution. Complexity: O(1).

  • Postcondition: lambda > 0 && x == 0 => result == 0
fn gamma_pdf(x: Float64, k: Float64, theta: Float64) -> Float64

Gamma density with shape k and scale theta. Complexity: O(1).

  • Postcondition: (k <= 0 || theta <= 0 || x < 0) => math.is_nan(result)
fn gamma_cdf(x: Float64, k: Float64, theta: Float64) -> Float64

Gamma cumulative distribution: P(k, x/theta). Complexity: O(iterations).

  • Postcondition: k > 0 && theta > 0 && x <= 0 => result == 0
fn beta_pdf(x: Float64, a: Float64, b: Float64) -> Float64

Beta density with shape parameters a and b. Complexity: O(1).

  • Postcondition: (a <= 0 || b <= 0) => math.is_nan(result)
  • Postcondition: (a > 0 && b > 0 && (x <= 0 || x >= 1)) => (result == 0)
fn beta_cdf(x: Float64, a: Float64, b: Float64) -> Float64

Beta cumulative distribution: I_x(a, b). Complexity: O(iterations).

  • Postcondition: a > 0 && b > 0 && x <= 0 => result == 0
  • Postcondition: a > 0 && b > 0 && x >= 1 => result == 1
fn chi2_pdf(x: Float64, k: Float64) -> Float64

Chi-squared density with k degrees of freedom. Complexity: O(1).

  • Postcondition: (x < 0 || k <= 0) => math.is_nan(result)
  • Postcondition: (x == 0 && k > 2) => (result == 0)
fn chi2_cdf(x: Float64, k: Float64) -> Float64

Chi-squared cumulative distribution: P(k/2, x/2). Complexity: O(iterations).

  • Postcondition: k > 0 && x <= 0 => result == 0
fn t_pdf(x: Float64, v: Float64) -> Float64

Student's t density with v degrees of freedom. Complexity: O(1).

  • Postcondition: (v <= 0) => math.is_nan(result)
fn t_cdf(x: Float64, v: Float64) -> Float64

Student's t cumulative distribution via the regularized incomplete beta. Complexity: O(iterations).

  • Postcondition: (v <= 0) => math.is_nan(result)
fn f_pdf(x: Float64, d1: Float64, d2: Float64) -> Float64

F density with d1, d2 degrees of freedom. Complexity: O(1).

  • Postcondition: (x <= 0 || d1 <= 0 || d2 <= 0) => math.is_nan(result)
fn f_cdf(x: Float64, d1: Float64, d2: Float64) -> Float64

F cumulative distribution: I_{d1 x / (d1 x + d2)}(d1/2, d2/2). Complexity: O(iterations).

  • Postcondition: d1 > 0 && d2 > 0 && x <= 0 => result == 0
fn weibull_pdf(x: Float64, shape: Float64, scale: Float64) -> Float64

Weibull density with shape and scale. Complexity: O(1).

  • Postcondition: (shape <= 0 || scale <= 0 || x < 0) => math.is_nan(result)
  • Postcondition: (x == 0 && shape > 1) => (result == 0)
fn weibull_cdf(x: Float64, shape: Float64, scale: Float64) -> Float64

Weibull cumulative distribution. Complexity: O(1).

  • Postcondition: shape > 0 && scale > 0 && x <= 0 => result == 0
fn lognormal_pdf(x: Float64, mu: Float64, sigma: Float64) -> Float64

Log-normal density of exp(mu + sigma Z). Complexity: O(1).

  • Postcondition: (sigma <= 0 || x <= 0) => math.is_nan(result)
fn lognormal_cdf(x: Float64, mu: Float64, sigma: Float64) -> Float64

Log-normal cumulative distribution. Complexity: O(1).

  • Postcondition: (sigma <= 0 || x <= 0) => math.is_nan(result)
fn pareto_pdf(x: Float64, alpha: Float64, xm: Float64) -> Float64

Pareto density with shape alpha and scale xm. Complexity: O(1).

  • Postcondition: (alpha <= 0 || xm <= 0 || x < xm) => math.is_nan(result)
fn pareto_cdf(x: Float64, alpha: Float64, xm: Float64) -> Float64

Pareto cumulative distribution. Complexity: O(1).

  • Postcondition: (alpha <= 0 || xm <= 0) => math.is_nan(result)
  • Postcondition: (alpha > 0 && xm > 0 && x < xm) => (result == 0)
fn poisson_pmf(k: Int, lambda: Float64) -> Float64

Poisson probability of k events with mean lambda (integer k). Complexity: O(1).

  • Postcondition: lambda == 0 && k == 0 => result == 1
  • Postcondition: lambda == 0 && k > 0 => result == 0
fn poisson_cdf(k: Int, lambda: Float64) -> Float64

Poisson cumulative distribution. Complexity: O(k).

  • Postcondition: lambda == 0 && k >= 0 => result == 1
fn binomial_pmf(k: Int, n: Int, p: Float64) -> Float64

Binomial probability of k successes in n trials. Complexity: O(1).

  • Postcondition: (p < 0 || p > 1 || k < 0 || n < 0 || k > n) => math.is_nan(result)
fn binomial_cdf(k: Int, n: Int, p: Float64) -> Float64

Binomial cumulative distribution. Complexity: O(n).

  • Postcondition: n >= 0 && k >= n => result == 1
fn geometric_pmf(k: Int, p: Float64) -> Float64

Geometric probability of first success at trial k. Complexity: O(1).

  • Postcondition: p > 0 && p <= 1 && k >= 1 => result >= 0 && result <= 1
fn geometric_cdf(k: Int, p: Float64) -> Float64

Geometric cumulative distribution. Complexity: O(k).

  • Postcondition: p > 0 && p <= 1 && k >= 1 => result >= 0 && result <= 1
fn negative_binomial_pmf(k: Int, r: Int, p: Float64) -> Float64

Negative binomial probability of k failures before r successes. Complexity: O(1).

  • Postcondition: (p <= 0 || p > 1 || k < 0 || r <= 0) => math.is_nan(result)
fn negative_binomial_cdf(k: Int, r: Int, p: Float64) -> Float64

Negative binomial cumulative distribution. Complexity: O(k).

  • Postcondition: (k < 0 || r <= 0 || p <= 0 || p > 1) => math.is_nan(result)
fn hypergeometric_pmf(k: Int, n: Int, K: Int, N: Int) -> Float64

Hypergeometric probability of k successes drawing n from a population of N with K successes. Complexity: O(1).

  • Postcondition: (n < 0 || K < 0 || N <= 0 || k < 0 || k > n || k > K || n - k > N - K) => math.is_nan(result)
fn hypergeometric_cdf(k: Int, n: Int, K: Int, N: Int) -> Float64

Hypergeometric cumulative distribution. Complexity: O(n).

  • Postcondition: N > 0 && K >= 0 && n >= 0 && k >= K => result == 1



regress.xi

type RegressionResult

Least-squares linear fit result: slope, intercept, and R^2.

Field Type
slope Float64
intercept Float64
r2 Float64
fn linear_regression(x: &Vec[Float64], y: &Vec[Float64]) -> RegressionResult

Least-squares linear fit y = slope*x + intercept with R-squared. Returns a zeroed result for fewer than 2 points or a mismatch. Complexity: O(n).

  • Postcondition: (x.len() == 0 || y.len() != x.len()) => (result.slope == 0 && result.intercept == 0 && result.r2 == 0)
  • Postcondition: (x.len() == 1 && y.len() == 1) => (result.slope == 0 && result.r2 == 0)
fn slope(x: &Vec[Float64], y: &Vec[Float64]) -> Float64

Regression slope. Returns 0 for degenerate input. Complexity: O(n).

  • Postcondition: (x.len() < 2 || y.len() != x.len()) => (result == 0)
fn intercept(x: &Vec[Float64], y: &Vec[Float64]) -> Float64

Regression intercept. Returns 0 for degenerate input. Complexity: O(n).

  • Postcondition: (x.len() == 0 || y.len() != x.len()) => (result == 0)
fn r_squared(x: &Vec[Float64], y: &Vec[Float64]) -> Float64

Coefficient of determination R^2. Returns 0 for degenerate input. Complexity: O(n).

  • Postcondition: (x.len() < 2 || y.len() != x.len()) => (result == 0)
fn pearson_correlation(x: &Vec[Float64], y: &Vec[Float64]) -> Float64

Pearson correlation coefficient. Complexity: O(n).

  • Postcondition: (x.len() < 2 || y.len() != x.len()) => math.is_nan(result)
fn spearman_correlation(x: &Vec[Float64], y: &Vec[Float64]) -> Float64

Rank-based Spearman correlation. Complexity: O(n log n).

  • Postcondition: (y.len() != x.len() || x.len() < 2) => math.is_nan(result)
fn polynomial_regression(x: &Vec[Float64], y: &Vec[Float64], degree: Int) -> Vec[Float64]

Least-squares polynomial coefficients (lowest degree first) by solving the normal equations: exact for degree 1 and 2 (Cramer's rule); higher degrees return the empty vector (documented). Complexity: O(n).

  • Postcondition: (degree < 1 || degree > 2) => (result.len() == 0)
  • Postcondition: (degree == 1 && x.len() >= 2 && y.len() == x.len()) => (result.len() == 2)
  • Postcondition: (degree == 2 && x.len() >= 3 && y.len() == x.len()) => (result.len() == 0 || result.len() == 3)
fn exponential_fit(x: &Vec[Float64], y: &Vec[Float64]) -> (Float64, Float64)

Exponential fit y = a * exp(b*x): linear regression on (x, ln y). Returns (a, b); NaN for non-positive y. Complexity: O(n).

  • Postcondition: (x.len() < 2 || y.len() != x.len()) => (math.is_nan(result._0) && math.is_nan(result._1))
fn predict_line(slope: Float64, intercept: Float64, x: Float64) -> Float64

Predicted value slope * x + intercept. Complexity: O(1).

  • Postcondition: result == slope * x + intercept
fn residuals(x: &Vec[Float64], y: &Vec[Float64], slope: Float64, intercept: Float64) -> Vec[Float64]

Observed minus predicted values. Empty for a mismatch. Complexity: O(n).

  • Postcondition: (y.len() != x.len()) => (result.len() == 0)
  • Postcondition: (y.len() == x.len()) => (result.len() == x.len())



statistics.xi

fn mean(data: &Vec[Float64]) -> Float64

Arithmetic mean; 0 for an empty sample. Complexity: O(n).

  • Postcondition: (data.len() == 0) => (result == 0)
fn median(data: &Vec[Float64]) -> Float64

Middle value of the sorted sample; average of the two middles when even. NaN for an empty sample. Complexity: O(n log n).

  • Postcondition: (data.len() == 0) => math.is_nan(result)
fn mode(data: &Vec[Float64]) -> Option[Float64]

Most frequently occurring value. NaN for an empty sample; the first mode wins ties (documented). Complexity: O(n^2).

  • Postcondition: (data.len() == 0) => (result is None)
  • Postcondition: (data.len() > 0) => (result is Some(_))
fn variance(data: &Vec[Float64]) -> Float64

Sample variance (n - 1); 0 for fewer than 2 samples. Complexity: O(n).

  • Postcondition: (data.len() < 2) => (result == 0)
fn variance_pop(data: &Vec[Float64]) -> Float64

Population variance (n); 0 for an empty sample. Complexity: O(n).

  • Postcondition: (data.len() == 0) => (result == 0)
fn stddev(data: &Vec[Float64]) -> Float64

Sample standard deviation. Complexity: O(n).

  • Postcondition: (data.len() < 2) => (result == 0)
fn stddev_pop(data: &Vec[Float64]) -> Float64

Population standard deviation. Complexity: O(n).

  • Postcondition: (data.len() == 0) => (result == 0)
fn range(data: &Vec[Float64]) -> Float64

Range (max - min); 0 for an empty sample. Complexity: O(n).

  • Postcondition: (data.len() == 0) => (result == 0)
fn iqr(data: &Vec[Float64]) -> Float64

Interquartile range (Q3 - Q1). NaN for fewer than 2 samples. Complexity: O(n log n).

  • Postcondition: (data.len() == 0) => math.is_nan(result)
fn quartiles(data: &Vec[Float64]) -> Vec[Float64]

Quartiles [Q1, Q2, Q3] by linear interpolation. Empty for an empty sample. Complexity: O(n log n).

  • Postcondition: (data.len() == 0) => (result.len() == 0)
  • Postcondition: (data.len() > 0) => (result.len() == 3)
fn percentile(data: &Vec[Float64], p: Float64) -> Float64

p-th percentile by linear interpolation (p in [0, 100]). NaN for invalid p. Complexity: O(n log n).

  • Postcondition: (p < 0 || p > 100) => math.is_nan(result)
  • Postcondition: (data.len() == 0 && 0 <= p && p <= 100) => math.is_nan(result)
fn skewness(data: &Vec[Float64]) -> Float64

Standardized third central moment. Complexity: O(n).

  • Postcondition: (data.len() < 3) => math.is_nan(result)
fn kurtosis(data: &Vec[Float64]) -> Float64

Excess kurtosis (fourth central moment, zero for normal). Complexity: O(n).

  • Postcondition: (data.len() < 4) => math.is_nan(result)
fn covariance(x: &Vec[Float64], y: &Vec[Float64]) -> Float64

Sample covariance of x and y. Complexity: O(n).

  • Postcondition: (x.len() != y.len()) => math.is_nan(result)
  • Postcondition: (x.len() == y.len() && x.len() < 2) => (result == 0)
fn correlation(x: &Vec[Float64], y: &Vec[Float64]) -> Float64

Pearson correlation coefficient. Complexity: O(n).

  • Postcondition: (x.len() != y.len()) => math.is_nan(result)
  • Postcondition: (x.len() == y.len() && x.len() < 2) => math.is_nan(result)
fn spearman_correlation(x: &Vec[Float64], y: &Vec[Float64]) -> Float64

Spearman rank correlation: the Pearson correlation of the ranks. Complexity: O(n log n).

  • Postcondition: (x.len() != y.len()) => math.is_nan(result)
  • Postcondition: (x.len() == y.len() && x.len() < 2) => math.is_nan(result)
fn kendall_correlation(x: &Vec[Float64], y: &Vec[Float64]) -> Float64

Kendall tau-b rank correlation (concordant minus discordant pairs). Complexity: O(n^2).

  • Postcondition: (x.len() != y.len()) => math.is_nan(result)
  • Postcondition: (x.len() == y.len() && x.len() < 2) => math.is_nan(result)
fn rms(data: &Vec[Float64]) -> Float64

Root mean square of the sample; 0 for an empty sample. Complexity: O(n).

  • Postcondition: (data.len() == 0) => (result == 0)
fn geometric_mean(data: &Vec[Float64]) -> Float64

Geometric mean via log-space; NaN for non-positive values. Complexity: O(n).

  • Postcondition: (data.len() == 0) => math.is_nan(result)
fn harmonic_mean(data: &Vec[Float64]) -> Float64

Harmonic mean; NaN for non-positive values. Complexity: O(n).

  • Postcondition: (data.len() == 0) => math.is_nan(result)
fn weighted_mean(data: &Vec[Float64], weights: &Vec[Float64]) -> Float64

Mean weighted by weights. Complexity: O(n).

  • Postcondition: (data.len() != weights.len()) => math.is_nan(result)
fn trimmed_mean(data: &Vec[Float64], trim: Float64) -> Float64

Mean after removing the fraction trim from each sorted tail. NaN for invalid trim or an over-trimmed sample. Complexity: O(n log n).

  • Postcondition: (trim < 0 || trim >= 0.5) => math.is_nan(result)
  • Postcondition: (data.len() == 0) => math.is_nan(result)
fn winsorized_mean(data: &Vec[Float64], trim: Float64) -> Float64

Mean with the fraction trim of each tail winsorized to the tail values. NaN for invalid trim. Complexity: O(n log n).

  • Postcondition: (trim < 0 || trim >= 0.5) => math.is_nan(result)
  • Postcondition: (data.len() == 0) => math.is_nan(result)
fn mad(data: &Vec[Float64]) -> Float64

Median absolute deviation from the median. NaN for an empty sample. Complexity: O(n log n).

  • Postcondition: (data.len() == 0) => math.is_nan(result)
fn z_score(x: Float64, mean: Float64, stddev: Float64) -> Float64

Standardized score (x - mean) / stddev. Complexity: O(1).

  • Postcondition: (stddev == 0) => math.is_nan(result)



stats.xi

fn stats_min(data: &Vec[Int]) -> Int

Returns the minimum value in a vector of integers. Returns 0 for empty input.

  • Postcondition: data.len() == 0 => result == 0

fn stats_max(data: &Vec[Int]) -> Int

Returns the maximum value in a vector of integers. Returns 0 for empty input.

  • Postcondition: data.len() == 0 => result == 0

fn stats_range(data: &Vec[Int]) -> Int

Returns the range (max - min) of a vector of integers.

  • Postcondition: data.len() == 0 => result == 0

fn stats_mode(data: &Vec[Int]) -> Option[Int]

Returns the most frequently occurring value (mode) in a sorted vector. For ties, returns the first mode encountered.

  • Postcondition: (data.len() == 0) => (result is None)
  • Postcondition: (data.len() > 0) => (result is Some(_))

fn stats_variance(data: &Vec[Int]) -> Float64

Computes the population variance of a vector of integers. Sum of squared deviations from the mean divided by N.

  • Postcondition: data.len() == 0 => result == 0
  • Postcondition: result >= 0

fn stats_sample_variance(data: &Vec[Int]) -> Float64

Computes the sample variance (Bessel's correction: divide by N-1).

  • Postcondition: data.len() < 2 => result == 0
  • Postcondition: result >= 0

fn stats_stddev_f(data: &Vec[Int]) -> Float64

Computes the population standard deviation (Float64).

  • Postcondition: result >= 0

fn stats_sample_stddev(data: &Vec[Int]) -> Float64

Computes the sample standard deviation (Float64).

  • Postcondition: result >= 0

fn stats_q1(data: &Vec[Int]) -> Int

Returns the first quartile (Q1) of a sorted vector of integers. Uses the median-of-lower-half method.

  • Postcondition: data.len() == 0 => result == 0

fn stats_q3(data: &Vec[Int]) -> Int

Returns the third quartile (Q3) of a sorted vector of integers. Uses the median-of-upper-half method.

  • Postcondition: data.len() == 0 => result == 0

fn stats_iqr(data: &Vec[Int]) -> Int

Returns the interquartile range (Q3 - Q1).

  • Postcondition: data.len() == 0 => result == 0

fn stats_sum_f(data: &Vec[Float64]) -> Float64

Sum of a vector of Float64 values.

  • Postcondition: data.len() == 0 => result == 0

fn stats_mean_f(data: &Vec[Float64]) -> Float64

Mean of a vector of Float64 values.

  • Postcondition: data.len() == 0 => result == 0

fn stats_stddev_f_f(data: &Vec[Float64]) -> Float64

Population standard deviation of a vector of Float64 values.

  • Postcondition: data.len() == 0 => result == 0
  • Postcondition: result >= 0 || result != result

fn stats_covariance(a: &Vec[Int], b: &Vec[Int]) -> Float64

Computes the population covariance between two vectors of equal length.

  • Postcondition: a.len() == 0 => result == 0
  • Postcondition: b.len() != a.len() => result == 0

fn stats_correlation(a: &Vec[Int], b: &Vec[Int]) -> Float64

Computes the Pearson correlation coefficient between two vectors.

  • Postcondition: (a.len() < 2 || b.len() < 2) => (result == 0)

fn stats_histogram(data: &Vec[Int], bins: Int, lo: Int, hi: Int) -> Vec[Int]

Builds a histogram with the specified number of bins over [lo, hi]. Each bin counts values in [bin_start, bin_start + bin_width).

  • Postcondition: bins <= 0 => result.len() == 0
  • Postcondition: hi <= lo => result.len() == 0
  • Postcondition: bins > 0 && hi > lo => result.len() == bins

fn stats_geometric_mean(data: &Vec[Int]) -> Float64

Computes the geometric mean using logarithms to avoid overflow. Requires all values to be positive.

  • Postcondition: data.len() == 0 => result == 0
  • Postcondition: result >= 0

fn stats_harmonic_mean(data: &Vec[Int]) -> Float64

Computes the harmonic mean. Returns 0 if any value is <= 0.

  • Postcondition: data.len() == 0 => result == 0
  • Postcondition: result >= 0

fn stats_zscore(value: Int, mean: Float64, stddev: Float64) -> Float64

Computes the z-score: (value - mean) / stddev.

  • Postcondition: stddev == 0 => result == 0

fn stats_slope(x: &Vec[Int], y: &Vec[Int]) -> Float64

Computes the slope of the simple linear regression line y = mx + b.

  • Postcondition: x.len() < 2 => result == 0
  • Postcondition: y.len() != x.len() => result == 0

fn stats_intercept(x: &Vec[Int], y: &Vec[Int]) -> Float64

Computes the intercept of the simple linear regression line y = mx + b.

  • Postcondition: y.len() == 0 => result == 0

fn stats_r_squared(x: &Vec[Int], y: &Vec[Int]) -> Float64

Computes the R-squared (coefficient of determination) for linear regression.

  • Postcondition: x.len() < 2 => result == 0
  • Postcondition: y.len() != x.len() => result == 0


test.xi

fn t_test_one_sample(data: &Vec[Float64], mu: Float64) -> Float64

One-sample t statistic against population mean mu. NaN for fewer than 2 samples. Complexity: O(n).

  • Postcondition: data.len() < 2 => (result != result)
fn t_test_two_sample(a: &Vec[Float64], b: &Vec[Float64]) -> Float64

Independent two-sample t statistic (Welch, unequal variance). NaN for fewer than 2 samples in either group. Complexity: O(n).

  • Postcondition: (a.len() < 2 || b.len() < 2) => (result != result)
fn t_test_paired(a: &Vec[Float64], b: &Vec[Float64]) -> Float64

Paired t statistic on the differences a - b. NaN for a mismatch or fewer than 2 pairs. Complexity: O(n).

  • Postcondition: (a.len() != b.len() || a.len() < 2) => (result != result)
fn chi_squared_test(observed: &Vec[Int], expected: &Vec[Float64]) -> Float64

Chi-squared goodness-of-fit statistic sum (o - e)^2 / e. NaN for a mismatch or a zero expected count. Complexity: O(n).

  • Postcondition: expected.len() != observed.len() => (result != result)
  • Postcondition: (result >= 0) || (result != result)
fn f_test(a: &Vec[Float64], b: &Vec[Float64]) -> Float64

F statistic as the ratio of the sample variances. NaN for fewer than 2 samples or a zero denominator variance. Complexity: O(n).

  • Postcondition: (a.len() < 2 || b.len() < 2) => (result != result)
  • Postcondition: (result >= 0) || (result != result)
fn anova_one_way(groups: &Vec[Vec[Float64]]) -> Float64

One-way ANOVA F statistic across groups. TODO(compiler): NOT IMPLEMENTABLE in this compiler build - the groups are a Vec[Vec[Float64]] whose element reads return garbage (BUG 23 #1 residual; verified by minimal probe). Keep the frozen signature; revisit when nested float Vec reads land.

  • Postcondition: result != result
fn p_value_from_t(t: Float64, df: Float64) -> Float64

Two-tailed p-value for a t statistic with df degrees of freedom: P(|T| > t) = I_{df/(df + t^2)}(df/2, 1/2). Complexity: O(iterations).

  • Postcondition: df <= 0 => (result != result)
  • Postcondition: (result >= 0 && result <= 1) || (result != result)
fn p_value_from_chi2(x: Float64, df: Float64) -> Float64

Right-tail p-value for a chi-squared statistic: 1 - P(df/2, x/2). Complexity: O(iterations).

  • Postcondition: (df <= 0 || x < 0) => (result != result)
  • Postcondition: (df > 0 && x == 0) => (result == 1)
  • Postcondition: (result >= 0 && result <= 1) || (result != result)
fn z_score(x: Float64, mu: Float64, sigma: Float64) -> Float64

Standardized score (x - mu) / sigma. Complexity: O(1).

  • Postcondition: (sigma == 0) => (result != result)
fn confidence_interval(data: &Vec[Float64], level: Float64) -> (Float64, Float64)

Confidence interval (lower, upper) for the sample mean at the given confidence level. NaN for fewer than 2 samples or an invalid level. Complexity: O(n).

  • Postcondition: (data.len() < 2 || level <= 0 || level >= 1) => ((result._0 != result._0) && (result._1 != result._1))
  • Postcondition: (data.len() >= 2 && level > 0 && level < 1) => ((result._1 >= result._0) || (result._0 != result._0))
fn standard_error(data: &Vec[Float64]) -> Float64

Standard error of the mean. NaN for fewer than 2 samples. Complexity: O(n).

  • Postcondition: data.len() < 2 => (result != result)
  • Postcondition: (result >= 0) || (result != result)