#[derive(Debug, Clone)]
pub struct AugRng {
state: u64,
}
impl AugRng {
pub fn new(seed: u64) -> Self {
let state = seed.wrapping_add(0x9e37_79b9_7f4a_7c15);
Self { state }
}
#[inline]
fn next_u64(&mut self) -> u64 {
self.state = self
.state
.wrapping_mul(6_364_136_223_846_793_005)
.wrapping_add(1_442_695_040_888_963_407);
self.state
}
pub fn next_f64(&mut self) -> f64 {
let bits = self.next_u64() >> 11;
(bits as f64) * (1.0 / (1u64 << 53) as f64)
}
pub fn next_normal(&mut self) -> f64 {
let u1 = (self.next_f64() + 1e-300).min(1.0); let u2 = self.next_f64();
(-2.0 * u1.ln()).sqrt() * (2.0 * std::f64::consts::PI * u2).cos()
}
pub fn next_bool(&mut self, p: f64) -> bool {
self.next_f64() < p
}
pub fn next_usize(&mut self, max: usize) -> usize {
if max == 0 {
return 0;
}
(self.next_u64() as usize) % max
}
}
pub(crate) fn sample_beta_symmetric(alpha: f64, rng: &mut AugRng) -> f64 {
if (alpha - 1.0).abs() < 1e-9 {
rng.next_f64()
} else {
let sigma = 0.5 / (2.0 * alpha).sqrt();
let z = rng.next_normal();
(0.5 + z * sigma).clamp(0.0, 1.0)
}
}