1use statrs::distribution::{Continuous, ContinuousCDF, Normal};
8
9fn standard() -> Normal {
10 Normal::new(0.0, 1.0).expect("N(0,1) is well-defined")
12}
13
14pub fn cdf(x: f64) -> f64 {
16 standard().cdf(x)
17}
18
19pub fn pdf(x: f64) -> f64 {
21 standard().pdf(x)
22}
23
24pub fn inverse_cdf(p: f64) -> f64 {
26 assert!(
27 p > 0.0 && p < 1.0,
28 "inverse_cdf input must be in (0, 1), got {}",
29 p
30 );
31 standard().inverse_cdf(p)
32}
33
34#[cfg(test)]
35mod tests {
36 use super::{cdf, inverse_cdf};
37
38 #[test]
39 fn cdf_is_symmetric_around_zero() {
40 assert!((cdf(0.0) - 0.5).abs() < 1e-12);
41 assert!((cdf(-1.0) + cdf(1.0) - 1.0).abs() < 1e-12);
42 }
43
44 #[test]
45 fn inverse_cdf_round_trip() {
46 for p in [0.1, 0.25, 0.5, 0.75, 0.9] {
47 let x = inverse_cdf(p);
48 assert!((cdf(x) - p).abs() < 1e-9);
49 }
50 }
51
52 #[test]
53 fn quartile_matches_known_value() {
54 let q = inverse_cdf(0.25);
56 assert!((q - (-0.6744897501960818)).abs() < 1e-9);
57 }
58}