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}