#[derive(Debug, Clone)]
pub struct Pcg32 {
state: u64,
inc: u64,
}
impl Pcg32 {
#[must_use]
pub fn new(seed: u64, stream: u64) -> Self {
let mut rng = Self {
state: 0,
inc: (stream << 1) | 1,
};
rng.next_u32();
rng.state = rng.state.wrapping_add(seed);
rng.next_u32();
rng
}
#[inline]
pub fn next_u32(&mut self) -> u32 {
let old_state = self.state;
self.state = old_state
.wrapping_mul(6364136223846793005)
.wrapping_add(self.inc);
let xor_shifted = (((old_state >> 18) ^ old_state) >> 27) as u32;
let rot = (old_state >> 59) as u32;
(xor_shifted >> rot) | (xor_shifted << (rot.wrapping_neg() & 31))
}
#[inline]
pub fn next_f64(&mut self) -> f64 {
(self.next_u32() as f64) / (u32::MAX as f64 + 1.0)
}
#[inline]
pub fn next_f32(&mut self) -> f32 {
(self.next_u32() as f32) / (u32::MAX as f32 + 1.0)
}
#[inline]
pub fn next_f64_range(&mut self, lo: f64, hi: f64) -> f64 {
lo + (hi - lo) * self.next_f64()
}
#[inline]
pub fn next_normal(&mut self) -> f64 {
let u1 = self.next_f64().max(1e-300); let u2 = self.next_f64();
(-2.0 * u1.ln()).sqrt() * (std::f64::consts::TAU * u2).cos()
}
}
#[must_use]
#[inline]
pub fn halton(index: u32, base: u32) -> f64 {
let mut result = 0.0;
let mut f = 1.0 / base as f64;
let mut i = index;
while i > 0 {
result += f * (i % base) as f64;
i /= base;
f /= base as f64;
}
result
}
#[must_use]
#[inline]
pub fn halton_2d(index: u32) -> (f64, f64) {
(halton(index, 2), halton(index, 3))
}
#[must_use]
#[inline]
pub fn sobol(index: u32) -> f64 {
let mut n = index;
n ^= n >> 1;
n = ((n & 0xAAAAAAAA) >> 1) | ((n & 0x55555555) << 1);
n = ((n & 0xCCCCCCCC) >> 2) | ((n & 0x33333333) << 2);
n = ((n & 0xF0F0F0F0) >> 4) | ((n & 0x0F0F0F0F) << 4);
n = ((n & 0xFF00FF00) >> 8) | ((n & 0x00FF00FF) << 8);
n = n.rotate_left(16);
n as f64 / (1u64 << 32) as f64
}