///
/// [1]: Bob Jenkins, [*ISAAC: A fast cryptographic random number
/// generator*](http://www.burtleburtle.net/bob/rand/isaacafa.html)
-#[deriving(Copy)]
+#[derive(Copy)]
pub struct IsaacRng {
cnt: u32,
rsl: [u32; RAND_SIZE_UINT],
let mut g = a;
let mut h = a;
- macro_rules! mix(
+ macro_rules! mix {
() => {{
a^=b<<11; d+=a; b+=c;
b^=c>>2; e+=b; c+=d;
g^=h<<8; b+=g; h+=a;
h^=a>>9; c+=h; a+=b;
}}
- );
+ }
for _ in range(0u, 4) {
mix!();
}
if use_rsl {
- macro_rules! memloop (
+ macro_rules! memloop {
($arr:expr) => {{
for i in range_step(0, RAND_SIZE as uint, 8) {
a+=$arr[i ]; b+=$arr[i+1];
self.mem[i+6]=g; self.mem[i+7]=h;
}
}}
- );
+ }
memloop!(self.rsl);
memloop!(self.mem);
static MIDPOINT: uint = (RAND_SIZE / 2) as uint;
- macro_rules! ind (($x:expr) => {
- self.mem[(($x >> 2) as uint & ((RAND_SIZE - 1) as uint))]
- });
+ macro_rules! ind {
+ ($x:expr) => ( self.mem[(($x >> 2) as uint & ((RAND_SIZE - 1) as uint))] )
+ }
let r = [(0, MIDPOINT), (MIDPOINT, 0)];
for &(mr_offset, m2_offset) in r.iter() {
- macro_rules! rngstepp(
+ macro_rules! rngstepp {
($j:expr, $shift:expr) => {{
- let base = $j;
- let mix = a << $shift as uint;
+ let base = $j;
+ let mix = a << $shift as uint;
- let x = self.mem[base + mr_offset];
- a = (a ^ mix) + self.mem[base + m2_offset];
- let y = ind!(x) + a + b;
- self.mem[base + mr_offset] = y;
+ let x = self.mem[base + mr_offset];
+ a = (a ^ mix) + self.mem[base + m2_offset];
+ let y = ind!(x) + a + b;
+ self.mem[base + mr_offset] = y;
- b = ind!(y >> RAND_SIZE_LEN as uint) + x;
- self.rsl[base + mr_offset] = b;
- }}
- );
- macro_rules! rngstepn(
+ b = ind!(y >> RAND_SIZE_LEN as uint) + x;
+ self.rsl[base + mr_offset] = b;
+ }}
+ }
+
+ macro_rules! rngstepn {
($j:expr, $shift:expr) => {{
- let base = $j;
- let mix = a >> $shift as uint;
+ let base = $j;
+ let mix = a >> $shift as uint;
- let x = self.mem[base + mr_offset];
- a = (a ^ mix) + self.mem[base + m2_offset];
- let y = ind!(x) + a + b;
- self.mem[base + mr_offset] = y;
+ let x = self.mem[base + mr_offset];
+ a = (a ^ mix) + self.mem[base + m2_offset];
+ let y = ind!(x) + a + b;
+ self.mem[base + mr_offset] = y;
- b = ind!(y >> RAND_SIZE_LEN as uint) + x;
- self.rsl[base + mr_offset] = b;
- }}
- );
+ b = ind!(y >> RAND_SIZE_LEN as uint) + x;
+ self.rsl[base + mr_offset] = b;
+ }}
+ }
for i in range_step(0u, MIDPOINT, 4) {
rngstepp!(i + 0, 13);
}
}
+// Cannot be derived because [u32; 256] does not implement Clone
+impl Clone for IsaacRng {
+ fn clone(&self) -> IsaacRng {
+ *self
+ }
+}
+
impl Rng for IsaacRng {
#[inline]
fn next_u32(&mut self) -> u32 {
///
/// [1]: Bob Jenkins, [*ISAAC: A fast cryptographic random number
/// generator*](http://www.burtleburtle.net/bob/rand/isaacafa.html)
-#[deriving(Copy)]
+#[derive(Copy)]
pub struct Isaac64Rng {
cnt: uint,
rsl: [u64; RAND_SIZE_64],
/// of `rsl` as a seed, otherwise construct one algorithmically (not
/// randomly).
fn init(&mut self, use_rsl: bool) {
- macro_rules! init (
+ macro_rules! init {
($var:ident) => (
let mut $var = 0x9e3779b97f4a7c13;
)
- );
+ }
init!(a); init!(b); init!(c); init!(d);
init!(e); init!(f); init!(g); init!(h);
- macro_rules! mix(
+ macro_rules! mix {
() => {{
a-=e; f^=h>>9; h+=a;
b-=f; g^=a<<9; a+=b;
g-=c; d^=f>>17; f+=g;
h-=d; e^=g<<14; g+=h;
}}
- );
+ }
for _ in range(0u, 4) {
mix!();
}
if use_rsl {
- macro_rules! memloop (
+ macro_rules! memloop {
($arr:expr) => {{
for i in range(0, RAND_SIZE_64 / 8).map(|i| i * 8) {
a+=$arr[i ]; b+=$arr[i+1];
self.mem[i+6]=g; self.mem[i+7]=h;
}
}}
- );
+ }
memloop!(self.rsl);
memloop!(self.mem);
let mut b = self.b + self.c;
const MIDPOINT: uint = RAND_SIZE_64 / 2;
const MP_VEC: [(uint, uint); 2] = [(0,MIDPOINT), (MIDPOINT, 0)];
- macro_rules! ind (
+ macro_rules! ind {
($x:expr) => {
*self.mem.get_unchecked(($x as uint >> 3) & (RAND_SIZE_64 - 1))
}
- );
+ }
for &(mr_offset, m2_offset) in MP_VEC.iter() {
for base in range(0, MIDPOINT / 4).map(|i| i * 4) {
- macro_rules! rngstepp(
+ macro_rules! rngstepp {
($j:expr, $shift:expr) => {{
- let base = base + $j;
- let mix = a ^ (a << $shift as uint);
- 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(
+ let base = base + $j;
+ let mix = a ^ (a << $shift as uint);
+ 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 as uint);
- 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;
- }
- }}
- );
+ let base = base + $j;
+ let mix = a ^ (a >> $shift as uint);
+ 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!(0u, 21);
rngstepn!(1u, 5);
rngstepp!(2u, 12);
}
}
+// Cannot be derived because [u32; 256] does not implement Clone
+impl Clone for Isaac64Rng {
+ fn clone(&self) -> Isaac64Rng {
+ *self
+ }
+}
+
impl Rng for Isaac64Rng {
// FIXME #7771: having next_u32 like this should be unnecessary
#[inline]
}
}
+
#[cfg(test)]
mod test {
use std::prelude::v1::*;
let seed: &[_] = &[1, 23, 456, 7890, 12345];
let mut ra: IsaacRng = SeedableRng::from_seed(seed);
// Regression test that isaac is actually using the above vector
- let v = Vec::from_fn(10, |_| ra.next_u32());
+ let v = range(0, 10).map(|_| ra.next_u32()).collect::<Vec<_>>();
assert_eq!(v,
vec!(2558573138, 873787463, 263499565, 2103644246, 3595684709,
4203127393, 264982119, 2765226902, 2737944514, 3900253796));
// skip forward to the 10000th number
for _ in range(0u, 10000) { rb.next_u32(); }
- let v = Vec::from_fn(10, |_| rb.next_u32());
+ let v = range(0, 10).map(|_| rb.next_u32()).collect::<Vec<_>>();
assert_eq!(v,
vec!(3676831399, 3183332890, 2834741178, 3854698763, 2717568474,
1576568959, 3507990155, 179069555, 141456972, 2478885421));
let seed: &[_] = &[1, 23, 456, 7890, 12345];
let mut ra: Isaac64Rng = SeedableRng::from_seed(seed);
// Regression test that isaac is actually using the above vector
- let v = Vec::from_fn(10, |_| ra.next_u64());
+ let v = range(0, 10).map(|_| ra.next_u64()).collect::<Vec<_>>();
assert_eq!(v,
vec!(547121783600835980, 14377643087320773276, 17351601304698403469,
1238879483818134882, 11952566807690396487, 13970131091560099343,
// skip forward to the 10000th number
for _ in range(0u, 10000) { rb.next_u64(); }
- let v = Vec::from_fn(10, |_| rb.next_u64());
+ let v = range(0, 10).map(|_| rb.next_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: Isaac64Rng = SeedableRng::from_seed(seed);
+ let mut clone = rng.clone();
+ for _ in range(0u, 16) {
+ assert_eq!(rng.next_u64(), clone.next_u64());
+ }
+ }
}