#[derive(Clone, Debug)]
pub struct Rng {
s: [u64; 4],
}
impl Rng {
#[must_use]
pub fn seed_from_u64(mut seed: u64) -> Self {
let mut next = || {
seed = seed.wrapping_add(0x9E37_79B9_7F4A_7C15);
let mut z = seed;
z = (z ^ (z >> 30)).wrapping_mul(0xBF58_476D_1CE4_E5B9);
z = (z ^ (z >> 27)).wrapping_mul(0x94D0_49BB_1331_11EB);
z ^ (z >> 31)
};
Self {
s: [next(), next(), next(), next()],
}
}
#[inline]
pub fn next_u64(&mut self) -> u64 {
let result = self.s[0]
.wrapping_add(self.s[3])
.rotate_left(23)
.wrapping_add(self.s[0]);
let t = self.s[1] << 17;
self.s[2] ^= self.s[0];
self.s[3] ^= self.s[1];
self.s[1] ^= self.s[2];
self.s[0] ^= self.s[3];
self.s[2] ^= t;
self.s[3] = self.s[3].rotate_left(45);
result
}
#[inline]
pub fn next_f64(&mut self) -> f64 {
let bits = self.next_u64() >> 11;
bits as f64 * (1.0 / (1u64 << 53) as f64)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn same_seed_same_stream() {
let mut a = Rng::seed_from_u64(42);
let mut b = Rng::seed_from_u64(42);
for _ in 0..100 {
assert_eq!(a.next_u64(), b.next_u64());
}
}
#[test]
fn different_seeds_differ() {
let mut a = Rng::seed_from_u64(1);
let mut b = Rng::seed_from_u64(2);
assert_ne!(a.next_u64(), b.next_u64());
}
#[test]
fn f64_in_unit_interval() {
let mut r = Rng::seed_from_u64(7);
for _ in 0..10_000 {
let x = r.next_f64();
assert!((0.0..1.0).contains(&x));
}
}
#[test]
fn f64_mean_is_near_half() {
let mut r = Rng::seed_from_u64(123);
let n = 100_000;
let mean: f64 = (0..n).map(|_| r.next_f64()).sum::<f64>() / f64::from(n);
assert!((mean - 0.5).abs() < 0.01);
}
}