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)
}
}