Skip to main content

probability_rs/dist/
exponential.rs

1use crate::dist::{Continuous, DistError, Distribution, Moments};
2use crate::rng::RngCore;
3
4#[derive(Debug, Clone, Copy)]
5pub struct Exponential {
6    lambda: f64,
7}
8
9impl Exponential {
10    pub fn new(lambda: f64) -> Result<Self, DistError> {
11        if !(lambda > 0.0 && lambda.is_finite()) {
12            return Err(DistError::InvalidParameter);
13        }
14        Ok(Self { lambda })
15    }
16    #[inline]
17    pub fn lambda(&self) -> f64 {
18        self.lambda
19    }
20}
21
22impl Distribution for Exponential {
23    type Value = f64;
24    fn cdf(&self, x: f64) -> f64 {
25        if x <= 0.0 {
26            0.0
27        } else {
28            1.0 - (-self.lambda * x).exp()
29        }
30    }
31    fn in_support(&self, x: f64) -> bool {
32        x >= 0.0 && x.is_finite()
33    }
34    fn sample<R: RngCore>(&self, rng: &mut R) -> f64 {
35        let u = rng.next_f64();
36        -u.ln() / self.lambda
37    }
38}
39
40impl Continuous for Exponential {
41    fn pdf(&self, x: f64) -> f64 {
42        if self.in_support(x) {
43            self.lambda * (-self.lambda * x).exp()
44        } else {
45            0.0
46        }
47    }
48    fn inv_cdf(&self, p: f64) -> f64 {
49        debug_assert!(p > 0.0 && p < 1.0);
50        -(1.0 - p).ln() / self.lambda
51    }
52}
53
54impl Moments for Exponential {
55    fn mean(&self) -> f64 {
56        1.0 / self.lambda
57    }
58    fn variance(&self) -> f64 {
59        1.0 / (self.lambda * self.lambda)
60    }
61    fn skewness(&self) -> f64 { 2.0 }
62    fn kurtosis(&self) -> f64 { 6.0 }
63    fn entropy(&self) -> f64 { 1.0 - self.lambda.ln() }
64}
65
66#[cfg(test)]
67mod tests {
68    use super::*;
69    #[test]
70    fn basic_values() {
71        let e = Exponential::new(2.0).unwrap();
72        assert!((e.mean() - 0.5).abs() < 1e-15);
73        assert!((e.variance() - 0.25).abs() < 1e-15);
74        assert!((e.cdf(0.0) - 0.0).abs() < 1e-15);
75        assert!((e.pdf(0.0) - 2.0).abs() < 1e-12);
76        assert!((e.skewness() - 2.0).abs() < 1e-15);
77        assert!((e.kurtosis() - 6.0).abs() < 1e-15);
78    }
79}