73 lines
1.9 KiB
Rust
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))
|
|
}
|
|
}
|