pub trait RandomSource {
fn next_u32(&mut self) -> u32;
fn next_u64(&mut self) -> u64 {
((self.next_u32() as u64) << 32) | (self.next_u32() as u64)
}
fn next_unit_f64(&mut self) -> f64 {
(self.next_u64() >> 11) as f64 * (1.0 / (1u64 << 53) as f64)
}
fn standard_normal(&mut self) -> f64 {
let mut first = self.next_unit_f64();
if first <= f64::MIN_POSITIVE {
first = f64::MIN_POSITIVE;
}
let second = self.next_unit_f64();
libm::sqrt(-2.0 * libm::log(first)) * libm::cos(core::f64::consts::TAU * second)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Pcg32 {
state: u64,
increment: u64,
}
impl Pcg32 {
#[must_use]
pub fn new(seed: u64) -> Self {
Self::with_stream(seed, DEFAULT_STREAM)
}
#[must_use]
pub fn with_stream(seed: u64, stream: u64) -> Self {
let mut generator = Pcg32 {
state: 0,
increment: (stream << 1) | 1,
};
let _ = generator.next_u32();
generator.state = generator.state.wrapping_add(seed);
let _ = generator.next_u32();
generator
}
}
impl RandomSource for Pcg32 {
fn next_u32(&mut self) -> u32 {
let previous = self.state;
self.state = previous
.wrapping_mul(PCG_MULTIPLIER)
.wrapping_add(self.increment);
let xorshifted = (((previous >> 18) ^ previous) >> 27) as u32;
let rotation = (previous >> 59) as u32;
xorshifted.rotate_right(rotation)
}
}
const PCG_MULTIPLIER: u64 = 6364136223846793005;
const DEFAULT_STREAM: u64 = 0xda3e_39cb_94b9_5bdb;