weiss_core/
util.rs

1/// Deterministic xorshift64* RNG for reproducibility.
2#[derive(Clone, Copy, Debug, Hash)]
3pub struct Rng64 {
4    state: u64,
5}
6
7impl Rng64 {
8    /// Create a new RNG (zero seed is remapped).
9    pub fn new(seed: u64) -> Self {
10        let mut s = seed;
11        if s == 0 {
12            s = 0x9E3779B97F4A7C15;
13        }
14        Self { state: s }
15    }
16
17    /// Generate the next u64.
18    pub fn next_u64(&mut self) -> u64 {
19        // xorshift64*
20        let mut x = self.state;
21        x ^= x >> 12;
22        x ^= x << 25;
23        x ^= x >> 27;
24        self.state = x;
25        x.wrapping_mul(0x2545F4914F6CDD1D)
26    }
27
28    /// Generate the next u32.
29    pub fn next_u32(&mut self) -> u32 {
30        (self.next_u64() >> 32) as u32
31    }
32
33    /// Read the current internal state.
34    pub fn state(&self) -> u64 {
35        self.state
36    }
37
38    /// Generate a boolean with 50/50 probability.
39    pub fn next_bool(&mut self) -> bool {
40        (self.next_u64() & 1) == 1
41    }
42
43    /// Generate a uniform integer in [0, upper).
44    pub fn gen_range(&mut self, upper: usize) -> usize {
45        if upper == 0 {
46            return 0;
47        }
48        (self.next_u64() as usize) % upper
49    }
50
51    /// Shuffle a slice in-place.
52    pub fn shuffle<T>(&mut self, slice: &mut [T]) {
53        for i in (1..slice.len()).rev() {
54            let j = self.gen_range(i + 1);
55            slice.swap(i, j);
56        }
57    }
58}