Skip to main content

probability_rs/rng/
splitmix64.rs

1//! SplitMix64 (Sebastiano Vigna): fast, good bit diffusion, non-cryptographic RNG.
2
3use super::RngCore;
4
5#[derive(Clone, Debug)]
6pub struct SplitMix64 {
7    pub(crate) state: u64,
8}
9
10impl SplitMix64 {
11    pub fn seed_from_u64(seed: u64) -> Self {
12        Self { state: seed }
13    }
14}
15
16impl RngCore for SplitMix64 {
17    #[inline]
18    fn next_u64(&mut self) -> u64 {
19        let mut z = {
20            self.state = self.state.wrapping_add(0x9E3779B97F4A7C15);
21            self.state
22        };
23        z = (z ^ (z >> 30)).wrapping_mul(0xBF58476D1CE4E5B9);
24        z = (z ^ (z >> 27)).wrapping_mul(0x94D049BB133111EB);
25        z ^ (z >> 31)
26    }
27}
28
29#[cfg(test)]
30mod tests {
31    use super::*;
32    #[test]
33    fn deterministic_sequence() {
34        let mut r1 = SplitMix64::seed_from_u64(1);
35        let mut r2 = SplitMix64::seed_from_u64(1);
36        for _ in 0..10 {
37            assert_eq!(r1.next_u64(), r2.next_u64());
38        }
39    }
40}