1use std::ops::Range;
2
3#[derive(Clone, Debug)]
11pub struct Rng {
12 state: u64,
13}
14
15impl Rng {
16 pub const DEFAULT_SEED: u64 = 0x4d59_5df4_d0f3_3173;
18 const XORSHIFT64_STAR_MULTIPLIER: u64 = 0x2545_f491_4f6c_dd1d;
20 const F32_MANTISSA_BITS: u32 = 24;
22
23 pub const fn new(seed: u64) -> Self {
25 Self {
26 state: if seed == 0 { Self::DEFAULT_SEED } else { seed },
27 }
28 }
29
30 pub const fn reseed(&mut self, seed: u64) {
32 self.state = if seed == 0 { Self::DEFAULT_SEED } else { seed };
33 }
34
35 #[must_use]
37 pub fn next_u64(&mut self) -> u64 {
38 let mut x = self.state;
39 x ^= x >> 12;
40 x ^= x << 25;
41 x ^= x >> 27;
42 self.state = x;
43 x.wrapping_mul(Self::XORSHIFT64_STAR_MULTIPLIER)
44 }
45
46 #[must_use]
48 pub fn next_u32(&mut self) -> u32 {
49 (self.next_u64() >> 32) as u32
50 }
51
52 #[must_use]
58 pub fn range_u32(&mut self, range: Range<u32>) -> u32 {
59 assert!(range.start < range.end, "range must be non-empty");
60 range.start + self.uniform_below_u32(range.end - range.start)
61 }
62
63 #[must_use]
69 pub fn range_usize(&mut self, range: Range<usize>) -> usize {
70 assert!(range.start < range.end, "range must be non-empty");
71 range.start + self.uniform_below_usize(range.end - range.start)
72 }
73
74 #[must_use]
76 pub fn next_f32(&mut self) -> f32 {
77 const INV_2_POW_24: f32 = 1.0 / ((1u32 << Rng::F32_MANTISSA_BITS) as f32);
78 ((self.next_u32() >> (u32::BITS - Self::F32_MANTISSA_BITS)) as f32) * INV_2_POW_24
79 }
80
81 fn uniform_below_u32(&mut self, upper_exclusive: u32) -> u32 {
82 let zone = u32::MAX - (u32::MAX % upper_exclusive);
83 loop {
84 let value = self.next_u32();
85 if value < zone {
86 return value % upper_exclusive;
87 }
88 }
89 }
90
91 fn uniform_below_usize(&mut self, upper_exclusive: usize) -> usize {
92 let upper = upper_exclusive as u64;
96 let zone = u64::MAX - (u64::MAX % upper);
97 loop {
98 let value = self.next_u64();
99 if value < zone {
100 return (value % upper) as usize;
101 }
102 }
103 }
104}
105
106impl Default for Rng {
107 fn default() -> Self {
109 Self::new(Self::DEFAULT_SEED)
110 }
111}
112
113#[cfg(test)]
114mod tests {
115 use super::Rng;
116
117 #[test]
118 fn same_seed_same_sequence() {
119 let mut a = Rng::new(1337);
120 let mut b = Rng::new(1337);
121 for _ in 0..32 {
122 assert_eq!(a.next_u64(), b.next_u64());
123 }
124 }
125
126 #[test]
127 fn range_u32_stays_within_bounds() {
128 let mut rng = Rng::new(42);
129 for _ in 0..2000 {
130 let value = rng.range_u32(10..20);
131 assert!((10..20).contains(&value));
132 }
133 }
134
135 #[test]
136 fn range_usize_stays_within_bounds() {
137 let mut rng = Rng::new(7);
138 for _ in 0..2000 {
139 let value = rng.range_usize(3..9);
140 assert!((3..9).contains(&value));
141 }
142 }
143
144 #[test]
145 fn f32_is_in_zero_to_one() {
146 let mut rng = Rng::new(1);
147 for _ in 0..2000 {
148 let value = rng.next_f32();
149 assert!((0.0..1.0).contains(&value));
150 }
151 }
152
153 #[test]
154 fn reseed_restores_the_sequence() {
155 let mut rng = Rng::new(99);
156 let first: Vec<u64> = (0..8).map(|_| rng.next_u64()).collect();
157 rng.reseed(99);
158 let second: Vec<u64> = (0..8).map(|_| rng.next_u64()).collect();
159 assert_eq!(first, second);
160 }
161
162 #[test]
163 fn zero_seed_falls_back_to_default() {
164 assert_eq!(Rng::new(0).next_u64(), Rng::new(Rng::DEFAULT_SEED).next_u64());
166 assert_eq!(Rng::default().next_u64(), Rng::new(Rng::DEFAULT_SEED).next_u64());
167 }
168}