pub mod xorwow64;
pub mod xorwow128;
use rand_core::impls::fill_bytes_via_next;
use rand_core::le::read_u32_into;
use rand_core::{Error, RngCore, SeedableRng};
use std::ops::BitXor;
#[cfg(feature = "serde1")]
use serde::{Deserialize, Serialize};
macro_rules! make_xorwow {
($(#[$meta:meta])*
$name: ident, $nr: expr) => (
$(#[$meta])*
#[derive(Debug, Clone, Eq, PartialEq)]
#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
pub struct $name {
s: [u32; $nr]
}
)
}
make_xorwow!(
Xorwow96, 4);
make_xorwow!(
Xorwow128, 5);
make_xorwow!(
Xorwow160, 6);
make_xorwow!(
XorwowXor96, 4);
make_xorwow!(
XorwowXor128, 5);
make_xorwow!(
XorwowXor160, 6);
macro_rules! impl_xorwow {
($name: ident, $mod: ident, $nr: expr, $shift: expr) => {
impl $name {
fn clock(&mut self) {
let mut x = self.s[$nr - 2];
let y = self.s[0];
for i in (2..($nr - 1)).rev() {
self.s[i] = self.s[i - 1];
}
self.s[1] = y;
x ^= x >> $shift.0;
x ^= x << $shift.1;
x ^= y ^ (y << $shift.2);
self.s[0] = x;
self.s[$nr - 1] = self.s[$nr - 1].wrapping_add(362437);
}
pub fn return_u32(&mut self) -> u32 {
self.clock();
self.s[0].$mod(self.s[$nr - 1])
}
pub fn return_u64(&mut self) -> u64 {
self.clock();
let be = self.s[1].$mod(self.s[$nr - 1]) as u64;
let le = self.s[0].$mod(self.s[$nr - 1]) as u64;
(be << 32) | le
}
pub fn dump_state(&self) -> [u32; $nr] {
self.s
}
}
};
}
impl_xorwow!(Xorwow96, wrapping_add, 4, (10, 5, 26));
impl_xorwow!(Xorwow128, wrapping_add, 5, (5, 14, 1));
impl_xorwow!(Xorwow160, wrapping_add, 6, (2, 1, 4));
impl_xorwow!(XorwowXor96, bitxor, 4, (10, 5, 26));
impl_xorwow!(XorwowXor128, bitxor, 5, (5, 14, 1));
impl_xorwow!(XorwowXor160, bitxor, 6, (2, 1, 4));
macro_rules! impl_seedable {
($name: ident, $nr: expr) => {
impl SeedableRng for $name {
type Seed = [u8; $nr * 4];
fn from_seed(seed: [u8; $nr * 4]) -> Self {
let mut state = [0u32; $nr];
read_u32_into(&seed, &mut state);
if state[0..($nr - 1)] == [0u32; $nr - 1] {
for i in 0..($nr - 1) { state[i] = u32::MAX; }
}
Self { s: state }
}
fn seed_from_u64(seed: u64) -> Self {
let mut state = [0u32; $nr];
let be = (seed >> 32) as u32;
let le = seed as u32;
for x in state.iter_mut().enumerate().take($nr - 1) {
match x.0 % 4 {
0 => *x.1 = le,
1 => *x.1 = !le,
2 => *x.1 = be,
3usize.. => *x.1 = !be,
}
}
Self { s: state }
}
}
};
}
impl_seedable!(Xorwow96, 4);
impl_seedable!(Xorwow128, 5);
impl_seedable!(Xorwow160, 6);
impl_seedable!(XorwowXor96, 4);
impl_seedable!(XorwowXor128, 5);
impl_seedable!(XorwowXor160, 6);
macro_rules! impl_core {
($name: ident) => {
impl RngCore for $name {
fn next_u32(&mut self) -> u32 {
self.return_u32()
}
fn next_u64(&mut self) -> u64 {
self.return_u64()
}
fn fill_bytes(&mut self, dest: &mut [u8]) {
fill_bytes_via_next(self, dest);
}
fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
self.fill_bytes(dest);
Ok(())
}
}
};
}
pub(crate) use impl_core;
impl_core!(Xorwow96);
impl_core!(Xorwow128);
impl_core!(Xorwow160);
impl_core!(XorwowXor96);
impl_core!(XorwowXor128);
impl_core!(XorwowXor160);