1pub fn mix_seed(seed: u64, id: u64) -> u64 {
19 let mut z = seed ^ id.wrapping_mul(0x9E37_79B9_7F4A_7C15);
20 z = (z ^ (z >> 30)).wrapping_mul(0xBF58_476D_1CE4_E5B9);
21 z = (z ^ (z >> 27)).wrapping_mul(0x94D0_49BB_1331_11EB);
22 z ^ (z >> 31)
23}
24
25#[derive(Clone, Debug)]
27pub struct Rng {
28 state: u64,
29}
30
31impl Rng {
32 pub fn new(seed: u64) -> Self {
34 Rng { state: seed }
35 }
36
37 pub fn split(seed: u64, id: u64) -> Self {
43 Rng::new(mix_seed(seed, id))
44 }
45
46 #[inline]
47 fn next_u64(&mut self) -> u64 {
48 self.state = self.state.wrapping_add(0x9E37_79B9_7F4A_7C15);
49 let mut z = self.state;
50 z = (z ^ (z >> 30)).wrapping_mul(0xBF58_476D_1CE4_E5B9);
51 z = (z ^ (z >> 27)).wrapping_mul(0x94D0_49BB_1331_11EB);
52 z ^ (z >> 31)
53 }
54
55 #[inline]
57 pub fn uniform(&mut self) -> f64 {
58 (self.next_u64() >> 11) as f64 / (1u64 << 53) as f64
59 }
60
61 #[inline]
63 pub fn uniform_in(&mut self, lo: f64, hi: f64) -> f64 {
64 lo + (hi - lo) * self.uniform()
65 }
66
67 #[inline]
69 pub fn normal(&mut self) -> f64 {
70 let u1 = (1.0 - self.uniform()).max(f64::MIN_POSITIVE); let u2 = self.uniform();
72 (-2.0 * u1.ln()).sqrt() * (2.0 * std::f64::consts::PI * u2).cos()
73 }
74
75 #[inline]
77 pub fn index(&mut self, bound: usize) -> usize {
78 debug_assert!(bound > 0);
79 (self.next_u64() % bound as u64) as usize
80 }
81}
82
83#[cfg(test)]
84mod tests {
85 use super::*;
86
87 #[test]
88 fn deterministic() {
89 let mut a = Rng::new(123);
90 let mut b = Rng::new(123);
91 for _ in 0..1000 {
92 assert_eq!(a.next_u64(), b.next_u64());
93 }
94 }
95
96 #[test]
97 fn uniform_in_range() {
98 let mut r = Rng::new(7);
99 for _ in 0..10_000 {
100 let x = r.uniform();
101 assert!((0.0..1.0).contains(&x));
102 }
103 }
104
105 #[test]
106 fn index_in_range() {
107 let mut r = Rng::new(9);
108 for _ in 0..10_000 {
109 assert!(r.index(13) < 13);
110 }
111 }
112
113 #[test]
115 fn split_streams_are_independent_and_reproducible() {
116 let mut s0a = Rng::split(42, 0);
117 let mut s0b = Rng::split(42, 0);
118 let mut s1 = Rng::split(42, 1);
119 assert_eq!(s0a.next_u64(), s0b.next_u64());
121 let a: Vec<u64> = (0..8).map(|_| s0a.next_u64()).collect();
123 let b: Vec<u64> = (0..8).map(|_| s1.next_u64()).collect();
124 assert_ne!(a, b);
125 }
126
127 #[test]
129 fn normal_is_roughly_standard() {
130 let mut r = Rng::new(2024);
131 let n = 100_000;
132 let mut mean = 0.0;
133 let mut m2 = 0.0;
134 for k in 1..=n {
135 let x = r.normal();
136 let d = x - mean;
137 mean += d / k as f64;
138 m2 += d * (x - mean);
139 }
140 let var = m2 / (n as f64 - 1.0);
141 assert!(mean.abs() < 0.02, "mean {mean}");
142 assert!((var - 1.0).abs() < 0.05, "var {var}");
143 }
144}