urng 0.9.0

Universal Random Number Generator
Documentation
use crate::wide::{SplitMix32x4, SplitMix32x8, SplitMix32x16, impl_methods, wide_rotate_left};
use ::wide::{u32x4, u32x8, u32x16};

macro_rules! impl_variants {
    ($size:expr) => {
        ::paste::paste! {
            #[repr(C, align(64))]
            pub struct [<Jsf32x $size>] {
                pub(crate) a: [<u32x $size>],
                pub(crate) b: [<u32x $size>],
                pub(crate) c: [<u32x $size>],
                pub(crate) d: [<u32x $size>],
            }

            impl [<Jsf32x $size>] {
                pub fn new(seed: u32) -> Self {
                    let mut seedgen = [<SplitMix32x $size>]::new(seed);
                    Self {
                        a: [<u32x $size>]::splat(0xf1ea5eed),
                        b: bytemuck::cast(seedgen.nextu()),
                        c: bytemuck::cast(seedgen.nextu()),
                        d: bytemuck::cast(seedgen.nextu()),
                    }
                }

                #[inline(always)]
                pub fn nextu(&mut self) -> [u32; $size] {
                    let e = self.a - wide_rotate_left!(32 self.b, 27);
                    self.a = self.b ^ wide_rotate_left!(32 self.c, 17);
                    self.b = self.c + self.d;
                    self.c = self.d + e;
                    self.d = e + self.a;
                    bytemuck::cast(self.d)
                }

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

impl_variants!(4, 8, 16);

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

    crate::safe_test!(Jsf32x4);
    crate::safe_test!(Jsf32x8);
    crate::safe_test!(Jsf32x16);
}