r2rs-nmath 0.1.1

Statistics programming for Rust based on R's nmath package
Documentation
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())
    }
}