#[derive(Debug, Clone)]
pub(crate) struct SplitMix64(u64);
impl SplitMix64 {
pub(crate) fn new(seed: u64) -> Self {
Self(seed)
}
pub(crate) fn next_u64(&mut self) -> u64 {
self.0 = self.0.wrapping_add(0x9E37_79B9_7F4A_7C15);
let mut z = self.0;
z = (z ^ (z >> 30)).wrapping_mul(0xBF58_476D_1CE4_E5B9);
z = (z ^ (z >> 27)).wrapping_mul(0x94D0_49BB_1331_11EB);
z ^ (z >> 31)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn deterministic_for_same_seed() {
let mut a = SplitMix64::new(42);
let mut b = SplitMix64::new(42);
let seq_a: Vec<u64> = (0..8).map(|_| a.next_u64()).collect();
let seq_b: Vec<u64> = (0..8).map(|_| b.next_u64()).collect();
assert_eq!(seq_a, seq_b);
}
#[test]
fn differs_across_seeds_and_advances() {
let mut a = SplitMix64::new(1);
let mut b = SplitMix64::new(2);
assert_ne!(a.next_u64(), b.next_u64());
let first = SplitMix64::new(1).next_u64();
let mut c = SplitMix64::new(1);
let _ = c.next_u64();
assert_ne!(first, c.next_u64());
}
}