use std::ops::{Bound, RangeBounds};
use crate::prelude::*;
const INCREMENT: u64 = 1442695040888963407;
const MULTIPLIER: u64 = 6364136223846793005;
#[derive(Clone, Debug)]
pub struct Pcg {
state: u64,
}
impl Pcg {
pub fn fork(&mut self) -> Self {
Self::new(self.next_u32() as u64)
}
pub fn new(seed: u64) -> Self {
let mut rng = Self { state: 0 };
rng.state = rng.state.wrapping_add(INCREMENT);
rng.next_u32();
rng.state = rng.state.wrapping_add(seed);
rng.next_u32();
rng
}
pub fn next_f32(&mut self) -> f32 {
(self.next_u32() >> 8) as f32 / (1u32 << 24) as f32
}
pub fn next_u32(&mut self) -> u32 {
let old_state = self.state;
self.state = old_state.wrapping_mul(MULTIPLIER).wrapping_add(INCREMENT);
let xor_shifted = (((old_state >> 18) ^ old_state) >> 27) as u32;
let rot = (old_state >> 59) as u32;
xor_shifted.rotate_right(rot)
}
pub fn next_u32_range<R>(&mut self, r: R) -> Result<u32, ImgalError>
where
R: RangeBounds<u32>,
{
let start = match r.start_bound() {
Bound::Included(&s) => s,
Bound::Excluded(&s) => s.saturating_add(1),
Bound::Unbounded => 0,
};
let end = match r.end_bound() {
Bound::Included(&e) => e.saturating_add(1),
Bound::Excluded(&e) => e,
Bound::Unbounded => u32::MAX,
};
if start >= end {
return Err(ImgalError::InvalidPositiveRange {
start: start as usize,
end: end as usize,
});
}
let diff = end - start;
let threshold = diff.wrapping_neg() % diff;
loop {
let v = self.next_u32();
if v >= threshold {
return Ok(start + (v % diff));
}
}
}
}