pbrt/shared/src/utils/rng.rs

73 lines
1.9 KiB
Rust

#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct Rng {
pub state: u64,
pub inc: u64,
}
impl Default for Rng {
fn default() -> Self {
Self {
state: 0x853c49e6748fea9b,
inc: 0xda3e39cb94b95bdb,
}
}
}
impl Rng {
pub fn set_sequence(&mut self, init_seq: u64) {
self.state = 0;
self.inc = (init_seq << 1) | 1;
self.uniform_u32(); // Warm up
// PCG32_DEFAULT_STATE
self.state = self.state.wrapping_add(0x853c49e6748fea9b);
self.uniform_u32();
}
pub fn set_sequence_with_offset(&mut self, sequence_index: u64, offset: u64) {
self.state = 0;
self.inc = (sequence_index << 1) | 1;
self.uniform_u32();
self.state = self.state.wrapping_add(offset);
self.uniform_u32();
}
pub fn new(sequence_index: u64) -> Self {
let mut rng = Self { state: 0, inc: 0 };
rng.set_sequence(sequence_index);
rng
}
pub fn new_with_offset(sequence_index: u64, offset: u64) -> Self {
let mut rng = Self { state: 0, inc: 0 };
rng.set_sequence_with_offset(sequence_index, offset);
rng
}
pub fn advance(&mut self, delta: u64) {
// TODO: Implementation of PCG32 advance/seek
for _ in 0..delta {
self.uniform_u32();
}
}
pub fn uniform<T>(&mut self) -> T
where
T: From<f32>,
{
// Convert u32 to float [0,1)
let v = self.uniform_u32();
let f = (v as f32) * 2.3283064365386963e-10; // 1 / 2^32
T::from(f)
}
fn uniform_u32(&mut self) -> u32 {
let oldstate = self.state;
self.state = oldstate
.wrapping_mul(6364136223846793005)
.wrapping_add(self.inc);
let xorshifted = (((oldstate >> 18) ^ oldstate) >> 27) as u32;
let rot = (oldstate >> 59) as u32;
(xorshifted >> rot) | (xorshifted << ((0u32.wrapping_sub(rot)) & 31))
}
}