std::rand: Add an implementation of ISAAC64.
This is 2x faster on 64-bit computers at generating anything larger than 32-bits. It has been verified against the canonical C implementation from the website of the creator of ISAAC64. Also, move `Rng.next` to `Rng.next_u32` and add `Rng.next_u64` to take full advantage of the wider word width; otherwise Isaac64 will always be squeezed down into a u32 wasting half the entropy and offering no advantage over the 32-bit variant.
This commit is contained in:
parent
72bf201d61
commit
a2b509656a
8 changed files with 295 additions and 64 deletions
|
@ -1533,7 +1533,7 @@ mod tests {
|
||||||
let mut r = rng();
|
let mut r = rng();
|
||||||
let mut bitv = 0 as uint;
|
let mut bitv = 0 as uint;
|
||||||
do b.iter {
|
do b.iter {
|
||||||
bitv |= (1 << ((r.next() as uint) % uint::bits));
|
bitv |= (1 << ((r.next_u32() as uint) % uint::bits));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1542,7 +1542,7 @@ mod tests {
|
||||||
let mut r = rng();
|
let mut r = rng();
|
||||||
let mut bitv = SmallBitv::new(uint::bits);
|
let mut bitv = SmallBitv::new(uint::bits);
|
||||||
do b.iter {
|
do b.iter {
|
||||||
bitv.set((r.next() as uint) % uint::bits, true);
|
bitv.set((r.next_u32() as uint) % uint::bits, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1551,7 +1551,7 @@ mod tests {
|
||||||
let mut r = rng();
|
let mut r = rng();
|
||||||
let mut bitv = BigBitv::new(~[0]);
|
let mut bitv = BigBitv::new(~[0]);
|
||||||
do b.iter {
|
do b.iter {
|
||||||
bitv.set((r.next() as uint) % uint::bits, true);
|
bitv.set((r.next_u32() as uint) % uint::bits, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1562,7 +1562,7 @@ mod tests {
|
||||||
storage.grow(BENCH_BITS / uint::bits, &0u);
|
storage.grow(BENCH_BITS / uint::bits, &0u);
|
||||||
let mut bitv = BigBitv::new(storage);
|
let mut bitv = BigBitv::new(storage);
|
||||||
do b.iter {
|
do b.iter {
|
||||||
bitv.set((r.next() as uint) % BENCH_BITS, true);
|
bitv.set((r.next_u32() as uint) % BENCH_BITS, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1571,7 +1571,7 @@ mod tests {
|
||||||
let mut r = rng();
|
let mut r = rng();
|
||||||
let mut bitv = Bitv::new(BENCH_BITS, false);
|
let mut bitv = Bitv::new(BENCH_BITS, false);
|
||||||
do b.iter {
|
do b.iter {
|
||||||
bitv.set((r.next() as uint) % BENCH_BITS, true);
|
bitv.set((r.next_u32() as uint) % BENCH_BITS, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1580,7 +1580,7 @@ mod tests {
|
||||||
let mut r = rng();
|
let mut r = rng();
|
||||||
let mut bitv = Bitv::new(uint::bits, false);
|
let mut bitv = Bitv::new(uint::bits, false);
|
||||||
do b.iter {
|
do b.iter {
|
||||||
bitv.set((r.next() as uint) % uint::bits, true);
|
bitv.set((r.next_u32() as uint) % uint::bits, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1589,7 +1589,7 @@ mod tests {
|
||||||
let mut r = rng();
|
let mut r = rng();
|
||||||
let mut bitv = BitvSet::new();
|
let mut bitv = BitvSet::new();
|
||||||
do b.iter {
|
do b.iter {
|
||||||
bitv.insert((r.next() as uint) % uint::bits);
|
bitv.insert((r.next_u32() as uint) % uint::bits);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1598,7 +1598,7 @@ mod tests {
|
||||||
let mut r = rng();
|
let mut r = rng();
|
||||||
let mut bitv = BitvSet::new();
|
let mut bitv = BitvSet::new();
|
||||||
do b.iter {
|
do b.iter {
|
||||||
bitv.insert((r.next() as uint) % BENCH_BITS);
|
bitv.insert((r.next_u32() as uint) % BENCH_BITS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -187,7 +187,7 @@ impl IsaacRng {
|
||||||
|
|
||||||
impl Rng for IsaacRng {
|
impl Rng for IsaacRng {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn next(&mut self) -> u32 {
|
fn next_u32(&mut self) -> u32 {
|
||||||
if self.cnt == 0 {
|
if self.cnt == 0 {
|
||||||
// make some more numbers
|
// make some more numbers
|
||||||
self.isaac();
|
self.isaac();
|
||||||
|
@ -196,3 +196,234 @@ impl Rng for IsaacRng {
|
||||||
self.rsl[self.cnt]
|
self.rsl[self.cnt]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static RAND_SIZE_64_LEN: uint = 8;
|
||||||
|
static RAND_SIZE_64: uint = 1 << RAND_SIZE_64_LEN;
|
||||||
|
|
||||||
|
/// A random number generator that uses the 64-bit variant of the
|
||||||
|
/// [ISAAC
|
||||||
|
/// algorithm](http://en.wikipedia.org/wiki/ISAAC_%28cipher%29).
|
||||||
|
///
|
||||||
|
/// The ISAAC algorithm is suitable for cryptographic purposes.
|
||||||
|
pub struct Isaac64Rng {
|
||||||
|
priv cnt: uint,
|
||||||
|
priv rsl: [u64, .. RAND_SIZE_64],
|
||||||
|
priv mem: [u64, .. RAND_SIZE_64],
|
||||||
|
priv a: u64,
|
||||||
|
priv b: u64,
|
||||||
|
priv c: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Isaac64Rng {
|
||||||
|
/// Create a 64-bit ISAAC random number generator with a random
|
||||||
|
/// seed.
|
||||||
|
pub fn new() -> Isaac64Rng {
|
||||||
|
Isaac64Rng::new_seeded(seed(RAND_SIZE_64 as uint * 8))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a 64-bit ISAAC random number generator with a
|
||||||
|
/// seed. This can be any length, although the maximum number of
|
||||||
|
/// bytes used is 2048 and any more will be silently ignored. A
|
||||||
|
/// generator constructed with a given seed will generate the same
|
||||||
|
/// sequence of values as all other generators constructed with
|
||||||
|
/// the same seed.
|
||||||
|
pub fn new_seeded(seed: &[u8]) -> Isaac64Rng {
|
||||||
|
let mut rng = Isaac64Rng {
|
||||||
|
cnt: 0,
|
||||||
|
rsl: [0, .. RAND_SIZE_64],
|
||||||
|
mem: [0, .. RAND_SIZE_64],
|
||||||
|
a: 0, b: 0, c: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
let array_size = sys::size_of_val(&rng.rsl);
|
||||||
|
let copy_length = cmp::min(array_size, seed.len());
|
||||||
|
|
||||||
|
// manually create a &mut [u8] slice of randrsl to copy into.
|
||||||
|
let dest = unsafe { cast::transmute((&mut rng.rsl, array_size)) };
|
||||||
|
vec::bytes::copy_memory(dest, seed, copy_length);
|
||||||
|
rng.init(true);
|
||||||
|
rng
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a 64-bit ISAAC random number generator using the
|
||||||
|
/// default fixed seed.
|
||||||
|
pub fn new_unseeded() -> Isaac64Rng {
|
||||||
|
let mut rng = Isaac64Rng {
|
||||||
|
cnt: 0,
|
||||||
|
rsl: [0, .. RAND_SIZE_64],
|
||||||
|
mem: [0, .. RAND_SIZE_64],
|
||||||
|
a: 0, b: 0, c: 0,
|
||||||
|
};
|
||||||
|
rng.init(false);
|
||||||
|
rng
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Initialises `self`. If `use_rsl` is true, then use the current value
|
||||||
|
/// of `rsl` as a seed, otherwise construct one algorithmically (not
|
||||||
|
/// randomly).
|
||||||
|
fn init(&mut self, use_rsl: bool) {
|
||||||
|
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(
|
||||||
|
() => {{
|
||||||
|
a-=e; f^=h>>9; h+=a;
|
||||||
|
b-=f; g^=a<<9; a+=b;
|
||||||
|
c-=g; h^=b>>23; b+=c;
|
||||||
|
d-=h; a^=c<<15; c+=d;
|
||||||
|
e-=a; b^=d>>14; d+=e;
|
||||||
|
f-=b; c^=e<<20; e+=f;
|
||||||
|
g-=c; d^=f>>17; f+=g;
|
||||||
|
h-=d; e^=g<<14; g+=h;
|
||||||
|
}}
|
||||||
|
);
|
||||||
|
|
||||||
|
for _ in range(0, 4) { mix!(); }
|
||||||
|
if use_rsl {
|
||||||
|
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];
|
||||||
|
c+=$arr[i+2]; d+=$arr[i+3];
|
||||||
|
e+=$arr[i+4]; f+=$arr[i+5];
|
||||||
|
g+=$arr[i+6]; 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 range(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();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Refills the output buffer (`self.rsl`)
|
||||||
|
fn isaac64(&mut self) {
|
||||||
|
self.c += 1;
|
||||||
|
// abbreviations
|
||||||
|
let mut a = self.a;
|
||||||
|
let mut b = self.b + self.c;
|
||||||
|
static MIDPOINT: uint = RAND_SIZE_64 / 2;
|
||||||
|
static MP_VEC: [(uint, uint), .. 2] = [(0,MIDPOINT), (MIDPOINT, 0)];
|
||||||
|
macro_rules! ind (
|
||||||
|
($x:expr) => {
|
||||||
|
self.mem.unsafe_get(($x as uint >> 3) & (RAND_SIZE_64 - 1))
|
||||||
|
}
|
||||||
|
);
|
||||||
|
macro_rules! rngstep(
|
||||||
|
($j:expr, $shift:expr) => {{
|
||||||
|
let base = base + $j;
|
||||||
|
let mix = a ^ (if $shift < 0 {
|
||||||
|
a >> -$shift as uint
|
||||||
|
} else {
|
||||||
|
a << $shift as uint
|
||||||
|
});
|
||||||
|
let mix = if $j == 0 {!mix} else {mix};
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let x = self.mem.unsafe_get(base + mr_offset);
|
||||||
|
a = mix + self.mem.unsafe_get(base + m2_offset);
|
||||||
|
let y = ind!(x) + a + b;
|
||||||
|
self.mem.unsafe_set(base + mr_offset, y);
|
||||||
|
|
||||||
|
b = ind!(y >> RAND_SIZE_64_LEN) + x;
|
||||||
|
self.rsl.unsafe_set(base + mr_offset, b);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
);
|
||||||
|
|
||||||
|
for &(mr_offset, m2_offset) in MP_VEC.iter() {
|
||||||
|
for base in range(0, MIDPOINT / 4).map(|i| i * 4) {
|
||||||
|
rngstep!(0, 21);
|
||||||
|
rngstep!(1, -5);
|
||||||
|
rngstep!(2, 12);
|
||||||
|
rngstep!(3, -33);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.a = a;
|
||||||
|
self.b = b;
|
||||||
|
self.cnt = RAND_SIZE_64;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Rng for Isaac64Rng {
|
||||||
|
#[inline]
|
||||||
|
fn next_u64(&mut self) -> u64 {
|
||||||
|
if self.cnt == 0 {
|
||||||
|
// make some more numbers
|
||||||
|
self.isaac64();
|
||||||
|
}
|
||||||
|
self.cnt -= 1;
|
||||||
|
unsafe { self.rsl.unsafe_get(self.cnt) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::*;
|
||||||
|
use rand::{Rng, seed};
|
||||||
|
use option::{Option, Some};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_rng_seeded() {
|
||||||
|
let seed = seed(1024);
|
||||||
|
let mut ra = IsaacRng::new_seeded(seed);
|
||||||
|
let mut rb = IsaacRng::new_seeded(seed);
|
||||||
|
assert_eq!(ra.gen_ascii_str(100u), rb.gen_ascii_str(100u));
|
||||||
|
|
||||||
|
let seed = seed(2048);
|
||||||
|
let mut ra = Isaac64Rng::new_seeded(seed);
|
||||||
|
let mut rb = Isaac64Rng::new_seeded(seed);
|
||||||
|
assert_eq!(ra.gen_ascii_str(100u), rb.gen_ascii_str(100u));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_rng_seeded_custom_seed() {
|
||||||
|
// much shorter than generated seeds which are 1024 & 2048
|
||||||
|
// bytes resp.
|
||||||
|
let seed = [2u8, 32u8, 4u8, 32u8, 51u8];
|
||||||
|
let mut ra = IsaacRng::new_seeded(seed);
|
||||||
|
let mut rb = IsaacRng::new_seeded(seed);
|
||||||
|
assert_eq!(ra.gen_ascii_str(100u), rb.gen_ascii_str(100u));
|
||||||
|
|
||||||
|
let mut ra = Isaac64Rng::new_seeded(seed);
|
||||||
|
let mut rb = Isaac64Rng::new_seeded(seed);
|
||||||
|
assert_eq!(ra.gen_ascii_str(100u), rb.gen_ascii_str(100u));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_rng_seeded_custom_seed2() {
|
||||||
|
let seed = [2u8, 32u8, 4u8, 32u8, 51u8];
|
||||||
|
let mut ra = IsaacRng::new_seeded(seed);
|
||||||
|
// Regression test that isaac is actually using the above vector
|
||||||
|
let r = ra.next_u32();
|
||||||
|
error2!("{:?}", r);
|
||||||
|
assert_eq!(r, 2935188040u32);
|
||||||
|
|
||||||
|
let mut ra = Isaac64Rng::new_seeded(seed);
|
||||||
|
// Regression test that isaac is actually using the above vector
|
||||||
|
let r = ra.next_u64();
|
||||||
|
error2!("{:?}", r);
|
||||||
|
assert!(r == 0 && r == 1); // FIXME: find true value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -58,7 +58,7 @@ use uint;
|
||||||
use vec;
|
use vec;
|
||||||
use libc::size_t;
|
use libc::size_t;
|
||||||
|
|
||||||
pub use self::isaac::IsaacRng;
|
pub use self::isaac::{IsaacRng, Isaac64Rng};
|
||||||
|
|
||||||
pub mod distributions;
|
pub mod distributions;
|
||||||
pub mod isaac;
|
pub mod isaac;
|
||||||
|
@ -74,7 +74,7 @@ impl Rand for int {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn rand<R: Rng>(rng: &mut R) -> int {
|
fn rand<R: Rng>(rng: &mut R) -> int {
|
||||||
if int::bits == 32 {
|
if int::bits == 32 {
|
||||||
rng.next() as int
|
rng.gen::<i32>() as int
|
||||||
} else {
|
} else {
|
||||||
rng.gen::<i64>() as int
|
rng.gen::<i64>() as int
|
||||||
}
|
}
|
||||||
|
@ -84,28 +84,28 @@ impl Rand for int {
|
||||||
impl Rand for i8 {
|
impl Rand for i8 {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn rand<R: Rng>(rng: &mut R) -> i8 {
|
fn rand<R: Rng>(rng: &mut R) -> i8 {
|
||||||
rng.next() as i8
|
rng.next_u32() as i8
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Rand for i16 {
|
impl Rand for i16 {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn rand<R: Rng>(rng: &mut R) -> i16 {
|
fn rand<R: Rng>(rng: &mut R) -> i16 {
|
||||||
rng.next() as i16
|
rng.next_u32() as i16
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Rand for i32 {
|
impl Rand for i32 {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn rand<R: Rng>(rng: &mut R) -> i32 {
|
fn rand<R: Rng>(rng: &mut R) -> i32 {
|
||||||
rng.next() as i32
|
rng.next_u32() as i32
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Rand for i64 {
|
impl Rand for i64 {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn rand<R: Rng>(rng: &mut R) -> i64 {
|
fn rand<R: Rng>(rng: &mut R) -> i64 {
|
||||||
(rng.next() as i64 << 32) | rng.next() as i64
|
rng.next_u64() as i64
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,7 +113,7 @@ impl Rand for uint {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn rand<R: Rng>(rng: &mut R) -> uint {
|
fn rand<R: Rng>(rng: &mut R) -> uint {
|
||||||
if uint::bits == 32 {
|
if uint::bits == 32 {
|
||||||
rng.next() as uint
|
rng.gen::<u32>() as uint
|
||||||
} else {
|
} else {
|
||||||
rng.gen::<u64>() as uint
|
rng.gen::<u64>() as uint
|
||||||
}
|
}
|
||||||
|
@ -123,28 +123,28 @@ impl Rand for uint {
|
||||||
impl Rand for u8 {
|
impl Rand for u8 {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn rand<R: Rng>(rng: &mut R) -> u8 {
|
fn rand<R: Rng>(rng: &mut R) -> u8 {
|
||||||
rng.next() as u8
|
rng.next_u32() as u8
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Rand for u16 {
|
impl Rand for u16 {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn rand<R: Rng>(rng: &mut R) -> u16 {
|
fn rand<R: Rng>(rng: &mut R) -> u16 {
|
||||||
rng.next() as u16
|
rng.next_u32() as u16
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Rand for u32 {
|
impl Rand for u32 {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn rand<R: Rng>(rng: &mut R) -> u32 {
|
fn rand<R: Rng>(rng: &mut R) -> u32 {
|
||||||
rng.next()
|
rng.next_u32()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Rand for u64 {
|
impl Rand for u64 {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn rand<R: Rng>(rng: &mut R) -> u64 {
|
fn rand<R: Rng>(rng: &mut R) -> u64 {
|
||||||
(rng.next() as u64 << 32) | rng.next() as u64
|
rng.next_u64()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,9 +159,9 @@ static SCALE : f64 = (u32::max_value as f64) + 1.0f64;
|
||||||
impl Rand for f64 {
|
impl Rand for f64 {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn rand<R: Rng>(rng: &mut R) -> f64 {
|
fn rand<R: Rng>(rng: &mut R) -> f64 {
|
||||||
let u1 = rng.next() as f64;
|
let u1 = rng.next_u32() as f64;
|
||||||
let u2 = rng.next() as f64;
|
let u2 = rng.next_u32() as f64;
|
||||||
let u3 = rng.next() as f64;
|
let u3 = rng.next_u32() as f64;
|
||||||
|
|
||||||
((u1 / SCALE + u2) / SCALE + u3) / SCALE
|
((u1 / SCALE + u2) / SCALE + u3) / SCALE
|
||||||
}
|
}
|
||||||
|
@ -170,7 +170,7 @@ impl Rand for f64 {
|
||||||
impl Rand for bool {
|
impl Rand for bool {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn rand<R: Rng>(rng: &mut R) -> bool {
|
fn rand<R: Rng>(rng: &mut R) -> bool {
|
||||||
rng.next() & 1u32 == 1u32
|
rng.gen::<u8>() & 1 == 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -252,8 +252,23 @@ pub struct Weighted<T> {
|
||||||
|
|
||||||
/// A random number generator
|
/// A random number generator
|
||||||
pub trait Rng {
|
pub trait Rng {
|
||||||
/// Return the next random integer
|
/// Return the next random u32.
|
||||||
fn next(&mut self) -> u32;
|
///
|
||||||
|
/// By default this is implemented in terms of `next_u64`. An
|
||||||
|
/// implementation of this trait must provide at least one of
|
||||||
|
/// these two methods.
|
||||||
|
fn next_u32(&mut self) -> u32 {
|
||||||
|
self.next_u64() as u32
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the next random u64.
|
||||||
|
///
|
||||||
|
/// By default this is implemented in terms of `next_u32`. An
|
||||||
|
/// implementation of this trait must provide at least one of
|
||||||
|
/// these two methods.
|
||||||
|
fn next_u64(&mut self) -> u64 {
|
||||||
|
(self.next_u32() as u64 << 32) | (self.next_u32() as u64)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Return a random value of a Rand type.
|
/// Return a random value of a Rand type.
|
||||||
|
@ -594,7 +609,7 @@ pub struct XorShiftRng {
|
||||||
|
|
||||||
impl Rng for XorShiftRng {
|
impl Rng for XorShiftRng {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn next(&mut self) -> u32 {
|
fn next_u32(&mut self) -> u32 {
|
||||||
let x = self.x;
|
let x = self.x;
|
||||||
let t = x ^ (x << 11);
|
let t = x ^ (x << 11);
|
||||||
self.x = self.y;
|
self.x = self.y;
|
||||||
|
@ -680,8 +695,12 @@ pub fn task_rng() -> @mut IsaacRng {
|
||||||
// Allow direct chaining with `task_rng`
|
// Allow direct chaining with `task_rng`
|
||||||
impl<R: Rng> Rng for @mut R {
|
impl<R: Rng> Rng for @mut R {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn next(&mut self) -> u32 {
|
fn next_u32(&mut self) -> u32 {
|
||||||
(**self).next()
|
(**self).next_u32()
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
fn next_u64(&mut self) -> u64 {
|
||||||
|
(**self).next_u64()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -700,34 +719,6 @@ mod test {
|
||||||
use option::{Option, Some};
|
use option::{Option, Some};
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_rng_seeded() {
|
|
||||||
let seed = seed(400);
|
|
||||||
let mut ra = IsaacRng::new_seeded(seed);
|
|
||||||
let mut rb = IsaacRng::new_seeded(seed);
|
|
||||||
assert_eq!(ra.gen_ascii_str(100u), rb.gen_ascii_str(100u));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_rng_seeded_custom_seed() {
|
|
||||||
// much shorter than generated seeds which are 1024 bytes
|
|
||||||
let seed = [2u8, 32u8, 4u8, 32u8, 51u8];
|
|
||||||
let mut ra = IsaacRng::new_seeded(seed);
|
|
||||||
let mut rb = IsaacRng::new_seeded(seed);
|
|
||||||
assert_eq!(ra.gen_ascii_str(100u), rb.gen_ascii_str(100u));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_rng_seeded_custom_seed2() {
|
|
||||||
let seed = [2u8, 32u8, 4u8, 32u8, 51u8];
|
|
||||||
let mut ra = IsaacRng::new_seeded(seed);
|
|
||||||
// Regression test that isaac is actually using the above vector
|
|
||||||
let r = ra.next();
|
|
||||||
debug2!("{:?}", r);
|
|
||||||
assert!(r == 890007737u32 // on x86_64
|
|
||||||
|| r == 2935188040u32); // on x86
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_gen_integer_range() {
|
fn test_gen_integer_range() {
|
||||||
let mut r = rng();
|
let mut r = rng();
|
||||||
|
@ -921,6 +912,15 @@ mod bench {
|
||||||
bh.bytes = size_of::<uint>() as u64;
|
bh.bytes = size_of::<uint>() as u64;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[bench]
|
||||||
|
fn rand_isaac64(bh: &mut BenchHarness) {
|
||||||
|
let mut rng = Isaac64Rng::new();
|
||||||
|
do bh.iter {
|
||||||
|
rng.gen::<uint>();
|
||||||
|
}
|
||||||
|
bh.bytes = size_of::<uint>() as u64;
|
||||||
|
}
|
||||||
|
|
||||||
#[bench]
|
#[bench]
|
||||||
fn rand_shuffle_100(bh: &mut BenchHarness) {
|
fn rand_shuffle_100(bh: &mut BenchHarness) {
|
||||||
let mut rng = XorShiftRng::new();
|
let mut rng = XorShiftRng::new();
|
||||||
|
|
|
@ -509,7 +509,7 @@ mod test {
|
||||||
do run_in_newsched_task() {
|
do run_in_newsched_task() {
|
||||||
use rand::{rng, Rng};
|
use rand::{rng, Rng};
|
||||||
let mut r = rng();
|
let mut r = rng();
|
||||||
let _ = r.next();
|
let _ = r.next_u32();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -109,7 +109,7 @@ fn main() {
|
||||||
let mut rng = std::rand::IsaacRng::new_seeded([1, 1, 1, 1, 1, 1, 1]);
|
let mut rng = std::rand::IsaacRng::new_seeded([1, 1, 1, 1, 1, 1, 1]);
|
||||||
let mut set = HashSet::new();
|
let mut set = HashSet::new();
|
||||||
while set.len() != n_keys {
|
while set.len() != n_keys {
|
||||||
let next = rng.next() as uint;
|
let next = rng.gen();
|
||||||
if set.insert(next) {
|
if set.insert(next) {
|
||||||
rand.push(next);
|
rand.push(next);
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,7 +60,7 @@ impl Results {
|
||||||
let mut set = f();
|
let mut set = f();
|
||||||
do timed(&mut self.random_ints) {
|
do timed(&mut self.random_ints) {
|
||||||
for _ in range(0, num_keys) {
|
for _ in range(0, num_keys) {
|
||||||
set.insert((rng.next() as uint) % rand_cap);
|
set.insert(rng.gen::<uint>() % rand_cap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -102,7 +102,7 @@ impl Results {
|
||||||
let mut set = f();
|
let mut set = f();
|
||||||
do timed(&mut self.random_strings) {
|
do timed(&mut self.random_strings) {
|
||||||
for _ in range(0, num_keys) {
|
for _ in range(0, num_keys) {
|
||||||
let s = (rng.next() as uint).to_str();
|
let s = rng.gen::<uint>().to_str();
|
||||||
set.insert(s);
|
set.insert(s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,7 +76,7 @@ fn make_random_fasta(wr: @io::Writer,
|
||||||
wr.write_line(~">" + id + " " + desc);
|
wr.write_line(~">" + id + " " + desc);
|
||||||
let mut rng = rand::rng();
|
let mut rng = rand::rng();
|
||||||
let rng = @mut MyRandom {
|
let rng = @mut MyRandom {
|
||||||
last: rng.next()
|
last: rng.gen()
|
||||||
};
|
};
|
||||||
let mut op: ~str = ~"";
|
let mut op: ~str = ~"";
|
||||||
for _ in range(0u, n as uint) {
|
for _ in range(0u, n as uint) {
|
||||||
|
|
|
@ -69,8 +69,8 @@ pub fn main() {
|
||||||
let mut rng = rand::rng();
|
let mut rng = rand::rng();
|
||||||
for f in fns.iter() {
|
for f in fns.iter() {
|
||||||
let f = *f;
|
let f = *f;
|
||||||
let sz = rng.next() % 256u32 + 256u32;
|
let sz = rng.gen::<u32>() % 256u32 + 256u32;
|
||||||
let frame_backoff = rng.next() % 10u32 + 1u32;
|
let frame_backoff = rng.gen::<u32>() % 10u32 + 1u32;
|
||||||
task::try(|| runtest(f, frame_backoff) );
|
task::try(|| runtest(f, frame_backoff) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue