numra_stats/distributions/
uniform.rs1use numra_core::Scalar;
8use rand::RngCore;
9
10use super::normal::random_uniform_01;
11use super::ContinuousDistribution;
12
13#[derive(Clone, Debug)]
15pub struct Uniform<S: Scalar> {
16 pub a: S,
17 pub b: S,
18}
19
20impl<S: Scalar> Uniform<S> {
21 pub fn new(a: S, b: S) -> Self {
22 Self { a, b }
23 }
24}
25
26impl<S: Scalar> ContinuousDistribution<S> for Uniform<S> {
27 fn pdf(&self, x: S) -> S {
28 if x >= self.a && x <= self.b {
29 S::ONE / (self.b - self.a)
30 } else {
31 S::ZERO
32 }
33 }
34
35 fn cdf(&self, x: S) -> S {
36 if x < self.a {
37 S::ZERO
38 } else if x > self.b {
39 S::ONE
40 } else {
41 (x - self.a) / (self.b - self.a)
42 }
43 }
44
45 fn quantile(&self, p: S) -> S {
46 self.a + p * (self.b - self.a)
47 }
48
49 fn mean(&self) -> S {
50 let half = S::HALF;
51 (self.a + self.b) * half
52 }
53
54 fn variance(&self) -> S {
55 let twelve = S::from_f64(12.0);
56 let d = self.b - self.a;
57 d * d / twelve
58 }
59
60 fn sample(&self, rng: &mut dyn RngCore) -> S {
61 let u = random_uniform_01::<S>(rng);
62 self.a + u * (self.b - self.a)
63 }
64}
65
66#[cfg(test)]
67mod tests {
68 use super::*;
69
70 #[test]
71 fn test_uniform_pdf() {
72 let u = Uniform::new(0.0_f64, 1.0);
73 assert!((u.pdf(0.5) - 1.0).abs() < 1e-14);
74 assert!((u.pdf(-0.1)).abs() < 1e-14);
75 assert!((u.pdf(1.1)).abs() < 1e-14);
76 }
77
78 #[test]
79 fn test_uniform_cdf() {
80 let u = Uniform::new(2.0_f64, 4.0);
81 assert!((u.cdf(2.0)).abs() < 1e-14);
82 assert!((u.cdf(3.0) - 0.5).abs() < 1e-14);
83 assert!((u.cdf(4.0) - 1.0).abs() < 1e-14);
84 }
85
86 #[test]
87 fn test_uniform_quantile() {
88 let u = Uniform::new(0.0_f64, 10.0);
89 assert!((u.quantile(0.0)).abs() < 1e-14);
90 assert!((u.quantile(0.5) - 5.0).abs() < 1e-14);
91 assert!((u.quantile(1.0) - 10.0).abs() < 1e-14);
92 }
93
94 #[test]
95 fn test_uniform_mean_variance() {
96 let u = Uniform::new(0.0_f64, 12.0);
97 assert!((u.mean() - 6.0).abs() < 1e-14);
98 assert!((u.variance() - 12.0).abs() < 1e-14);
99 }
100}