Skip to main content

qualia_core_db/solvers/statistics/
mod.rs

1//! Statistics solver — the single, canonical home for numeric statistics.
2//!
3//! Zero-allocation kernels over caller-owned slices, a sibling to
4//! `solvers::linear_algebra`. This is where descriptive statistics, hypothesis
5//! tests, correlation, and binning live for the *whole* engine.
6//!
7//! **Composition rule (Modality-First):** specialized/domain libraries
8//! (`specialized_libs::statistical_computing`, `machine_learning`, …) marshal
9//! their domain data into a slice and call these functions. They MUST NOT carry
10//! their own `mean`/`variance`/`correlation` re-implementations. See
11//! `MODALITY_FIRST_CONSOLIDATION.md`.
12//!
13//! Probabilistic *logic* (Bayesian networks, truth-degree reasoning over quins)
14//! is a separate concern and lives in `modalities::probabilistic`; it may call
15//! into here for numeric work, but the two are not merged.
16
17pub mod anomaly;
18pub mod correlation;
19pub mod descriptive;
20pub mod distributions;
21pub mod histogram;
22pub mod hypothesis;
23pub mod information;
24pub mod regression;
25pub mod robust;
26pub mod timeseries;
27
28pub use correlation::{correlation_p_value, kendall, pearson, rank_into, spearman};
29pub use descriptive::{
30    covariance, kurtosis, max, mean, median_in_place, median_sorted, min, mode_in_place,
31    quantile_in_place, quantile_sorted, skewness, std_dev, sum, variance,
32};
33pub use histogram::{histogram_into, HistRange};
34pub use timeseries::{autocorrelation, exponential_smoothing_into, moving_average_into};
35
36pub use hypothesis::{
37    chi_square_gof, chi_square_independence, friedman, ks_1sample, mann_whitney_u, mcnemar,
38    one_sample_t, one_way_anova, paired_t, two_sample_t, AnovaResult, ChiSquareResult,
39    FriedmanResult, KolmogorovSmirnovResult, MannWhitneyResult, NonparametricResult, TTest,
40    TwoSampleTTest,
41};
42pub use information::{cross_entropy, entropy, kl_divergence, mutual_information_discrete};
43pub use regression::{simple_linear_regression, LinearRegression};
44pub use robust::{iqr, median_abs_deviation, trimmed_mean, winsorized_mean};
45
46/// Basic bootstrap mean (cold bounded, for calibration/validation).
47/// Resamples with replacement using provided RNG state (SplitMix style).
48/// Writes means for `num_samples` into `out`.
49pub fn bootstrap_means(
50    data: &[f64],
51    num_samples: usize,
52    seed: u64,
53    out: &mut [f64],
54) -> Result<usize, ()> {
55    if data.is_empty() || num_samples == 0 || out.len() < num_samples {
56        return Err(());
57    }
58    let mut rng = seed;
59    for s in 0..num_samples {
60        let mut sum = 0.0;
61        for _ in 0..data.len() {
62            // simple xorshift for demo
63            rng ^= rng << 13;
64            rng ^= rng >> 7;
65            rng ^= rng << 17;
66            let idx = (rng as usize) % data.len();
67            sum += data[idx];
68        }
69        out[s] = sum / data.len() as f64;
70    }
71    Ok(num_samples)
72}
73
74/// Ljung-Box test statistic for autocorrelation up to lag h.
75/// acf[0..h] are sample autocorrelations (from lag 1).
76pub fn ljung_box(acf: &[f64], n: usize, h: usize) -> f64 {
77    if h == 0 || acf.len() < h {
78        return f64::NAN;
79    }
80    let mut q = 0.0;
81    for k in 1..=h {
82        if k - 1 < acf.len() {
83            q += acf[k - 1].powi(2) / (n - k) as f64;
84        }
85    }
86    q * n as f64
87}
88
89/// Simple ADF-like stationarity proxy (negative means more stationary tendency).
90pub fn adf_proxy(series: &[f64]) -> f64 {
91    if series.len() < 3 {
92        return f64::NAN;
93    }
94    let mut sum_diff = 0.0;
95    let mut sum_lag = 0.0;
96    for i in 1..series.len() {
97        let diff = series[i] - series[i - 1];
98        sum_diff += diff * series[i - 1];
99        sum_lag += series[i - 1] * series[i - 1];
100    }
101    if sum_lag.abs() < 1e-12 {
102        return 0.0;
103    }
104    sum_diff / sum_lag
105}
106
107// Additional distributions (5.1-A progress)
108pub use distributions::{
109    beta_pdf, binomial_cdf, binomial_pmf, empirical_cdf, exponential_cdf, exponential_pdf,
110    gamma_pdf, laplace_cdf, laplace_pdf, lognormal_cdf, lognormal_pdf, poisson_cdf, poisson_pmf,
111    uniform_cdf, uniform_pdf, weibull_pdf,
112};