use crate::numeric::Float;
#[derive(Clone, Debug)]
pub(crate) struct SmallRng {
state: u64,
spare: Option<f64>,
}
impl SmallRng {
pub(crate) fn new(seed: u64) -> Self {
Self {
state: seed ^ 0x9e37_79b9_7f4a_7c15,
spare: None,
}
}
fn next_u64(&mut self) -> u64 {
self.state = self
.state
.wrapping_mul(6364136223846793005)
.wrapping_add(1442695040888963407);
self.state
}
pub(crate) fn uniform<T: Float>(&mut self) -> T {
let value = (self.next_u64() >> 11) as f64 * (1.0 / ((1u64 << 53) as f64));
T::from_f64(value)
}
pub(crate) fn normal<T: Float>(&mut self) -> T {
if let Some(spare) = self.spare.take() {
return T::from_f64(spare);
}
let u1 = (self.uniform::<f64>()).max(f64::MIN_POSITIVE);
let u2 = self.uniform::<f64>();
let radius = (-2.0 * u1.ln()).sqrt();
let theta = core::f64::consts::TAU * u2;
self.spare = Some(radius * theta.sin());
T::from_f64(radius * theta.cos())
}
}