use crate::{rng::fixup, traits::RNG};
#[derive(Clone, Debug)]
pub struct WichmannHill {
state: [u32; 3],
}
impl Default for WichmannHill {
fn default() -> Self {
Self::new()
}
}
impl WichmannHill {
pub fn new() -> Self {
let mut ret = Self { state: [0; 3] };
ret.randomize();
ret
}
pub fn fixup_seeds(&mut self) {
let i1 = self.state[0];
self.state[0] = i1 % 30269;
let i2 = self.state[1];
self.state[1] = i2 % 30307;
let i3 = self.state[2];
self.state[2] = i3 % 30323;
}
}
impl RNG for WichmannHill {
fn set_seed(&mut self, mut seed: u32) {
for _ in 0..50 {
seed = seed.wrapping_mul(69069).wrapping_add(1);
}
(0..3).for_each(|j| {
seed = seed.wrapping_mul(69069).wrapping_add(1);
self.state[j] = seed;
});
self.fixup_seeds()
}
fn get_state(&self) -> Vec<i32> {
self.state.clone().iter().map(|&i| i as i32).collect()
}
fn unif_rand(&mut self) -> f64 {
let i1 = self.state[0];
self.state[0] = i1.wrapping_mul(171).wrapping_rem(30269);
let i2 = self.state[1];
self.state[1] = i2.wrapping_mul(172).wrapping_rem(30307);
let i3 = self.state[2];
self.state[2] = i3.wrapping_mul(170).wrapping_rem(30323);
let (i1, i2, i3) = (self.state[0], self.state[1], self.state[2]);
let value = i1 as f64 / 30269.0 + i2 as f64 / 30307.0 + i3 as f64 / 30323.0;
fixup(value - value.trunc())
}
}