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 111 112 113 114 115 116 117
use crate::core::*; use rand::Rng; use spaces::continuous::PositiveReals; use std::fmt; #[derive(Debug, Clone, Copy)] pub struct InvGamma { pub alpha: f64, pub beta: f64, } impl InvGamma { pub fn new(alpha: f64, beta: f64) -> InvGamma { assert_positive_real!(alpha); assert_positive_real!(beta); InvGamma { alpha, beta } } pub fn with_scale(k: f64, theta: f64) -> InvGamma { InvGamma::new(k, 1.0 / theta) } } impl Default for InvGamma { fn default() -> InvGamma { InvGamma { alpha: 1.0, beta: 1.0, } } } impl Distribution for InvGamma { type Support = PositiveReals; fn support(&self) -> PositiveReals { PositiveReals } fn cdf(&self, x: f64) -> Probability { use special_fun::FloatSpecial; (self.alpha.gammainc(self.beta / x) / self.alpha.gamma()).into() } fn sample<R: Rng + ?Sized>(&self, _: &mut R) -> f64 { unimplemented!() } } impl ContinuousDistribution for InvGamma { fn pdf(&self, x: f64) -> Probability { use special_fun::FloatSpecial; (self.beta.powf(self.alpha) * x.powf(-self.alpha - 1.0) * (-self.beta / x).exp() / self.alpha.gamma()) .into() } } impl UnivariateMoments for InvGamma { fn mean(&self) -> f64 { if self.alpha <= 1.0 { unimplemented!("Mean is undefined for alpha <= 1.") } self.beta / (self.alpha - 1.0) } fn variance(&self) -> f64 { if self.alpha <= 2.0 { unimplemented!("Variance is undefined for alpha <= 2.") } let am1 = self.alpha - 1.0; self.beta * self.beta / am1 / am1 / (self.alpha - 2.0) } fn skewness(&self) -> f64 { if self.alpha <= 3.0 { unimplemented!("Skewness is undefined for alpha <= 3.") } 4.0 * (self.alpha - 2.0).sqrt() / (self.alpha - 3.0) } fn excess_kurtosis(&self) -> f64 { if self.alpha <= 4.0 { unimplemented!("Kurtosis is undefined for alpha <= 4.") } (30.0 * self.alpha - 66.0) / (self.alpha - 3.0) / (self.alpha - 4.0) } } impl Modes for InvGamma { fn modes(&self) -> Vec<f64> { vec![self.beta / (self.alpha + 1.0)] } } impl Entropy for InvGamma { fn entropy(&self) -> f64 { use special_fun::FloatSpecial; self.alpha + (self.beta * self.alpha.gamma()).ln() - (1.0 + self.alpha) * self.alpha.digamma() } } impl fmt::Display for InvGamma { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "Inv-Gamma({}, {})", self.alpha, self.beta) } }