use crate::{
rng::{fixup, i2_32m1},
traits::RNG,
};
#[derive(Clone, Debug)]
pub struct SuperDuper {
state: [u32; 2],
}
impl Default for SuperDuper {
fn default() -> Self {
Self::new()
}
}
impl SuperDuper {
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
}
self.state[1] |= 1;
}
}
impl RNG for SuperDuper {
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 {
let i1 = self.state[0];
self.state[0] ^= (i1 >> 15) & 0o377777;
let i1 = self.state[0];
self.state[0] ^= i1 << 17;
let i2 = self.state[1];
self.state[1] = i2.wrapping_mul(69069);
let (i1, i2) = (self.state[0], self.state[1]);
fixup((i1 ^ i2) as f64 * i2_32m1)
}
}