const MULTIPLIER: u64 = 15750249268501108917;
use core::{convert::Infallible, fmt};
use rand_core::{SeedableRng, TryRng, utils};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[derive(Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Lcg128CmDxsm64 {
state: u128,
increment: u128,
}
pub type Pcg64Dxsm = Lcg128CmDxsm64;
impl Lcg128CmDxsm64 {
#[inline]
pub fn advance(&mut self, delta: u128) {
let mut acc_mult: u128 = 1;
let mut acc_plus: u128 = 0;
let mut cur_mult = MULTIPLIER as u128;
let mut cur_plus = self.increment;
let mut mdelta = delta;
while mdelta > 0 {
if (mdelta & 1) != 0 {
acc_mult = acc_mult.wrapping_mul(cur_mult);
acc_plus = acc_plus.wrapping_mul(cur_mult).wrapping_add(cur_plus);
}
cur_plus = cur_mult.wrapping_add(1).wrapping_mul(cur_plus);
cur_mult = cur_mult.wrapping_mul(cur_mult);
mdelta /= 2;
}
self.state = acc_mult.wrapping_mul(self.state).wrapping_add(acc_plus);
}
pub fn new(state: u128, stream: u128) -> Self {
let increment = (stream << 1) | 1;
Self::from_state_incr(state, increment)
}
#[inline]
fn from_state_incr(state: u128, increment: u128) -> Self {
let mut pcg = Self { state, increment };
pcg.state = pcg.state.wrapping_add(pcg.increment);
pcg.step();
pcg
}
#[inline(always)]
fn step(&mut self) {
self.state = self
.state
.wrapping_mul(MULTIPLIER as u128)
.wrapping_add(self.increment);
}
}
crate::macros::impl_state_stream!(Lcg128CmDxsm64, u128);
impl fmt::Debug for Lcg128CmDxsm64 {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Lcg128CmDxsm64 {{}}")
}
}
impl SeedableRng for Lcg128CmDxsm64 {
type Seed = [u8; 32];
fn from_seed(seed: Self::Seed) -> Self {
let seed_u64: [u64; 4] = utils::read_words(&seed);
let state = u128::from(seed_u64[0]) | (u128::from(seed_u64[1]) << 64);
let incr = u128::from(seed_u64[2]) | (u128::from(seed_u64[3]) << 64);
Self::from_state_incr(state, incr | 1)
}
}
impl TryRng for Lcg128CmDxsm64 {
type Error = Infallible;
#[inline]
fn try_next_u32(&mut self) -> Result<u32, Infallible> {
self.try_next_u64().map(|result| result as u32)
}
#[inline]
fn try_next_u64(&mut self) -> Result<u64, Infallible> {
let res = output_dxsm(self.state);
self.step();
Ok(res)
}
#[inline]
fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Infallible> {
utils::fill_bytes_via_next_word(dest, || self.try_next_u64())
}
}
#[inline(always)]
fn output_dxsm(state: u128) -> u64 {
let mut hi = (state >> 64) as u64;
let mut lo = state as u64;
lo |= 1;
hi ^= hi >> 32;
hi = hi.wrapping_mul(MULTIPLIER);
hi ^= hi >> 48;
hi = hi.wrapping_mul(lo);
hi
}