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
use crate::{ consts::{PI, PI2, PI_OVER_2, THREE_HALVES}, prelude::*, }; use rand::Rng; use spaces::real::PositiveReals; use std::fmt; const TWO_PI_MINUS_3: f64 = 2.0 * (PI - 3.0); const FOUR_MINUS_PI: f64 = (4.0 - PI); const FOUR_MINUS_PI_OVER_2: f64 = FOUR_MINUS_PI / 2.0; const EXCESS_KURTOSIS: f64 = 1.5 * PI2 - 6.0 * PI + 16.0 / FOUR_MINUS_PI_OVER_2 / FOUR_MINUS_PI_OVER_2; const KURTOSIS: f64 = EXCESS_KURTOSIS + 3.0; pub use crate::params::Shape; new_dist!(Rayleigh<Shape<f64>>); macro_rules! get_sigma { ($self:ident) => { ($self.0).0 } } impl Rayleigh { pub fn new(sigma: f64) -> Result<Rayleigh, failure::Error> { Ok(Rayleigh(Shape::new(sigma)?)) } pub fn new_unchecked(sigma: f64) -> Rayleigh { Rayleigh(Shape(sigma)) } } impl Distribution for Rayleigh { type Support = PositiveReals; type Params = Shape<f64>; fn support(&self) -> PositiveReals { PositiveReals } fn params(&self) -> Shape<f64> { self.0 } fn cdf(&self, x: &f64) -> Probability { let sigma = get_sigma!(self); Probability::new_unchecked(1.0 - (-x * x / sigma * sigma / 2.0).exp()) } fn sample<R: Rng + ?Sized>(&self, _: &mut R) -> f64 { unimplemented!() } } impl ContinuousDistribution for Rayleigh { fn pdf(&self, x: &f64) -> f64 { let sigma = get_sigma!(self); let sigma2 = sigma * sigma; x / sigma2 * (-x * x / sigma2 / 2.0).exp() } } impl UnivariateMoments for Rayleigh { fn mean(&self) -> f64 { get_sigma!(self) * PI_OVER_2.sqrt() } fn variance(&self) -> f64 { let sigma = get_sigma!(self); FOUR_MINUS_PI_OVER_2 * sigma * sigma } fn skewness(&self) -> f64 { TWO_PI_MINUS_3 * PI.sqrt() / FOUR_MINUS_PI.powf(THREE_HALVES) } fn kurtosis(&self) -> f64 { KURTOSIS } fn excess_kurtosis(&self) -> f64 { EXCESS_KURTOSIS } } impl Quantiles for Rayleigh { fn quantile(&self, _: Probability) -> f64 { unimplemented!() } fn median(&self) -> f64 { get_sigma!(self) * (2.0 * 2.0f64.ln()).sqrt() } } impl Modes for Rayleigh { fn modes(&self) -> Vec<f64> { vec![get_sigma!(self)] } } impl Entropy for Rayleigh { fn entropy(&self) -> f64 { use special_fun::FloatSpecial; let gamma = -(1.0f64.digamma()); 1.0 + (get_sigma!(self) / 2.0f64.sqrt()).ln() + gamma / 2.0 } } impl fmt::Display for Rayleigh { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "Rayleigh({})", get_sigma!(self)) } }