use crate::{Rng, TryRng};
pub trait SeedableRng: Sized {
type Seed: Clone + Default + AsRef<[u8]> + AsMut<[u8]>;
fn from_seed(seed: Self::Seed) -> Self;
fn seed_from_u64(mut state: u64) -> Self {
let mut seed = Self::Seed::default();
let mut iter = seed.as_mut().chunks_exact_mut(4);
for chunk in &mut iter {
chunk.copy_from_slice(&pcg32(&mut state));
}
let rem = iter.into_remainder();
if !rem.is_empty() {
rem.copy_from_slice(&pcg32(&mut state)[..rem.len()]);
}
Self::from_seed(seed)
}
fn from_rng<R: Rng + ?Sized>(rng: &mut R) -> Self {
let mut seed = Self::Seed::default();
rng.fill_bytes(seed.as_mut());
Self::from_seed(seed)
}
fn try_from_rng<R: TryRng + ?Sized>(rng: &mut R) -> Result<Self, R::Error> {
let mut seed = Self::Seed::default();
rng.try_fill_bytes(seed.as_mut())?;
Ok(Self::from_seed(seed))
}
fn fork(&mut self) -> Self
where
Self: Rng,
{
Self::from_rng(self)
}
fn try_fork(&mut self) -> Result<Self, Self::Error>
where
Self: TryRng,
{
Self::try_from_rng(self)
}
}
fn pcg32(state: &mut u64) -> [u8; 4] {
const MUL: u64 = 0x5851_F42D_4C95_7F2D;
const INC: u64 = 0xA176_54E4_6FBE_17F3;
*state = state.wrapping_mul(MUL).wrapping_add(INC);
let state = *state;
let xorshifted = (((state >> 18) ^ state) >> 27) as u32;
let rot = (state >> 59) as u32;
let x = xorshifted.rotate_right(rot);
x.to_le_bytes()
}