numerics.rs

1.3 kB · rust · 48 lines

1pub fn sum(values: &[f64]) -> f64 {2    if values.len() <= 8 {3        return values.iter().fold(0.0, |acc, v| acc + v);4    }5    let (left, right) = values.split_at(values.len() / 2);6    sum(left) + sum(right)7}89pub fn mean(values: &[f64]) -> f64 {10    sum(values) / values.len() as f6411}1213pub fn fraction_below(values: &[f64], bound: f64) -> f64 {14    values.iter().filter(|v| **v < bound).count() as f64 / values.len() as f6415}1617pub fn goe(s: f64) -> f64 {18    1.0 - (-std::f64::consts::PI * s * s / 4.0).exp()19}2021pub fn poisson(s: f64) -> f64 {22    1.0 - (-s).exp()23}2425pub fn ks_distance(values: &[f64], law: fn(f64) -> f64) -> f64 {26    let mut sorted = values.to_vec();27    sorted.sort_by(|a, b| a.partial_cmp(b).expect("finite spacings"));28    let m = sorted.len() as f64;29    let mut worst: f64 = 0.0;30    for (i, s) in sorted.iter().enumerate() {31        let f = law(*s);32        worst = worst.max((i + 1) as f64 / m - f).max(f - i as f64 / m);33    }34    worst35}3637pub fn ks_pvalue(distance: f64, count: usize) -> f64 {38    let z = distance * (count as f64).sqrt();39    if z < 1e-6 {40        return 1.0;41    }42    let mut total = 0.0;43    for k in 1..200 {44        let sign = if k % 2 == 1 { 2.0 } else { -2.0 };45        total += sign * (-2.0 * (k * k) as f64 * z * z).exp();46    }47    total.clamp(0.0, 1.0)48}