use super::*;
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[repr(transparent)]
pub struct Wyrand {
state: u64,
}
impl Wyrand {
#[inline]
pub fn new() -> Random<Wyrand> {
let state = util::getrandom();
Random::wrap(Wyrand { state })
}
#[inline]
pub fn from_rng<R: Rng + ?Sized>(rand: &mut Random<R>) -> Random<Wyrand> {
Random::wrap(Wyrand { state: rand.next_u64() })
}
#[inline]
pub fn from_seed(seed: u64) -> Random<Wyrand> {
Random::wrap(Wyrand { state: seed })
}
}
impl Rng for Wyrand {
#[inline]
fn next_u32(&mut self) -> u32 {
(wyrand(&mut self.state) >> 32) as u32
}
#[inline]
fn next_u64(&mut self) -> u64 {
wyrand(&mut self.state)
}
#[inline(never)]
fn fill_bytes(&mut self, buf: &mut [MaybeUninit<u8>]) {
let mut rng = self.clone();
util::rng_fill_bytes(&mut rng, buf);
*self = rng;
}
#[inline]
fn jump(&mut self) {
jump(&mut self.state)
}
}
#[cfg(feature = "serde")]
#[test]
fn serde() {
tests::check_serde_initial_state(Wyrand::new());
tests::check_serde_middle_state(Wyrand::new());
}
#[inline(always)]
fn rapid_mum(a: u64, b: u64) -> (u64, u64) {
let r = a as u128 * b as u128;
(r as u64, (r >> 64) as u64)
}
#[inline(always)]
fn rapid_mix(a: u64, b: u64) -> u64 {
let (a, b) = rapid_mum(a, b);
a ^ b
}
const P0: u64 = 0x2d358dccaa6c78a5;
const P1: u64 = 0x8bb84b93962eacc9;
#[inline]
fn wyrand(seed: &mut u64) -> u64 {
*seed = seed.wrapping_add(P0);
rapid_mix(*seed ^ P1, *seed)
}
#[inline]
fn jump(seed: &mut u64) {
*seed = seed.wrapping_add(P0 << 40);
}