1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
use crate::prelude::*; use ndarray::Array2; use rand::Rng; use spaces::real::PositiveReals; use std::{fmt, ops::Not}; pub use crate::params::Rate; new_dist!(Exponential<Rate<f64>>); macro_rules! get_lambda { ($self:ident) => { ($self.0).0 } } impl Exponential { pub fn new(lambda: f64) -> Result<Exponential, failure::Error> { Ok(Exponential(Rate::new(lambda)?)) } pub fn new_unchecked(lambda: f64) -> Exponential { Exponential(Rate(lambda)) } #[inline(always)] pub fn lambda(&self) -> f64 { get_lambda!(self) } #[inline(always)] pub fn mu(&self) -> f64 { 1.0 / get_lambda!(self) } } impl Default for Exponential { fn default() -> Exponential { Exponential(Rate(1.0)) } } impl Distribution for Exponential { type Support = PositiveReals; type Params = Rate<f64>; fn support(&self) -> PositiveReals { PositiveReals } fn params(&self) -> Rate<f64> { self.0 } fn cdf(&self, x: &f64) -> Probability { Probability::new_unchecked(1.0 - (-get_lambda!(self) * x).exp()) } fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> f64 { use rand_distr::Distribution as _; rand_distr::Exp::new(get_lambda!(self)).unwrap().sample(rng) } } impl ContinuousDistribution for Exponential { fn pdf(&self, x: &f64) -> f64 { let l = get_lambda!(self); l * (-l * x).exp() } } impl UnivariateMoments for Exponential { fn mean(&self) -> f64 { 1.0 / get_lambda!(self) } fn variance(&self) -> f64 { let l = get_lambda!(self); 1.0 / l / l } fn skewness(&self) -> f64 { 2.0 } fn kurtosis(&self) -> f64 { 3.0 } fn excess_kurtosis(&self) -> f64 { 6.0 } } impl Quantiles for Exponential { fn quantile(&self, p: Probability) -> f64 { -(p.not().unwrap()) / get_lambda!(self) } fn median(&self) -> f64 { self.mean() * 2.0f64.ln() } } impl Modes for Exponential { fn modes(&self) -> Vec<f64> { vec![0.0] } } impl Entropy for Exponential { fn entropy(&self) -> f64 { 1.0 - get_lambda!(self).ln() } } impl FisherInformation for Exponential { fn fisher_information(&self) -> Array2<f64> { let l = get_lambda!(self); Array2::from_elem((1, 1), l * l) } } impl fmt::Display for Exponential { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "Exp({})", self.lambda()) } }