Skip to content

Commit

Permalink
implement xorshift128+
Browse files Browse the repository at this point in the history
  • Loading branch information
arthurprs committed Jul 18, 2015
1 parent e61752f commit 7b530c8
Show file tree
Hide file tree
Showing 3 changed files with 267 additions and 137 deletions.
110 changes: 60 additions & 50 deletions benches/bench.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,64 +3,74 @@
extern crate test;
extern crate rand;

const RAND_BENCH_N: u64 = 100;

mod distributions;

use std::mem::size_of;
use test::{black_box, Bencher};
use rand::{XorShiftRng, StdRng, IsaacRng, Isaac64Rng, Rng};
use rand::{OsRng, weak_rng};

#[bench]
fn rand_xorshift(b: &mut Bencher) {
let mut rng: XorShiftRng = OsRng::new().unwrap().gen();
b.iter(|| {
for _ in 0..RAND_BENCH_N {
black_box(rng.gen::<usize>());
}
});
b.bytes = size_of::<usize>() as u64 * RAND_BENCH_N;
}

#[bench]
fn rand_isaac(b: &mut Bencher) {
let mut rng: IsaacRng = OsRng::new().unwrap().gen();
b.iter(|| {
for _ in 0..RAND_BENCH_N {
black_box(rng.gen::<usize>());
}
});
b.bytes = size_of::<usize>() as u64 * RAND_BENCH_N;
}

#[bench]
fn rand_isaac64(b: &mut Bencher) {
let mut rng: Isaac64Rng = OsRng::new().unwrap().gen();
b.iter(|| {
for _ in 0..RAND_BENCH_N {
black_box(rng.gen::<usize>());
}
});
b.bytes = size_of::<usize>() as u64 * RAND_BENCH_N;
}
use test::Bencher;
use rand::{weak_rng, Rng};

#[bench]
fn rand_std(b: &mut Bencher) {
let mut rng = StdRng::new().unwrap();
b.iter(|| {
for _ in 0..RAND_BENCH_N {
black_box(rng.gen::<usize>());
}
});
b.bytes = size_of::<usize>() as u64 * RAND_BENCH_N;
}
pub const RAND_BENCH_N: u64 = 100;

#[bench]
fn rand_shuffle_100(b: &mut Bencher) {
let mut rng = weak_rng();
let x : &mut [usize] = &mut [1; 100];
b.iter(|| {
rng.shuffle(x);
rng.shuffle(x)
})
}

mod algorithms {
use test::{black_box, Bencher};
use std::mem::size_of;
use rand::{OsRng, StdRng, weak_rng, XorShiftRng, XorShiftPlusRng, IsaacRng, Isaac64Rng, Rng, ChaChaRng};

use super::*;

macro_rules! impl_bench {
($result_ty: ty: $fn_name: ident, $hasher: ident) => (
#[bench]
fn $fn_name(b: &mut Bencher) {
let mut rng: $hasher = OsRng::new().unwrap().gen();
b.iter(|| {
for _ in 0..RAND_BENCH_N {
black_box(rng.gen::<$result_ty>());
}
});
b.bytes = size_of::<$result_ty>() as u64 * RAND_BENCH_N;
}
)
}

impl_bench!(u32: rand_xorshift_u32, XorShiftRng);
impl_bench!(u64: rand_xorshift_u64, XorShiftRng);
impl_bench!(u32: rand_rand_xorshiftplus_u32, XorShiftPlusRng);
impl_bench!(u64: rand_xorshiftplus_u64, XorShiftPlusRng);
impl_bench!(u32: rand_isaac_u32, IsaacRng);
impl_bench!(u64: rand_isaac_u64, IsaacRng);
impl_bench!(u32: rand_isaac64_u32, Isaac64Rng);
impl_bench!(u64: rand_isaac64_u64, Isaac64Rng);
impl_bench!(u32: rand_chacha_u32, ChaChaRng);
impl_bench!(u64: rand_chacha_u64, ChaChaRng);

#[bench]
fn rand_std(b: &mut Bencher) {
let mut rng = StdRng::new().unwrap();
b.iter(|| {
for _ in 0..RAND_BENCH_N {
black_box(rng.gen::<usize>());
}
});
b.bytes = size_of::<usize>() as u64 * RAND_BENCH_N;
}

#[bench]
fn rand_weak(b: &mut Bencher) {
let mut rng = weak_rng();
b.iter(|| {
for _ in 0..RAND_BENCH_N {
black_box(rng.gen::<usize>());
}
});
b.bytes = size_of::<usize>() as u64 * RAND_BENCH_N;
}
}
89 changes: 2 additions & 87 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,7 @@ pub use os::OsRng;

pub use isaac::{IsaacRng, Isaac64Rng};
pub use chacha::ChaChaRng;
pub use xorshift::{XorShiftRng, XorShiftPlusRng};

#[cfg(target_pointer_width = "32")]
use IsaacRng as IsaacWordRng;
Expand All @@ -266,6 +267,7 @@ use distributions::range::SampleRange;
pub mod distributions;
pub mod isaac;
pub mod chacha;
pub mod xorshift;
pub mod reseeding;
mod rand_impls;
pub mod os;
Expand Down Expand Up @@ -598,93 +600,6 @@ pub trait SeedableRng<Seed>: Rng {
fn from_seed(seed: Seed) -> Self;
}

/// An Xorshift[1] random number
/// generator.
///
/// The Xorshift algorithm is not suitable for cryptographic purposes
/// but is very fast. If you do not know for sure that it fits your
/// requirements, use a more secure one such as `IsaacRng` or `OsRng`.
///
/// [1]: Marsaglia, George (July 2003). ["Xorshift
/// RNGs"](http://www.jstatsoft.org/v08/i14/paper). *Journal of
/// Statistical Software*. Vol. 8 (Issue 14).
#[allow(missing_copy_implementations)]
#[derive(Clone)]
pub struct XorShiftRng {
x: w32,
y: w32,
z: w32,
w: w32,
}

impl XorShiftRng {
/// Creates a new XorShiftRng instance which is not seeded.
///
/// The initial values of this RNG are constants, so all generators created
/// by this function will yield the same stream of random numbers. It is
/// highly recommended that this is created through `SeedableRng` instead of
/// this function
pub fn new_unseeded() -> XorShiftRng {
XorShiftRng {
x: w(0x193a6754),
y: w(0xa8a7d469),
z: w(0x97830e05),
w: w(0x113ba7bb),
}
}
}

impl Rng for XorShiftRng {
#[inline]
fn next_u32(&mut self) -> u32 {
let x = self.x;
let t = x ^ (x << 11);
self.x = self.y;
self.y = self.z;
self.z = self.w;
let w_ = self.w;
self.w = w_ ^ (w_ >> 19) ^ (t ^ (t >> 8));
self.w.0
}
}

impl SeedableRng<[u32; 4]> for XorShiftRng {
/// Reseed an XorShiftRng. This will panic if `seed` is entirely 0.
fn reseed(&mut self, seed: [u32; 4]) {
assert!(!seed.iter().all(|&x| x == 0),
"XorShiftRng.reseed called with an all zero seed.");

self.x = w(seed[0]);
self.y = w(seed[1]);
self.z = w(seed[2]);
self.w = w(seed[3]);
}

/// Create a new XorShiftRng. This will panic if `seed` is entirely 0.
fn from_seed(seed: [u32; 4]) -> XorShiftRng {
assert!(!seed.iter().all(|&x| x == 0),
"XorShiftRng::from_seed called with an all zero seed.");

XorShiftRng {
x: w(seed[0]),
y: w(seed[1]),
z: w(seed[2]),
w: w(seed[3]),
}
}
}

impl Rand for XorShiftRng {
fn rand<R: Rng>(rng: &mut R) -> XorShiftRng {
let mut tuple: (u32, u32, u32, u32) = rng.gen();
while tuple == (0, 0, 0, 0) {
tuple = rng.gen();
}
let (x, y, z, w_) = tuple;
XorShiftRng { x: w(x), y: w(y), z: w(z), w: w(w_) }
}
}

/// A wrapper for generating floating point numbers uniformly in the
/// open interval `(0,1)` (not including either endpoint).
///
Expand Down
Loading

0 comments on commit 7b530c8

Please sign in to comment.