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
use rand::distributions::{Distribution, Uniform};
use rand_pcg::Pcg64Mcg;
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct UniformRNG {
rng: Pcg64Mcg,
}
impl Default for UniformRNG {
fn default() -> Self {
UniformRNG {
rng: Pcg64Mcg::new(42),
}
}
}
impl UniformRNG {
pub fn rn(&mut self) -> f64 {
Uniform::new(0.0f64, 1.0f64).sample(&mut self.rng)
}
pub fn rng(&mut self) -> &mut Pcg64Mcg {
&mut self.rng
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn generator_chi_square_uniformity_test() {
let mut uniform_rng = UniformRNG::default();
let mut class_counts: [f64; 100] = [0.0; 100];
(0..100000).for_each(|_| {
let rn = uniform_rng.rn();
class_counts[(rn * 100.0) as usize] += 1.0;
});
let expected_count = 1000.0;
let chi_square = class_counts.iter().fold(0.0, |acc, class_count| {
acc + (*class_count - expected_count).powi(2) / expected_count
});
let chi_square_critical = 134.642;
assert![chi_square < chi_square_critical];
}
}