r2rs-nmath 0.1.1

Statistics programming for Rust based on R's nmath package
Documentation
use crate::{
    rng::{fixup, i2_32m1},
    traits::RNG,
};

#[derive(Clone, Debug)]
pub struct MarsagliaMulticarry {
    state: [u32; 2],
}

impl Default for MarsagliaMulticarry {
    fn default() -> Self {
        Self::new()
    }
}

impl MarsagliaMulticarry {
    pub fn new() -> Self {
        let mut ret = Self { state: [0; 2] };
        ret.randomize();
        ret
    }

    pub fn fixup_seeds(&mut self) {
        if self.state[0] == 0 {
            self.state[0] = 1
        }
        if self.state[1] == 0 {
            self.state[1] = 1
        }
    }
}

impl RNG for MarsagliaMulticarry {
    fn set_seed(&mut self, mut seed: u32) {
        for _ in 0..50 {
            seed = seed.wrapping_mul(69069).wrapping_add(1);
        }

        (0..2).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 {
        self.state[0] = (self.state[0] & 0o177777)
            .wrapping_mul(36969)
            .wrapping_add(self.state[0] >> 16);
        self.state[1] = (self.state[1] & 0o177777)
            .wrapping_mul(18000)
            .wrapping_add(self.state[1] >> 16);
        let x = ((self.state[0] << 16) ^ (self.state[1] & 0o177777)) as f64 * i2_32m1;

        fixup(x)
    }
}