这是indexloc提供的服务,不要输入任何密码
Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ keywords = ["rng", "random", "xorshift", "xoroshiro", "splitmix"]

[dependencies]
lazy_static = "0.2"
rand = "0.3"
rand = "0.6"
rand_core = "0.3"

[dev-dependencies]
time = "0.1"
37 changes: 19 additions & 18 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

//! Implementation of the high performance xoroshiro128+, xorshift128+, xorshift1024*, and splitmix64 pseudo random number generators.
//!
//! Implements the `Rand`, `Rng`, and `SeedableRng` traits from the [rand crate](https://crates.io/crates/rand).
//! Implements the `RngCore` and `SeedableRng` traits from the [rand_core crate](https://crates.io/crates/rand_core).
//!
//! # Usage
//! ```toml
Expand Down Expand Up @@ -122,6 +122,7 @@
extern crate lazy_static;

extern crate rand;
extern crate rand_core;

pub mod splitmix64;
pub mod xoroshiro128;
Expand All @@ -133,7 +134,7 @@ pub use xoroshiro128::Xoroshiro128;
pub use xorshift128::Xorshift128;
pub use xorshift1024::Xorshift1024;

pub use rand::{Rand, Rng, SeedableRng, StdRng};
pub use rand::{Rng, SeedableRng, StdRng};

use std::sync::atomic::{AtomicUsize, Ordering};

Expand All @@ -147,24 +148,24 @@ pub trait RngJump {
}


/// Create a jumpable random number generator. Each call increments
/// the generator jump state.
pub fn thread_rng <'a, T: Rand+Rng+RngJump+SeedableRng<&'a [u64]>>() -> T {
lazy_static! {
static ref THREAD_RNG_STATE : Vec<u64> = {
match StdRng::new() {
Ok(mut r) => r.gen_iter::<u64>().take(16).collect::<Vec<u64>>(),
Err(e) => panic!("could not initialize seeding rng: {}", e)
}
};
static ref THREAD_RNG_INSTANCE : AtomicUsize = AtomicUsize::new(0);
};
// /// Create a jumpable random number generator. Each call increments
// /// the generator jump state.
// pub fn thread_rng <'a, T: RngCore+RngJump+SeedableRng>() -> T {
// lazy_static! {
// static ref THREAD_RNG_STATE : Vec<u64> = {
// match StdRng::new() {
// Ok(mut r) => r.gen_iter::<u64>().take(16).collect::<Vec<u64>>(),
// Err(e) => panic!("could not initialize seeding rng: {}", e)
// }
// };
// static ref THREAD_RNG_INSTANCE : AtomicUsize = AtomicUsize::new(0);
// };

let mut rng:T = SeedableRng::from_seed(&(*THREAD_RNG_STATE)[..]);
rng.jump((*THREAD_RNG_INSTANCE).fetch_add(1, Ordering::SeqCst));
// let mut rng:T = SeedableRng::from_seed(&(*THREAD_RNG_STATE)[..]);
// rng.jump((*THREAD_RNG_INSTANCE).fetch_add(1, Ordering::SeqCst));

rng
}
// rng
// }


// Taken from the lib.rs in the rand crate.
Expand Down
37 changes: 25 additions & 12 deletions src/splitmix64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@

//! The `SplitMix64` random number generator.

use std::mem;
use std::num::Wrapping as w;
use rand::{Rand, Rng, SeedableRng};
use rand::Rng;
use rand_core::{Error, SeedableRng, RngCore, impls};

/// A random number generator that uses the splitmix64 algorithm [1].
///
Expand Down Expand Up @@ -37,7 +39,7 @@ use rand::{Rand, Rng, SeedableRng};
#[derive(Copy, Clone)]
pub struct SplitMix64(u64);

impl Rng for SplitMix64 {
impl RngCore for SplitMix64 {
#[inline]
fn next_u32(&mut self) -> u32 {
self.next_u64() as u32
Expand All @@ -51,24 +53,35 @@ impl Rng for SplitMix64 {
z = (z ^ (z >> 27)) * w(0x94D049BB133111EB_u64);
(z ^ (z >> 31)).0
}
}

impl SeedableRng<u64> for SplitMix64 {
fn reseed(&mut self, seed: u64) {
self.0 = seed;
#[inline]
fn fill_bytes(&mut self, dest: &mut [u8]) {
impls::fill_bytes_via_next(self, dest)
}

fn from_seed(seed: u64) -> SplitMix64 {
SplitMix64(seed)
fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
Ok(self.fill_bytes(dest))
}
}

impl Rand for SplitMix64 {
fn rand<R: Rng>(other: &mut R) -> SplitMix64 {
SeedableRng::from_seed(other.gen())
impl SplitMix64 {
pub fn new(seed: u64) -> Self {
SplitMix64(seed)
}
}

impl SeedableRng for SplitMix64 {
type Seed = [u8; 8];

fn from_seed(seed: Self::Seed) -> Self {
let u64_seed = unsafe { mem::transmute(seed) };
SplitMix64::new(u64_seed)
}

fn from_rng<R: RngCore>(mut rng: R) -> Result<Self, Error> {
Ok(SplitMix64(rng.gen()))
}
}

#[cfg(test)]
mod tests {
Expand Down Expand Up @@ -130,7 +143,7 @@ mod tests {
14635952304031724449,
15419692541594102413];

let mut rng: SplitMix64 = SeedableRng::from_seed(seed);
let mut rng = SplitMix64::new(seed);
let vals = rng.gen_iter::<u64>().take(t_vals.len()).collect::<Vec<u64>>();
assert!(::test::iter_eq(t_vals, vals));
}
Expand Down
53 changes: 28 additions & 25 deletions src/xoroshiro128.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@

//! The Xoroshiro128+ random number generator.

use std::mem;
use std::num::Wrapping as w;

use rand::{Rand, Rng, SeedableRng};
use rand::Rng;
use rand_core::{Error, SeedableRng, RngCore, impls};

use RngJump;

const STATE_SIZE: usize = 2;

/// A random number generator that uses the xoroshiro128+ algorithm [1].
///
/// # Description
Expand Down Expand Up @@ -50,15 +50,14 @@ const STATE_SIZE: usize = 2;
#[derive(Copy, Clone)]
pub struct Xoroshiro128([u64; 2]);

static EMPTY: Xoroshiro128 = Xoroshiro128([0, 0]);
static JUMP: [u64; 2] = [0xbeac0467eba5facb, 0xd86b048b86aa9922];

#[inline]
fn rotl(x: u64, k: i32) -> u64 {
(x << k) | (x >> (64 - k))
}

impl Rng for Xoroshiro128 {
impl RngCore for Xoroshiro128 {
fn next_u32(&mut self) -> u32 {
self.next_u64() as u32
}
Expand All @@ -75,34 +74,38 @@ impl Rng for Xoroshiro128 {

result.0
}
}

impl<'a> SeedableRng<&'a [u64]> for Xoroshiro128 {
fn reseed(&mut self, seed: &'a [u64]) {
if seed.len() < 2 {
panic!("Xoroshiro128 seed needs at least two u64s for seeding.");
}
self.0[0] = seed[0];
self.0[1] = seed[1];
#[inline]
fn fill_bytes(&mut self, dest: &mut [u8]) {
impls::fill_bytes_via_next(self, dest)
}

fn from_seed(seed: &'a [u64]) -> Xoroshiro128 {
let mut rng = EMPTY;
rng.reseed(seed);
rng
fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
Ok(self.fill_bytes(dest))
}

}

impl Rand for Xoroshiro128 {
fn rand<R: Rng>(other: &mut R) -> Xoroshiro128 {
let mut key: [u64; STATE_SIZE] = [0; STATE_SIZE];
for word in &mut key {
*word = other.gen();
}
SeedableRng::from_seed(&key[..])
impl Xoroshiro128 {
pub fn new(seed: [u64; 2]) -> Self {
Xoroshiro128(seed)
}
}

impl SeedableRng for Xoroshiro128 {
type Seed = [u8; 16];

fn from_seed(seed: Self::Seed) -> Self {
let u64_seed = unsafe { mem::transmute(seed) };
Xoroshiro128(u64_seed)
}

fn from_rng<R: RngCore>(mut rng: R) -> Result<Self, Error> {
Ok(Xoroshiro128([rng.gen(), rng.gen()]))
}

}

impl RngJump for Xoroshiro128 {
fn jump(&mut self, count: usize) {
for _ in 0..count {
Expand Down Expand Up @@ -186,7 +189,7 @@ mod tests {
6715575954761285513];

let states = [seed, seed];
let mut rng: Xoroshiro128 = SeedableRng::from_seed(&states[..]);
let mut rng = Xoroshiro128::new(states);
let vals = rng.gen_iter::<u64>().take(t_vals.len()).collect::<Vec<u64>>();
assert!(::test::iter_eq(t_vals, vals));
}
Expand Down
74 changes: 46 additions & 28 deletions src/xorshift1024.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@

#![cfg_attr(feature = "cargo-clippy", allow(needless_range_loop))]

use std::mem;
use std::num::Wrapping as w;

use rand::{Rand, Rng, SeedableRng};
use rand::Rng;
use rand_core::{Error, SeedableRng, RngCore, impls};

use RngJump;

const STATE_SIZE: usize = 16;

/// A random number generator that uses the xorshift1024* algorithm [1].
///
/// # Description
Expand Down Expand Up @@ -47,10 +47,10 @@ pub struct Xorshift1024 {
p: usize,
}

static EMPTY: Xorshift1024 = Xorshift1024 {
state: [0; 16],
p: 0,
};
// A newtype is used so that the required Default and AsMut<[u8]> traits
// can be implemented for SeedableRng::Seed.
pub struct U8Seed(pub [u8; 128]);

static JUMP: [u64; 16] = [0x84242f96eca9c41d,
0xa3c65b8776f96855,
0x5b34a39f070b5837,
Expand All @@ -70,7 +70,7 @@ static JUMP: [u64; 16] = [0x84242f96eca9c41d,



impl Rng for Xorshift1024 {
impl RngCore for Xorshift1024 {
#[inline]
fn next_u32(&mut self) -> u32 {
self.next_u64() as u32
Expand All @@ -87,34 +87,52 @@ impl Rng for Xorshift1024 {

(w(self.state[self.p]) * w(1181783497276652981_u64)).0
}

#[inline]
fn fill_bytes(&mut self, dest: &mut [u8]) {
impls::fill_bytes_via_next(self, dest)
}

fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
Ok(self.fill_bytes(dest))
}
}

impl<'a> SeedableRng<&'a [u64]> for Xorshift1024 {
fn reseed(&mut self, seed: &'a [u64]) {
if seed.len() < 16 {
panic!("Xorshift1024 seed needs at least 16 u64s for seeding.");
}
impl Xorshift1024 {
pub fn new(seed: [u64; 16]) -> Self {
Xorshift1024 { state: seed, p: 0 }
}
}

for (index, element) in seed.iter().enumerate() {
self.state[index] = *element;
}
impl Default for U8Seed {
fn default() -> Self {
U8Seed([0; 128])
}
}

fn from_seed(seed: &'a [u64]) -> Xorshift1024 {
let mut rng = EMPTY;
rng.reseed(seed);
rng
impl AsMut<[u8]> for U8Seed {
fn as_mut(&mut self) -> &mut [u8] {
&mut self.0
}
}

impl Rand for Xorshift1024 {
fn rand<R: Rng>(other: &mut R) -> Xorshift1024 {
let mut key: [u64; STATE_SIZE] = [0; STATE_SIZE];
for word in &mut key {
*word = other.gen();
}
SeedableRng::from_seed(&key[..])
impl SeedableRng for Xorshift1024 {
type Seed = U8Seed;

fn from_seed(seed: Self::Seed) -> Self {
let u64_seed = unsafe { mem::transmute(seed) };
Xorshift1024::new(u64_seed)
}

fn from_rng<R: RngCore>(mut rng: R) -> Result<Self, Error> {
let seed = [rng.gen(), rng.gen(), rng.gen(), rng.gen(),
rng.gen(), rng.gen(), rng.gen(), rng.gen(),
rng.gen(), rng.gen(), rng.gen(), rng.gen(),
rng.gen(), rng.gen(), rng.gen(), rng.gen()];

Ok(Xorshift1024 { state: seed, p: 0 })
}

}

impl RngJump for Xorshift1024 {
Expand Down Expand Up @@ -200,7 +218,7 @@ mod tests {
14943324017293890156];

let states = [seed; 16];
let mut rng: Xorshift1024 = SeedableRng::from_seed(&states[..]);
let mut rng = Xorshift1024::new(states);
let vals = rng.gen_iter::<u64>().take(t_vals.len()).collect::<Vec<u64>>();
assert!(::test::iter_eq(t_vals, vals));
}
Expand Down
Loading