urng 0.9.0

Universal Random Number Generator
Documentation
use crate::wide::{impl_methods, wide_rotate_left};
use crate::{Rng32, SplitMix32};
use ::wide::{u32x4, u32x8, u32x16};

macro_rules! impl_variants {
    ($size:expr) => {
        ::paste::paste! {
            #[allow(dead_code)]
            #[repr(C, align(64))]
            pub struct [<Xoroshiro64Ssx $size>] {
                s0: [<u32x $size>],
                s1: [<u32x $size>],
            }

            #[allow(dead_code)]
            impl [<Xoroshiro64Ssx $size>] {
                pub fn new(seed: u32) -> Self {
                    let mut seedgen = SplitMix32::new(seed);
                    Self {
                        s0: [<u32x $size>]::from([0u32; $size].map(|_| seedgen.nextu())),
                        s1: [<u32x $size>]::from([0u32; $size].map(|_| seedgen.nextu())),
                    }
                }

                #[inline(always)]
                pub fn nextu(&mut self) -> [u32; $size] {
                    let s0 = self.s0;
                    let mut s1 = self.s1;
                    let result = wide_rotate_left!(32 (s0 * 0x9E3779BBu32), 5) * 5u32;

                    s1 ^= s0;
                    self.s0 = wide_rotate_left!(32 s0, 26) ^ s1 ^ (s1 << 9);
                    self.s1 = wide_rotate_left!(32 s1, 13);

                    bytemuck::cast(result)
                }

                impl_methods!($size, 32);
            }
        }
    };
    ($($size:expr),+ $(,)*) => {
        $(impl_variants!($size);)+
    };
}

impl_variants!(4, 8, 16);

#[cfg(test)]
mod tests {
    use super::*;

    crate::safe_test!(Xoroshiro64Ssx4);
    crate::safe_test!(Xoroshiro64Ssx8);
    crate::safe_test!(Xoroshiro64Ssx16);
}