use core::num::Wrapping;
use crate::{RandomSource, Seedable};
const DEFAULT_SEED: u32 = 5489;
const STATE_LEN: usize = 624;
const STATE_LEN_M: usize = 397;
const UPPER_MASK: Wrapping<u32> = Wrapping(0x80000000);
const LOWER_MASK: Wrapping<u32> = Wrapping(0x7fffffff);
const TEMPERING_MASK_B: Wrapping<u32> = Wrapping(0x9d2c5680);
const TEMPERING_MASK_C: Wrapping<u32> = Wrapping(0xefc60000);
#[derive(Clone,Copy)]
pub struct MT19937 {
index: u16,
state: [Wrapping<u32>; STATE_LEN],
}
impl Seedable<u32> for MT19937 {
fn reseed(&mut self, seed: u32) {
self.index = STATE_LEN as u16;
self.state[0] = Wrapping(seed);
for i in 1..STATE_LEN {
self.state[i] = Wrapping(1812433253)
* (self.state[i-1] ^ (self.state[i-1] >> 30))
+ Wrapping(i as u32);
}
}
}
impl Seedable<&[u32]> for MT19937 {
fn reseed(&mut self, seed: &[u32]) {
self.reseed(19650218);
let seed_len = seed.len();
let mut i = 1;
let mut j = 0;
let k = usize::max(STATE_LEN, seed_len);
for _ in 0..k {
self.state[i] = (self.state[i] ^ ((self.state[i-1] ^ (self.state[i-1] >> 30))
* Wrapping(1664525))) + Wrapping(seed[j]) + Wrapping(j as u32);
i += 1;
j += 1;
if i >= STATE_LEN {
self.state[0] = self.state[STATE_LEN - 1];
i = 1;
}
if j >= seed_len {
j = 0;
}
}
for _ in 0..k {
self.state[i] = (self.state[i] ^ ((self.state[i-1] ^ (self.state[i-1] >> 30))
* Wrapping(1566083941))) - Wrapping(i as u32);
i += 1;
if i >= STATE_LEN {
self.state[0] = self.state[STATE_LEN - 1];
i = 1;
}
}
self.state[0] = UPPER_MASK;
}
}
impl MT19937 {
pub fn new() -> Self {
Self::new_with_seed(DEFAULT_SEED)
}
pub fn new_with_seed<S>(seed: S) -> Self
where
Self: Seedable<S>,
{
let mut s = Self {
index: 0,
state: [Wrapping(0); STATE_LEN],
};
s.reseed(seed);
s
}
fn switch_state(&mut self) {
const N: usize = STATE_LEN;
const M: usize = STATE_LEN_M;
const MAG: [Wrapping<u32>; 2] = [Wrapping(0), Wrapping(0x9908b0df)];
for i in 0..N-M {
let tmp = (self.state[i] & UPPER_MASK) | (self.state[i+1] & LOWER_MASK);
self.state[i] = self.state[i+M] ^ (tmp>>1) ^ MAG[tmp.0 as usize & 0x1];
}
for i in N-M..N-1 {
let tmp = (self.state[i] & UPPER_MASK) | (self.state[i+1] & LOWER_MASK);
self.state[i] = self.state[i + M - N] ^ (tmp>>1) ^ MAG[tmp.0 as usize & 0x1];
}
let tmp = (self.state[N-1] & UPPER_MASK) | (self.state[0] & LOWER_MASK);
self.state[N-1] = self.state[M-1] ^ (tmp>>1) ^ MAG[tmp.0 as usize & 0x1];
self.index = 0;
}
pub fn next_u32(&mut self) -> u32 {
debug_assert!(self.index != 0);
if self.index as usize >= STATE_LEN {
self.switch_state();
}
let mut n = self.state[self.index as usize];
self.index += 1;
n ^= n >> 11;
n ^= (n << 7) & TEMPERING_MASK_B;
n ^= (n << 15) & TEMPERING_MASK_C;
n ^= n >> 18;
n.0
}
}
impl Default for MT19937 {
fn default() -> Self {
Self::new()
}
}
impl RandomSource for MT19937 {
fn fill_bytes(&mut self, bytes: &mut [u8]) {
bytes.chunks_mut(4).for_each(|chunk| {
let rand_bytes: [u8; 4] = self.next_u32().to_le_bytes();
chunk.clone_from_slice(&rand_bytes[..chunk.len()]);
});
}
}