#[derive(Clone, Debug)]
pub(crate) struct Rng {
state: u64,
}
impl Rng {
#[inline]
pub(crate) fn new(seed: u64) -> Self {
Self { state: seed }
}
#[inline]
pub(crate) fn next_u64(&mut self) -> u64 {
self.state = self.state.wrapping_add(0x9E37_79B9_7F4A_7C15);
let mut z = self.state;
z = (z ^ (z >> 30)).wrapping_mul(0xBF58_476D_1CE4_E5B9);
z = (z ^ (z >> 27)).wrapping_mul(0x94D0_49BB_1331_11EB);
z ^ (z >> 31)
}
#[inline]
pub(crate) fn gen_range(&mut self, min: u32, max: u32) -> u32 {
if max <= min {
return min;
}
let span = u64::from(max - min) + 1;
min + (self.next_u64() % span) as u32
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_same_seed_yields_same_stream() {
let mut a = Rng::new(42);
let mut b = Rng::new(42);
for _ in 0..32 {
assert_eq!(a.next_u64(), b.next_u64());
}
}
#[test]
fn test_different_seeds_diverge() {
let mut a = Rng::new(1);
let mut b = Rng::new(2);
assert_ne!(a.next_u64(), b.next_u64());
}
#[test]
fn test_gen_range_stays_within_bounds() {
let mut r = Rng::new(7);
for _ in 0..10_000 {
let v = r.gen_range(150, 300);
assert!((150..=300).contains(&v));
}
}
#[test]
fn test_gen_range_degenerate_returns_min() {
let mut r = Rng::new(7);
assert_eq!(r.gen_range(10, 10), 10);
assert_eq!(r.gen_range(10, 5), 10);
}
#[test]
fn test_gen_range_covers_both_endpoints() {
let mut r = Rng::new(99);
let mut seen_min = false;
let mut seen_max = false;
for _ in 0..10_000 {
match r.gen_range(0, 3) {
0 => seen_min = true,
3 => seen_max = true,
_ => {}
}
}
assert!(seen_min && seen_max);
}
}