use crate::impl_core;
use rand_core::impls::fill_bytes_via_next;
use rand_core::le::read_u64_into;
use rand_core::{Error, RngCore, SeedableRng};
pub struct Linear128 {
s: [u64; 2],
}
macro_rules! impl_large {
($nr: expr) => {
fn get_bit(&mut self) -> u8 {
let output = self.s[0] as u8 & 1u8;
self.clock();
output
}
fn get_bit_rev(&mut self) -> u8 {
let output = (self.s[$nr - 1] >> 63) as u8;
self.clock_rev();
output
}
pub fn quick_bool(&mut self) -> bool {
if self.get_bit() == 1 {
true
} else {
false
}
}
pub fn quick_bool_rev(&mut self) -> bool {
if self.get_bit_rev() == 1 {
true
} else {
false
}
}
pub fn get_32bits(&mut self) -> u32 {
let mut output = 0u32;
for i in 0..32 {
output |= (self.get_bit() as u32) << i;
}
output
}
pub fn get_32bits_rev(&mut self) -> u32 {
let mut output = 0u32;
for i in 0..32 {
output |= (self.get_bit_rev() as u32) << (31 - i);
}
output
}
pub fn get_64bits(&mut self) -> u64 {
let mut output = 0u64;
for i in 0..64 {
output |= (self.get_bit() as u64) << i;
}
output
}
pub fn get_64bits_rev(&mut self) -> u64 {
let mut output = 0u64;
for i in 0..64 {
output |= (self.get_bit_rev() as u64) << (63 - i);
}
output
}
pub fn reverse_state(&mut self) {
let temp = self.s[0].reverse_bits();
for i in 1..$nr {
self.s[i - 1] = self.s[i].reverse_bits();
}
self.s[1] = temp;
}
pub fn inverse_state(&mut self) {
for i in 0..$nr {
self.s[i] = !self.s[i];
}
}
pub fn dump_state(&self) -> [u64; $nr] {
self.s
}
};
}
impl Linear128 {
pub fn clock(&mut self) {
let lsb = self.s[0] & 1;
self.s[0] = self.s[0] >> 1 | self.s[1] << 63;
self.s[1] >>= 1;
if lsb == 1 {
self.s[1] ^= 0xE100_0000_0000_0000;
}
}
pub fn clock_rev(&mut self) {
let msb = self.s[1] >> 63;
self.s[1] = self.s[1] << 1 | self.s[0] >> 63;
self.s[0] <<= 1;
if msb == 1 {
self.s[0] ^= 0x87;
}
}
impl_large!(2);
}
impl_core!(Linear128);
macro_rules! impl_seedable_large {
($name: ident, $nr: expr) => {
impl SeedableRng for $name {
type Seed = [u8; $nr * 8];
fn from_seed(seed: [u8; $nr * 8]) -> Self {
let mut state = [0u64; $nr];
read_u64_into(&seed, &mut state);
if state == [0u64; $nr] {
for i in 0..$nr {
state[i] = u64::MAX;
}
}
Self { s: state }
}
fn seed_from_u64(seed: u64) -> Self {
let mut state = [0u64; $nr];
let mut flip = true;
for x in state.iter_mut() {
if flip {
*x = seed;
} else {
*x = !seed;
}
flip = !flip;
}
Self { s: state }
}
}
};
}
impl_seedable_large!(Linear128, 2);