use core::convert::Infallible;
use rand::rand_core::{SeedableRng, TryRng};
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[cfg_attr(
feature = "serde",
derive(serde::Serialize, serde::Deserialize)
)]
pub struct Pcg32 {
state: u64,
inc: u64,
}
const PCG32_MULT: u64 = 6_364_136_223_846_793_005;
const PCG32_DEFAULT_INC: u64 = 1_442_695_040_888_963_407;
impl Pcg32 {
pub fn from_seed_stream(seed: u64, stream: u64) -> Self {
let mut rng = Self {
state: 0,
inc: (stream << 1) | 1,
};
let _ = rng.next_u32();
rng.state = rng.state.wrapping_add(seed);
let _ = rng.next_u32();
rng
}
pub fn from_u64_seed(seed: u64) -> Self {
Self::from_seed_stream(seed, PCG32_DEFAULT_INC)
}
#[inline]
pub fn next_u32(&mut self) -> u32 {
let old = self.state;
self.state =
old.wrapping_mul(PCG32_MULT).wrapping_add(self.inc);
let xorshifted = (((old >> 18) ^ old) >> 27) as u32;
let rot = (old >> 59) as u32;
xorshifted.rotate_right(rot)
}
#[inline]
pub fn next_u64(&mut self) -> u64 {
let lo = u64::from(self.next_u32());
let hi = u64::from(self.next_u32());
(hi << 32) | lo
}
pub fn fill_bytes(&mut self, dest: &mut [u8]) {
let mut i = 0;
while i + 4 <= dest.len() {
let bytes = self.next_u32().to_le_bytes();
dest[i..i + 4].copy_from_slice(&bytes);
i += 4;
}
if i < dest.len() {
let bytes = self.next_u32().to_le_bytes();
let remaining = dest.len() - i;
dest[i..].copy_from_slice(&bytes[..remaining]);
}
}
}
impl TryRng for Pcg32 {
type Error = Infallible;
fn try_next_u32(&mut self) -> Result<u32, Self::Error> {
Ok(self.next_u32())
}
fn try_next_u64(&mut self) -> Result<u64, Self::Error> {
Ok(self.next_u64())
}
fn try_fill_bytes(
&mut self,
dest: &mut [u8],
) -> Result<(), Self::Error> {
self.fill_bytes(dest);
Ok(())
}
}
impl SeedableRng for Pcg32 {
type Seed = [u8; 16];
fn from_seed(seed: [u8; 16]) -> Self {
let state = u64::from_le_bytes([
seed[0], seed[1], seed[2], seed[3], seed[4], seed[5],
seed[6], seed[7],
]);
let stream = u64::from_le_bytes([
seed[8], seed[9], seed[10], seed[11], seed[12], seed[13],
seed[14], seed[15],
]);
Self::from_seed_stream(state, stream | 1)
}
}
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[cfg_attr(
feature = "serde",
derive(serde::Serialize, serde::Deserialize)
)]
pub struct Pcg64 {
state: u128,
inc: u128,
}
const PCG64_MULT: u128 = 0x2360_ED05_1FC6_5DA4_4385_DF64_9FCC_F645;
const PCG64_DEFAULT_INC: u128 =
0x5851_F42D_4C95_7F2D_1405_7B7E_F767_814F;
impl Pcg64 {
pub fn from_seed_stream(seed: u128, stream: u128) -> Self {
let mut rng = Self {
state: 0,
inc: (stream << 1) | 1,
};
let _ = rng.next_u64();
rng.state = rng.state.wrapping_add(seed);
let _ = rng.next_u64();
rng
}
pub fn from_u128_seed(seed: u128) -> Self {
Self::from_seed_stream(seed, PCG64_DEFAULT_INC)
}
#[inline]
pub fn next_u64(&mut self) -> u64 {
let old = self.state;
self.state =
old.wrapping_mul(PCG64_MULT).wrapping_add(self.inc);
let half = ((old >> 64) as u64) ^ (old as u64);
let rot = (old >> 122) as u32;
half.rotate_right(rot)
}
#[inline]
pub fn next_u32(&mut self) -> u32 {
(self.next_u64() >> 32) as u32
}
pub fn fill_bytes(&mut self, dest: &mut [u8]) {
let mut i = 0;
while i + 8 <= dest.len() {
let bytes = self.next_u64().to_le_bytes();
dest[i..i + 8].copy_from_slice(&bytes);
i += 8;
}
if i < dest.len() {
let bytes = self.next_u64().to_le_bytes();
let remaining = dest.len() - i;
dest[i..].copy_from_slice(&bytes[..remaining]);
}
}
}
impl TryRng for Pcg64 {
type Error = Infallible;
fn try_next_u32(&mut self) -> Result<u32, Self::Error> {
Ok(self.next_u32())
}
fn try_next_u64(&mut self) -> Result<u64, Self::Error> {
Ok(self.next_u64())
}
fn try_fill_bytes(
&mut self,
dest: &mut [u8],
) -> Result<(), Self::Error> {
self.fill_bytes(dest);
Ok(())
}
}
impl SeedableRng for Pcg64 {
type Seed = [u8; 32];
fn from_seed(seed: [u8; 32]) -> Self {
let state = u128::from_le_bytes([
seed[0], seed[1], seed[2], seed[3], seed[4], seed[5],
seed[6], seed[7], seed[8], seed[9], seed[10], seed[11],
seed[12], seed[13], seed[14], seed[15],
]);
let stream = u128::from_le_bytes([
seed[16], seed[17], seed[18], seed[19], seed[20], seed[21],
seed[22], seed[23], seed[24], seed[25], seed[26], seed[27],
seed[28], seed[29], seed[30], seed[31],
]);
Self::from_seed_stream(state, stream | 1)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn pcg32_deterministic() {
let mut a = Pcg32::from_u64_seed(42);
let mut b = Pcg32::from_u64_seed(42);
for _ in 0..16 {
assert_eq!(a.next_u32(), b.next_u32());
}
}
#[test]
fn pcg32_nonzero_from_zero_seed() {
let mut rng = Pcg32::from_u64_seed(0);
assert_ne!(rng.next_u32(), 0);
}
#[test]
fn pcg32_fill_bytes_unaligned() {
let mut rng = Pcg32::from_u64_seed(7);
let mut buf = [0u8; 17];
rng.fill_bytes(&mut buf);
assert!(buf.iter().any(|&b| b != 0));
}
#[test]
fn pcg64_deterministic() {
let mut a = Pcg64::from_u128_seed(0xDEAD_BEEF);
let mut b = Pcg64::from_u128_seed(0xDEAD_BEEF);
for _ in 0..16 {
assert_eq!(a.next_u64(), b.next_u64());
}
}
#[test]
fn pcg64_nonzero_from_zero_seed() {
let mut rng = Pcg64::from_u128_seed(0);
assert_ne!(rng.next_u64(), 0);
}
#[test]
fn pcg64_fill_bytes_unaligned() {
let mut rng = Pcg64::from_u128_seed(1);
let mut buf = [0u8; 33];
rng.fill_bytes(&mut buf);
assert!(buf.iter().any(|&b| b != 0));
}
#[test]
fn pcg32_try_rng_impl() {
let mut rng = Pcg32::from_u64_seed(1);
assert!(rng.try_next_u32().is_ok());
assert!(rng.try_next_u64().is_ok());
let mut buf = [0u8; 8];
assert!(rng.try_fill_bytes(&mut buf).is_ok());
}
#[test]
fn pcg64_try_rng_impl() {
let mut rng = Pcg64::from_u128_seed(1);
assert!(rng.try_next_u32().is_ok());
assert!(rng.try_next_u64().is_ok());
let mut buf = [0u8; 8];
assert!(rng.try_fill_bytes(&mut buf).is_ok());
}
#[test]
fn pcg32_seedable_rng() {
let seed = [3u8; 16];
let mut a = <Pcg32 as SeedableRng>::from_seed(seed);
let mut b = <Pcg32 as SeedableRng>::from_seed(seed);
assert_eq!(a.next_u32(), b.next_u32());
}
#[test]
fn pcg64_seedable_rng() {
let seed = [3u8; 32];
let mut a = <Pcg64 as SeedableRng>::from_seed(seed);
let mut b = <Pcg64 as SeedableRng>::from_seed(seed);
assert_eq!(a.next_u64(), b.next_u64());
}
}