Pseudo Random Number Generator

Reference: https://github.com/BrutPitt/fastPRNG


struct Rng32([u32; 4]);

impl Rng32 {
    fn split_mix(v: u32) -> u32 {
        let mut z = v.wrapping_add(0x9e3779b9);
        z = (z ^ (z >> 15)).wrapping_mul(0x85ebca6b);
        z = (z ^ (z >> 13)).wrapping_mul(0xc2b2ae35);
        z ^ (z >> 16)
    }
    fn new() -> Self {
        let mut seed = 0;
        unsafe { std::arch::x86_64::_rdrand32_step(&mut seed) };
        let mut prev = seed;
        Self(std::array::from_fn(|_| {
            prev = Self::split_mix(prev);
            prev
        }))
    }
    fn next(&mut self, n: u32) -> u32 {
        let [x, y, z, w] = &mut self.0;
        let res = x.wrapping_add(*w);
        let t = x.wrapping_shl(9);
        *y ^= *x;
        *w ^= *y;
        *y ^= *z;
        *x ^= *w;
        *z ^= t;
        *w = w.rotate_left(11);
        ((res as u64 * n as u64) >> 32) as u32
    }
}

struct Rng64([u64; 4]);

impl Rng64 {
    fn split_mix(v: u64) -> u64 {
        let mut z = v.wrapping_add(0x9e3779b97f4a7c15);
        z = (z ^ (z >> 30)).wrapping_mul(0xbf58476d1ce4e5b9);
        z = (z ^ (z >> 27)).wrapping_mul(0x94d049bb133111eb);
        z ^ (z >> 31)
    }
    fn new() -> Self {
        let mut seed = 0;
        unsafe { std::arch::x86_64::_rdrand64_step(&mut seed) };
        let mut prev = seed;
        Self(std::array::from_fn(|_| {
            prev = Self::split_mix(prev);
            prev
        }))
    }
    fn next(&mut self, n: u64) -> u64 {
        let [x, y, z, w] = &mut self.0;
        let res = x.wrapping_add(*w);
        let t = x.wrapping_shl(17);
        *y ^= *x;
        *w ^= *y;
        *y ^= *z;
        *x ^= *w;
        *z ^= t;
        *w = w.rotate_left(45);
        ((res as u128 * n as u128) >> 64) as u64
    }
}