#![no_std]
extern crate random;
#[cfg(test)]
#[macro_use]
extern crate std;
use core::fmt;
use core::slice;
use core::iter::repeat;
use core::num::Wrapping as w;
use random::*;
type w32 = w<u32>;
type w64 = w<u64>;
const RAND_SIZE_64_LEN: usize = 8;
const RAND_SIZE_64: usize = 1 << RAND_SIZE_64_LEN;
#[derive(Clone, Copy)]
pub struct Rng {
cnt: usize,
rsl: [w64; RAND_SIZE_64],
mem: [w64; RAND_SIZE_64],
a: w64,
b: w64,
c: w64,
}
impl fmt::Debug for Rng {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("Rng")
.field("cnt", &self.cnt)
.field("rsl", &self.rsl.iter())
.field("mem", &self.mem.iter())
.field("a", &self.a)
.field("b", &self.b)
.field("c", &self.c)
.finish()
}
}
static empty: Rng = Rng {
cnt: 0,
rsl: [w(0); RAND_SIZE_64],
mem: [w(0); RAND_SIZE_64],
a: w(0),
b: w(0),
c: w(0),
};
impl Rng {
pub fn new_unseeded() -> Rng {
let mut rng = empty;
rng.init(false);
rng
}
fn init(&mut self, use_rsl: bool) {
macro_rules! init {
($var:ident) => (
let mut $var = w(0x9e3779b97f4a7c13);
)
}
init!(a);
init!(b);
init!(c);
init!(d);
init!(e);
init!(f);
init!(g);
init!(h);
macro_rules! mix {
() => {{
a = a - e;
f = f ^ (h >> 9);
h = h + a;
b = b - f;
g = g ^ (a << 9);
a = a + b;
c = c - g;
h = h ^ (b >> 23);
b = b + c;
d = d - h;
a = a ^ (c << 15);
c = c + d;
e = e - a;
b = b ^ (d >> 14);
d = d + e;
f = f - b;
c = c ^ (e << 20);
e = e + f;
g = g - c;
d = d ^ (f >> 17);
f = f + g;
h = h - d;
e = e ^ (g << 14);
g = g + h;
}}
}
for _ in 0..4 {
mix!();
}
if use_rsl {
macro_rules! memloop {
($arr:expr) => {{
for i in (0..RAND_SIZE_64 / 8).map(|i| i * 8) {
a = a + $arr[i];
b = b + $arr[i + 1];
c = c + $arr[i + 2];
d = d + $arr[i + 3];
e = e + $arr[i + 4];
f = f + $arr[i + 5];
g = g + $arr[i + 6];
h = h + $arr[i + 7];
mix!();
self.mem[i] = a;
self.mem[i + 1] = b;
self.mem[i + 2] = c;
self.mem[i + 3] = d;
self.mem[i + 4] = e;
self.mem[i + 5] = f;
self.mem[i + 6] = g;
self.mem[i + 7] = h;
}
}}
}
memloop!(self.rsl);
memloop!(self.mem);
} else {
for i in (0..RAND_SIZE_64 / 8).map(|i| i * 8) {
mix!();
self.mem[i] = a;
self.mem[i + 1] = b;
self.mem[i + 2] = c;
self.mem[i + 3] = d;
self.mem[i + 4] = e;
self.mem[i + 5] = f;
self.mem[i + 6] = g;
self.mem[i + 7] = h;
}
}
self.isaac64();
}
fn isaac64(&mut self) {
self.c = self.c + w(1);
let mut a = self.a;
let mut b = self.b + self.c;
const MIDPOINT: usize = RAND_SIZE_64 / 2;
const MP_VEC: [(usize, usize); 2] = [(0, MIDPOINT), (MIDPOINT, 0)];
macro_rules! ind {
($x:expr) => {
*self.mem.get_unchecked((($x >> 3).0 as usize) & (RAND_SIZE_64 - 1))
}
}
for &(mr_offset, m2_offset) in &MP_VEC {
for base in (0..MIDPOINT / 4).map(|i| i * 4) {
macro_rules! rngstepp {
($j:expr, $shift:expr) => {{
let base = base + $j;
let mix = a ^ (a << $shift);
let mix = if $j == 0 {!mix} else {mix};
unsafe {
let x = *self.mem.get_unchecked(base + mr_offset);
a = mix + *self.mem.get_unchecked(base + m2_offset);
let y = ind!(x) + a + b;
*self.mem.get_unchecked_mut(base + mr_offset) = y;
b = ind!(y >> RAND_SIZE_64_LEN) + x;
*self.rsl.get_unchecked_mut(base + mr_offset) = b;
}
}}
}
macro_rules! rngstepn {
($j:expr, $shift:expr) => {{
let base = base + $j;
let mix = a ^ (a >> $shift);
let mix = if $j == 0 {!mix} else {mix};
unsafe {
let x = *self.mem.get_unchecked(base + mr_offset);
a = mix + *self.mem.get_unchecked(base + m2_offset);
let y = ind!(x) + a + b;
*self.mem.get_unchecked_mut(base + mr_offset) = y;
b = ind!(y >> RAND_SIZE_64_LEN) + x;
*self.rsl.get_unchecked_mut(base + mr_offset) = b;
}
}}
}
rngstepp!(0, 21);
rngstepn!(1, 5);
rngstepp!(2, 12);
rngstepn!(3, 33);
}
}
self.a = a;
self.b = b;
self.cnt = RAND_SIZE_64;
}
}
impl RandomGen for Rng {
#[inline]
fn gen_u32(&mut self) -> u32 {
self.gen_u64() as u32
}
#[inline]
fn gen_u64(&mut self) -> u64 {
if self.cnt == 0 {
self.isaac64();
}
self.cnt -= 1;
debug_assert!(self.cnt < RAND_SIZE_64);
self.rsl[(self.cnt % RAND_SIZE_64) as usize].0
}
}
impl<'a> Seedable<&'a [u64]> for Rng {
fn reseed(&mut self, seed: &'a [u64]) {
let seed_iter = seed.iter().cloned().chain(repeat(0));
for (rsl_elem, seed_elem) in self.rsl.iter_mut().zip(seed_iter) {
*rsl_elem = w(seed_elem);
}
self.cnt = 0;
self.a = w(0);
self.b = w(0);
self.c = w(0);
self.init(true);
}
fn from_seed(seed: &'a [u64]) -> Rng {
let mut rng = empty;
rng.reseed(seed);
rng
}
}
impl Random for Rng {
fn random<G: ?Sized + RandomGen>(g: &mut G) -> Self {
let mut ret = empty;
unsafe {
let ptr = ret.rsl.as_mut_ptr() as *mut u8;
let slice = slice::from_raw_parts_mut(ptr, RAND_SIZE_64 * 8);
g.fill_bytes(slice);
}
ret.cnt = 0;
ret.a = w(0);
ret.b = w(0);
ret.c = w(0);
ret.init(true);
return ret;
}
}
#[cfg(test)]
mod tests {
use std::prelude::v1::*;
use {RandomGen, Seedable, Stream};
use super::Rng;
#[test]
fn test_rng_64_seeded() {
let seed: &[_] = &[1, 23, 456, 7890, 12345];
let ra: Rng = Seedable::from_seed(seed);
let rb: Rng = Seedable::from_seed(seed);
assert!(Iterator::eq(Stream::<_, u64>::new(ra).take(64),
Stream::<_, u64>::new(rb).take(64)));
}
#[test]
fn test_rng_64_reseed() {
let mut s = [0; 256];
s[1] = 50;
s[2] = 77;
s[3] = 19;
let mut r: Rng = Seedable::from_seed(&s[..]);
let xs: Vec<u64> = Stream::new(&mut r).take(64).collect();
r.reseed(&s);
let ys: Vec<u64> = Stream::new(&mut r).take(64).collect();
assert_eq!(xs, ys);
}
#[test]
fn test_rng_64_true_values() {
let seed: &[_] = &[1, 23, 456, 7890, 12345];
let mut ra: Rng = Seedable::from_seed(seed);
let v = (0..10).map(|_| ra.gen_u64()).collect::<Vec<_>>();
assert_eq!(v,
vec![547121783600835980, 14377643087320773276, 17351601304698403469,
1238879483818134882, 11952566807690396487, 13970131091560099343,
4469761996653280935, 15552757044682284409, 6860251611068737823,
13722198873481261842]);
let seed: &[_] = &[12345, 67890, 54321, 9876];
let mut rb: Rng = Seedable::from_seed(seed);
for _ in 0..10000 {
rb.gen_u64();
}
let v = (0..10).map(|_| rb.gen_u64()).collect::<Vec<_>>();
assert_eq!(v,
vec![18143823860592706164, 8491801882678285927, 2699425367717515619,
17196852593171130876, 2606123525235546165, 15790932315217671084,
596345674630742204, 9947027391921273664, 11788097613744130851,
10391409374914919106]);
}
#[test]
fn test_rng_clone() {
let seed: &[_] = &[1, 23, 456, 7890, 12345];
let mut rng: Rng = Seedable::from_seed(seed);
let mut clone = rng.clone();
for _ in 0..16 {
assert_eq!(rng.gen_u64(), clone.gen_u64());
}
}
}