probability/distribution/
uniform.rs

1#[allow(unused_imports)]
2use special::Primitive;
3
4use distribution;
5use source::Source;
6
7/// A continuous uniform distribution.
8#[derive(Clone, Copy, Debug)]
9pub struct Uniform {
10    a: f64,
11    b: f64,
12}
13
14impl Uniform {
15    /// Create a uniform distribution on interval `[a, b]`.
16    ///
17    /// It should hold that `a < b`.
18    #[inline]
19    pub fn new(a: f64, b: f64) -> Self {
20        should!(a < b);
21        Uniform { a, b }
22    }
23
24    /// Return the left endpoint of the support.
25    #[inline(always)]
26    pub fn a(&self) -> f64 {
27        self.a
28    }
29
30    /// Return the right endpoint of the support.
31    #[inline(always)]
32    pub fn b(&self) -> f64 {
33        self.b
34    }
35}
36
37impl Default for Uniform {
38    #[inline]
39    fn default() -> Self {
40        Uniform::new(0.0, 1.0)
41    }
42}
43
44impl distribution::Continuous for Uniform {
45    #[inline]
46    fn density(&self, x: f64) -> f64 {
47        if x < self.a || x > self.b {
48            0.0
49        } else {
50            1.0 / (self.b - self.a)
51        }
52    }
53}
54
55impl distribution::Distribution for Uniform {
56    type Value = f64;
57
58    #[inline]
59    fn distribution(&self, x: f64) -> f64 {
60        if x <= self.a {
61            0.0
62        } else if x >= self.b {
63            1.0
64        } else {
65            (x - self.a) / (self.b - self.a)
66        }
67    }
68}
69
70impl distribution::Entropy for Uniform {
71    #[inline]
72    fn entropy(&self) -> f64 {
73        (self.b - self.a).ln()
74    }
75}
76
77impl distribution::Inverse for Uniform {
78    #[inline]
79    fn inverse(&self, p: f64) -> f64 {
80        should!((0.0..=1.0).contains(&p));
81        self.a + (self.b - self.a) * p
82    }
83}
84
85impl distribution::Kurtosis for Uniform {
86    #[inline]
87    fn kurtosis(&self) -> f64 {
88        -1.2
89    }
90}
91
92impl distribution::Mean for Uniform {
93    #[inline]
94    fn mean(&self) -> f64 {
95        (self.a + self.b) / 2.0
96    }
97}
98
99impl distribution::Median for Uniform {
100    #[inline]
101    fn median(&self) -> f64 {
102        use distribution::Mean;
103        self.mean()
104    }
105}
106
107impl distribution::Sample for Uniform {
108    #[inline]
109    fn sample<S>(&self, source: &mut S) -> f64
110    where
111        S: Source,
112    {
113        self.a + (self.b - self.a) * source.read::<f64>()
114    }
115}
116
117impl distribution::Skewness for Uniform {
118    #[inline]
119    fn skewness(&self) -> f64 {
120        0.0
121    }
122}
123
124impl distribution::Variance for Uniform {
125    #[inline]
126    fn variance(&self) -> f64 {
127        (self.b - self.a).powi(2) / 12.0
128    }
129}
130
131#[cfg(test)]
132mod tests {
133    use alloc::{vec, vec::Vec};
134    use prelude::*;
135
136    macro_rules! new(
137        ($a:expr, $b:expr) => (Uniform::new($a, $b));
138    );
139
140    #[test]
141    fn distribution() {
142        let d = new!(-1.0, 1.0);
143        let x = vec![-1.5, -1.0, -0.5, 0.0, 0.5, 1.0, 1.5];
144        let p = vec![0.0, 0.0, 0.25, 0.5, 0.75, 1.0, 1.0];
145
146        assert_eq!(
147            &x.iter().map(|&x| d.distribution(x)).collect::<Vec<_>>(),
148            &p
149        );
150    }
151
152    #[test]
153    fn density() {
154        let d = new!(-1.0, 1.0);
155        let x = vec![-1.5, -1.0, -0.5, 0.0, 0.5, 1.0, 1.5];
156        let p = vec![0.0, 0.5, 0.5, 0.5, 0.5, 0.5, 0.0];
157
158        assert_eq!(&x.iter().map(|&x| d.density(x)).collect::<Vec<_>>(), &p);
159    }
160
161    #[test]
162    fn entropy() {
163        use core::f64::consts::E;
164        assert_eq!(new!(0.0, E).entropy(), 1.0);
165    }
166
167    #[test]
168    fn inverse() {
169        let d = new!(-1.0, 1.0);
170        let x = vec![-1.0, -0.5, 0.0, 0.5, 1.0];
171        let p = vec![0.0, 0.25, 0.5, 0.75, 1.0];
172
173        assert_eq!(&p.iter().map(|&p| d.inverse(p)).collect::<Vec<_>>(), &x);
174    }
175
176    #[test]
177    fn kurtosis() {
178        assert_eq!(new!(0.0, 2.0).kurtosis(), -1.2);
179    }
180
181    #[test]
182    fn mean() {
183        assert_eq!(new!(0.0, 2.0).mean(), 1.0);
184    }
185
186    #[test]
187    fn median() {
188        assert_eq!(new!(0.0, 2.0).median(), 1.0);
189    }
190
191    #[test]
192    fn sample() {
193        for x in Independent(&new!(7.0, 42.0), &mut source::default(42)).take(100) {
194            assert!(7.0 <= x && x <= 42.0);
195        }
196    }
197
198    #[test]
199    fn skewness() {
200        assert_eq!(new!(0.0, 2.0).skewness(), 0.0);
201    }
202
203    #[test]
204    fn variance() {
205        assert_eq!(new!(0.0, 12.0).variance(), 12.0);
206    }
207}