use rand::SeedableRng;
use rand_core::{impls, RngCore};
#[derive(Default)]
pub struct MinimalPCG32 {
state: u64,
inc: u64,
}
impl RngCore for MinimalPCG32 {
fn next_u32(&mut self) -> u32 {
let old_state = self.state;
self.state = old_state
.wrapping_mul(6364136223846793005_u64)
.wrapping_add(self.inc);
let xorshifted = ((old_state >> 18) ^ old_state) >> 27;
let rot = (old_state >> 59) as u32;
xorshifted.rotate_right(rot) as u32
}
fn next_u64(&mut self) -> u64 {
self.next_u32() as u64
}
fn fill_bytes(&mut self, dest: &mut [u8]) {
impls::fill_bytes_via_next(self, dest)
}
}
impl SeedableRng for MinimalPCG32 {
type Seed = [u8; 8];
fn from_seed(seed: Self::Seed) -> Self {
const INCREMENT: u64 = 3215534235932367344;
Self {
state: (u64::from_le_bytes(seed)).wrapping_add(INCREMENT),
inc: INCREMENT,
}
}
}
#[cfg(test)]
mod pcg_tests {
use super::*;
#[test]
fn two_seed() {
let mut two_seed = MinimalPCG32::from_seed(2u64.to_le_bytes());
assert_eq!(two_seed.next_u64(), 748672126);
assert_eq!(two_seed.next_u64(), 733451027);
assert_eq!(two_seed.next_u64(), 448);
assert_eq!(two_seed.next_u64(), 1074309680);
assert_eq!(two_seed.next_u64(), 2005882);
}
#[test]
fn seventy_three_seed() {
let mut seventy_three_seed = MinimalPCG32::from_seed(73u64.to_le_bytes());
assert_eq!(seventy_three_seed.next_u64(), 748672126);
assert_eq!(seventy_three_seed.next_u64(), 43634);
assert_eq!(seventy_three_seed.next_u64(), 1687);
assert_eq!(seventy_three_seed.next_u64(), 775788185);
assert_eq!(seventy_three_seed.next_u64(), 752437086);
}
}