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.0_f64, 1.0_f64).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];
}
}