mod pcg64;
mod philox;
mod xoshiro256;
pub(crate) fn splitmix64(state: &mut u64) -> u64 {
*state = state.wrapping_add(0x9e37_79b9_7f4a_7c15);
let mut z = *state;
z = (z ^ (z >> 30)).wrapping_mul(0xbf58_476d_1ce4_e5b9);
z = (z ^ (z >> 27)).wrapping_mul(0x94d0_49bb_1331_11eb);
z ^ (z >> 31)
}
pub use pcg64::Pcg64;
pub use philox::Philox;
pub use xoshiro256::Xoshiro256StarStar;
pub trait BitGenerator: Send {
fn next_u64(&mut self) -> u64;
fn seed_from_u64(seed: u64) -> Self
where
Self: Sized;
fn jump(&mut self) -> Option<()>;
fn stream(seed: u64, stream_id: u64) -> Option<Self>
where
Self: Sized;
fn next_f64(&mut self) -> f64 {
(self.next_u64() >> 11) as f64 * (1.0 / (1u64 << 53) as f64)
}
fn next_f32(&mut self) -> f32 {
(self.next_u64() >> 40) as f32 * (1.0 / (1u64 << 24) as f32)
}
fn fill_bytes(&mut self, dest: &mut [u8]) {
let mut i = 0;
while i + 8 <= dest.len() {
let val = self.next_u64();
dest[i..i + 8].copy_from_slice(&val.to_le_bytes());
i += 8;
}
if i < dest.len() {
let val = self.next_u64();
let bytes = val.to_le_bytes();
for (j, byte) in dest[i..].iter_mut().enumerate() {
*byte = bytes[j];
}
}
}
fn next_u64_bounded(&mut self, bound: u64) -> u64 {
if bound == 0 {
return 0;
}
let mut x = self.next_u64();
let mut m = (x as u128) * (bound as u128);
let mut l = m as u64;
if l < bound {
let threshold = bound.wrapping_neg() % bound;
while l < threshold {
x = self.next_u64();
m = (x as u128) * (bound as u128);
l = m as u64;
}
}
(m >> 64) as u64
}
}