1#[inline]
13fn splitmix64(state: &mut u64) -> u64 {
14 *state = state.wrapping_add(0x9E37_79B9_7F4A_7C15);
15 let mut z = *state;
16 z = (z ^ (z >> 30)).wrapping_mul(0xBF58_476D_1CE4_E5B9);
17 z = (z ^ (z >> 27)).wrapping_mul(0x94D0_49BB_1331_11EB);
18 z ^ (z >> 31)
19}
20
21#[derive(Debug, Clone)]
22pub struct Rng {
23 s: [u64; 4],
24}
25
26impl Rng {
27 pub fn seed_from(seed: u64) -> Self {
28 let mut sm = seed;
29 Rng {
30 s: [
31 splitmix64(&mut sm),
32 splitmix64(&mut sm),
33 splitmix64(&mut sm),
34 splitmix64(&mut sm),
35 ],
36 }
37 }
38
39 pub fn next_u64(&mut self) -> u64 {
41 let result = self.s[1].wrapping_mul(5).rotate_left(7).wrapping_mul(9);
42 let t = self.s[1] << 17;
43 self.s[2] ^= self.s[0];
44 self.s[3] ^= self.s[1];
45 self.s[1] ^= self.s[2];
46 self.s[0] ^= self.s[3];
47 self.s[2] ^= t;
48 self.s[3] = self.s[3].rotate_left(45);
49 result
50 }
51
52 pub fn f64(&mut self) -> f64 {
54 (self.next_u64() >> 11) as f64 * (1.0 / (1u64 << 53) as f64)
55 }
56
57 pub fn below(&mut self, n: u32) -> u32 {
59 debug_assert!(n > 0);
60 (self.next_u64() % n as u64) as u32
61 }
62
63 pub fn range_i32(&mut self, lo: i32, hi: i32) -> i32 {
65 debug_assert!(lo <= hi);
66 lo + self.below((hi - lo + 1) as u32) as i32
67 }
68
69 pub fn normal(&mut self, mu: f64, sigma: f64) -> f64 {
72 let u1 = self.f64().max(f64::MIN_POSITIVE);
73 let u2 = self.f64();
74 let z = (-2.0 * u1.ln()).sqrt() * (std::f64::consts::TAU * u2).cos();
75 mu + sigma * z
76 }
77
78 pub fn poisson(&mut self, lambda: f64) -> u32 {
80 let l = (-lambda).exp();
81 let mut k = 0u32;
82 let mut p = 1.0f64;
83 loop {
84 p *= self.f64();
85 if p <= l {
86 return k;
87 }
88 k += 1;
89 if k > 30 {
90 return 30; }
92 }
93 }
94
95 pub fn shuffle<T>(&mut self, slice: &mut [T]) {
97 for i in (1..slice.len()).rev() {
98 let j = self.below((i + 1) as u32) as usize;
99 slice.swap(i, j);
100 }
101 }
102}
103
104pub fn derive_stream(seed: u64, tag: u64) -> Rng {
107 let mut sm = seed ^ tag.wrapping_mul(0xA24B_AED4_963E_E407);
108 let mixed = splitmix64(&mut sm);
109 Rng::seed_from(mixed)
110}
111
112#[cfg(test)]
113mod tests {
114 use super::*;
115
116 #[test]
117 fn same_seed_same_sequence() {
118 let mut a = Rng::seed_from(42);
119 let mut b = Rng::seed_from(42);
120 for _ in 0..1000 {
121 assert_eq!(a.next_u64(), b.next_u64());
122 }
123 }
124
125 #[test]
126 fn derived_streams_are_independent_of_consumption_order() {
127 let mut s1 = derive_stream(7, 100);
128 let _burn: u64 = (0..500)
129 .map(|_| derive_stream(7, 99).next_u64())
130 .fold(0u64, |acc, x| acc.wrapping_add(x));
131 let mut s2 = derive_stream(7, 100);
132 for _ in 0..100 {
133 assert_eq!(s1.next_u64(), s2.next_u64());
134 }
135 }
136}