pub(crate) trait JitterRng {
fn uniform_f64(&mut self, lo: f64, hi: f64) -> f64;
}
pub(crate) struct SeededRng {
state: u64,
}
impl SeededRng {
pub(crate) fn new() -> Self {
let seed = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.map(|d| d.as_nanos() as u64)
.unwrap_or(0x123456789ABCDEF);
Self { state: seed }
}
#[cfg(test)]
pub(crate) fn from_seed(seed: u64) -> Self {
Self { state: seed.max(1) }
}
fn next_u64(&mut self) -> u64 {
self.state ^= self.state << 13;
self.state ^= self.state >> 7;
self.state ^= self.state << 17;
self.state.wrapping_mul(0x2545_F491_4F6C_DD1D)
}
}
impl JitterRng for SeededRng {
fn uniform_f64(&mut self, lo: f64, hi: f64) -> f64 {
let range = hi - lo;
let fraction = (self.next_u64() as f64) / (u64::MAX as f64);
lo + fraction * range
}
}