diff --git a/src/distribution/exponential.rs b/src/distribution/exponential.rs index 0856989c..c335b895 100644 --- a/src/distribution/exponential.rs +++ b/src/distribution/exponential.rs @@ -109,6 +109,19 @@ impl ContinuousCDF for Exp { (-self.rate * x).exp() } } + + /// Calculates the inverse cumulative distribution function. + /// + /// # Formula + /// + /// ```ignore + /// -ln(1 - p) / λ + /// ``` + /// + /// where `p` is the probability and `λ` is the rate + fn inverse_cdf(&self, p: f64) -> f64 { + -(1.0 - p).ln() / self.rate + } } impl Min for Exp { @@ -457,6 +470,27 @@ mod tests { test_case(f64::INFINITY, 1.0, cdf(f64::INFINITY)); } + #[test] + fn test_inverse_cdf() { + let distribution = Exp::new(0.42).unwrap(); + assert_eq!(distribution.median(), distribution.inverse_cdf(0.5)); + + let distribution = Exp::new(0.042).unwrap(); + assert_eq!(distribution.median(), distribution.inverse_cdf(0.5)); + + let distribution = Exp::new(0.0042).unwrap(); + assert_eq!(distribution.median(), distribution.inverse_cdf(0.5)); + + let distribution = Exp::new(0.33).unwrap(); + assert_eq!(distribution.median(), distribution.inverse_cdf(0.5)); + + let distribution = Exp::new(0.033).unwrap(); + assert_eq!(distribution.median(), distribution.inverse_cdf(0.5)); + + let distribution = Exp::new(0.0033).unwrap(); + assert_eq!(distribution.median(), distribution.inverse_cdf(0.5)); + } + #[test] fn test_sf() { let sf = |arg: f64| move |x: Exp| x.sf(arg);