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