use super::*;
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[repr(transparent)]
pub struct SplitMix64 {
state: u64,
}
impl SplitMix64 {
#[inline]
pub fn new() -> Random<SplitMix64> {
let state = util::getrandom();
Random::wrap(SplitMix64 { state })
}
#[inline]
pub fn from_rng<R: Rng + ?Sized>(rand: &mut Random<R>) -> Random<SplitMix64> {
Random::wrap(SplitMix64 { state: rand.next_u64() })
}
#[inline]
pub fn from_seed(seed: u64) -> Random<SplitMix64> {
Random::wrap(SplitMix64 { state: seed })
}
}
impl Rng for SplitMix64 {
#[inline]
fn next_u32(&mut self) -> u32 {
(next(&mut self.state) >> 32) as u32
}
#[inline]
fn next_u64(&mut self) -> u64 {
next(&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(SplitMix64::new());
tests::check_serde_middle_state(SplitMix64::new());
}
const GOLDEN_GAMMA: u64 = 0x9e3779b97f4a7c15;
#[inline]
fn next(x: &mut u64) -> u64 {
*x = x.wrapping_add(GOLDEN_GAMMA);
mix64(*x)
}
#[inline]
fn jump(x: &mut u64) {
*x = x.wrapping_add(GOLDEN_GAMMA << 40);
}
#[inline]
fn mix64(mut z: u64) -> u64 {
z = (z ^ (z >> 30)).wrapping_mul(0xbf58476d1ce4e5b9);
z = (z ^ (z >> 27)).wrapping_mul(0x94d049bb133111eb);
return z ^ (z >> 31);
}