use std::cmp::max;
use std::fmt;
const N: usize = 624;
const M: usize = 397;
const MATRIX_A: u32 = 0x9908b0df;
const UPPER_MASK: u32 = 0x80000000;
const LOWER_MASK: u32 = 0x7fffffff;
const INITIAL_INDEX: usize = N;
const UNSEEDED_INDEX: usize = N + 1;
#[derive(Clone)]
pub struct MersenneTwister {
index: usize,
state: [u32; N],
}
impl fmt::Debug for MersenneTwister {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.debug_struct("MersenneTwister")
.field("index", &self.index)
.field("state", &&self.state[..])
.finish()
}
}
impl MersenneTwister {
pub fn new() -> MersenneTwister {
MersenneTwister {
index: UNSEEDED_INDEX,
state: [0; N],
}
}
pub fn genrand_int32(&mut self) -> u32 {
let mt = &mut self.state;
if self.index >= N {
assert!(self.index != UNSEEDED_INDEX,
"random number generator must be seeded before use");
#[cfg(feature = "prefetch")]
#[cfg(target_feature = "sse")]
unsafe {
for i in (0..N).step_by(64) {
core::arch::x86_64::_mm_prefetch((mt as *const _ as *const i8).add(i), core::arch::x86_64::_MM_HINT_T2);
}
}
for kk in 0..(N - M) {
let y = (mt[kk] & UPPER_MASK) | (mt[kk + 1] & LOWER_MASK);
mt[kk] = mt[kk + M] ^ (y >> 1) ^ ((y & 1) * MATRIX_A);
}
for kk in (N - M)..(N - 1) {
let y = (mt[kk] & UPPER_MASK) | (mt[kk + 1] & LOWER_MASK);
mt[kk] = mt[kk + M - N] ^ (y >> 1) ^ ((y & 1) * MATRIX_A);
}
let kk = N - 1;
let y = (mt[kk] & UPPER_MASK) | (mt[kk + 1 - N] & LOWER_MASK);
mt[kk] = mt[kk + M - N] ^ (y >> 1) ^ ((y & 1) * MATRIX_A);
self.index = 0;
}
let y = mt[self.index];
self.index += 1;
let mut y = y;
y ^= y >> 11;
y ^= (y << 7) & 0x9d2c5680;
y ^= (y << 15) & 0xefc60000;
y ^= y >> 18;
y
}
pub fn init_by_array(&mut self, init_key: &[u32]) {
self.init_genrand(19650218);
let mt = &mut self.state;
let mut i: usize = 1;
let mut j: usize = 0;
for _ in 0..max(N, init_key.len()) {
let prev = mt[i - 1] ^ (mt[i - 1] >> 30);
mt[i] = (mt[i] ^ prev.wrapping_mul(1664525))
.wrapping_add(init_key[j])
.wrapping_add(j as u32);
i += 1;
if i >= N {
mt[0] = mt[N - 1];
i = 1;
}
j += 1;
if j >= init_key.len() {
j = 0;
}
}
for _ in 0..(N - 1) {
let prev = mt[i - 1] ^ (mt[i - 1] >> 30);
mt[i] = (mt[i] ^ prev.wrapping_mul(1566083941))
.wrapping_sub(i as u32);
i += 1;
if i >= N {
mt[0] = mt[N - 1];
i = 1;
}
}
mt[0] = 0x80000000;
}
pub fn init_genrand(&mut self, s: u32) {
let mt = &mut self.state;
mt[0] = s;
for i in 1..N {
let prev = mt[i - 1] ^ (mt[i - 1] >> 30);
mt[i] = prev.wrapping_mul(1812433253)
.wrapping_add(i as u32);
}
self.index = INITIAL_INDEX; }
pub fn genrand_res53(&mut self) -> f64 {
let a = self.genrand_int32() >> 5; let b = self.genrand_int32() >> 6;
(a as f64 * 67108864.0 + b as f64) * (1.0 / 9007199254740992.0)
}
pub fn genrand_int31(&mut self) -> i32 {
(self.genrand_int32() >> 1) as i32
}
pub fn genrand_real1(&mut self) -> f64 {
self.genrand_int32() as f64 / 4294967295.0
}
pub fn genrand_real2(&mut self) -> f64 {
self.genrand_int32() as f64 / 4294967296.0
}
pub fn genrand_real3(&mut self) -> f64 {
(self.genrand_int32() as f64 + 0.5) / 4294967296.0
}
#[deprecated = "Can lead to very poor quality random numbers. \
Use `init_by_array` or `init_genrand` instead."]
pub fn sgenrand(&mut self, seed: u32) {
let mt = &mut self.state;
mt[0] = seed;
for i in 1..N {
mt[i] = mt[i - 1].wrapping_mul(69069);
}
}
}