Skip to main content

numra_stats/distributions/
uniform.rs

1//! Continuous uniform distribution.
2//!
3//! Author: Moussa Leblouba
4//! Date: 9 February 2026
5//! Modified: 2 May 2026
6
7use numra_core::Scalar;
8use rand::RngCore;
9
10use super::normal::random_uniform_01;
11use super::ContinuousDistribution;
12
13/// Continuous uniform distribution on [a, b].
14#[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}