const MULTIPLIER: u128 = 0x2360_ED05_1FC6_5DA4_4385_DF64_9FCC_F645;
use core::fmt;
use rand_core::{Infallible, SeedableRng, TryRng, utils};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[derive(Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Lcg128Xsl64 {
state: u128,
increment: u128,
}
pub type Pcg64 = Lcg128Xsl64;
impl Lcg128Xsl64 {
#[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;
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;
Lcg128Xsl64::from_state_incr(state, increment)
}
#[inline]
fn from_state_incr(state: u128, increment: u128) -> Self {
let mut pcg = Lcg128Xsl64 { state, increment };
pcg.state = pcg.state.wrapping_add(pcg.increment);
pcg.step();
pcg
}
#[inline]
fn step(&mut self) {
self.state = self
.state
.wrapping_mul(MULTIPLIER)
.wrapping_add(self.increment);
}
}
crate::macros::impl_state_stream!(Lcg128Xsl64, u128);
impl fmt::Debug for Lcg128Xsl64 {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Lcg128Xsl64 {{}}")
}
}
impl SeedableRng for Lcg128Xsl64 {
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);
Lcg128Xsl64::from_state_incr(state, incr | 1)
}
}
impl TryRng for Lcg128Xsl64 {
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> {
self.step();
Ok(output_xsl_rr(self.state))
}
#[inline]
fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Infallible> {
utils::fill_bytes_via_next_word(dest, || self.try_next_u64())
}
}
#[derive(Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Mcg128Xsl64 {
state: u128,
}
pub type Pcg64Mcg = Mcg128Xsl64;
impl Mcg128Xsl64 {
#[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;
let mut cur_plus: u128 = 0;
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) -> Self {
Mcg128Xsl64 { state: state | 1 }
}
pub fn state(&self) -> u128 {
self.state
}
}
impl fmt::Debug for Mcg128Xsl64 {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Mcg128Xsl64 {{}}")
}
}
impl SeedableRng for Mcg128Xsl64 {
type Seed = [u8; 16];
fn from_seed(seed: Self::Seed) -> Self {
let seed_u64: [u64; 2] = utils::read_words(&seed);
let state = u128::from(seed_u64[0]) | (u128::from(seed_u64[1]) << 64);
Mcg128Xsl64::new(state)
}
}
impl TryRng for Mcg128Xsl64 {
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> {
self.state = self.state.wrapping_mul(MULTIPLIER);
Ok(output_xsl_rr(self.state))
}
#[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_xsl_rr(state: u128) -> u64 {
const XSHIFT: u32 = 64; const ROTATE: u32 = 122;
let rot = (state >> ROTATE) as u32;
let xsl = ((state >> XSHIFT) as u64) ^ (state as u64);
xsl.rotate_right(rot)
}