#[cfg(test)]
mod test;
#[cfg(test)]
mod test_data;
use std::num::Wrapping;
pub const M: Wrapping<i64> = Wrapping((1 << 48) - 1);
pub const A: Wrapping<i64> = Wrapping(0x5DEECE66D);
pub const C: Wrapping<i64> = Wrapping(11);
const F32_DIV: f32 = (1u32 << 24) as f32;
const F64_DIV: f64 = (1u64 << 53) as f64;
#[derive(Debug, Clone)]
pub struct Random {
state: Wrapping<i64>,
next_gaussian: Option<f64>
}
impl Random {
pub fn new(seed: u64) -> Self {
Random {
state: Wrapping((seed as i64) ^ A.0) & M,
next_gaussian: None
}
}
pub fn set_seed(&mut self, seed: u64) {
*self = Random::new(seed);
}
pub fn next(&mut self, bits: u8) -> i32 {
if bits > 48 {
panic!("Too many bits!")
}
self.state = (self.state * A + C) & M;
((self.state.0 as u64) >> (48 - bits)) as i32
}
pub fn next_bytes(&mut self, bytes: &mut [u8]) {
for chunk in bytes.chunks_mut(4) {
let mut block = self.next_u32();
for item in chunk {
*item = (block & 0xFF) as u8;
block >>= 8;
}
}
}
pub fn next_i32(&mut self) -> i32 {
self.next(32) as i32
}
pub fn next_u32(&mut self) -> u32 {
self.next(32) as u32
}
pub fn next_i32_bound(&mut self, max: i32) -> i32 {
if max <= 0 {
panic!("Maximum must be > 0")
}
if (max as u32).is_power_of_two() {
let max = max as i64;
return ((max.wrapping_mul(self.next(31) as i64)) >> 31) as i32;
}
let mut bits = self.next(31);
let mut val = bits % max;
while bits.wrapping_sub(val).wrapping_add(max - 1) < 0 {
bits = self.next(31);
val = bits % max;
}
val
}
pub fn next_u32_bound(&mut self, max: u32) -> u32 {
self.next_i32_bound(max as i32) as u32
}
pub fn next_i64(&mut self) -> i64 {
((self.next(32) as i64) << 32).wrapping_add(self.next(32) as i64)
}
pub fn next_u64(&mut self) -> u64 {
self.next_i64() as u64
}
pub fn next_bool(&mut self) -> bool {
self.next(1) == 1
}
pub fn next_f32(&mut self) -> f32 {
(self.next(24) as f32) / F32_DIV
}
pub fn next_f64(&mut self) -> f64 {
let high = (self.next(26) as i64) << 27;
let low = self.next(27) as i64;
(high.wrapping_add(low) as f64) / F64_DIV
}
fn next_gaussian_pair(&mut self) -> (f64, f64) {
let mut next_candidate = || {
let v = (
2.0 * self.next_f64() - 1.0,
2.0 * self.next_f64() - 1.0
);
(v, v.0*v.0 + v.1*v.1)
};
let (mut v, mut s) = next_candidate();
while s >= 1.0 || s == 0.0 {
let (vn, sn) = next_candidate();
v = vn;
s = sn;
}
let multiplier = ((s.log(::std::f64::consts::E) / s) * -2.0).sqrt();
(v.0 * multiplier, v.1 * multiplier)
}
pub fn next_gaussian(&mut self) -> f64 {
match self.next_gaussian.take() {
Some(next) => next,
None => {
let (v0, v1) = self.next_gaussian_pair();
self.next_gaussian = Some(v1);
v0
}
}
}
}