rollup merge of #20483: nagisa/rng-copy

* Implement (derive) `Clone` for `ChaChaRng`, `Isaac*Rng`, `StdRng` and `ThreadRng`;
* Derive `XorShiftRng` `Clone` implementation instead of implementing it explicitly.

`OsRng` is the only Rng which does not implement `Clone` or `Copy` after this patch because of its dependence on `Reader`.

r? @huonw I guess?
This commit is contained in:
Alex Crichton 2015-01-05 18:37:18 -08:00
commit ca40fe0f5e
4 changed files with 40 additions and 15 deletions

View File

@ -12,7 +12,6 @@
use core::prelude::*;
use core::num::Int;
use {Rng, SeedableRng, Rand};
const KEY_WORDS : uint = 8; // 8 words for the 256-bit key
@ -28,8 +27,7 @@ const CHACHA_ROUNDS: uint = 20; // Cryptographically secure from 8 upwards as of
///
/// [1]: D. J. Bernstein, [*ChaCha, a variant of
/// Salsa20*](http://cr.yp.to/chacha.html)
#[derive(Copy)]
#[deriving(Copy, Clone)]
pub struct ChaChaRng {
buffer: [u32; STATE_WORDS], // Internal buffer of output
state: [u32; STATE_WORDS], // Initial state
@ -283,5 +281,15 @@ mod test {
0x11cfa18e, 0xd3c50049, 0x75c775f6, 0x434c6530,
0x2c5bad8f, 0x898881dc, 0x5f1c86d9, 0xc1f8e7f4));
}
#[test]
fn test_rng_clone() {
let seed : &[_] = &[0u32, ..8];
let mut rng: ChaChaRng = SeedableRng::from_seed(seed);
let mut clone = rng.clone();
for _ in range(0u, 16) {
assert_eq!(rng.next_u64(), clone.next_u64());
}
}
}

View File

@ -179,6 +179,13 @@ impl IsaacRng {
}
}
// 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 {
@ -415,6 +422,13 @@ impl Isaac64Rng {
}
}
// 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]
@ -485,6 +499,7 @@ impl Rand for Isaac64Rng {
}
}
#[cfg(test)]
mod test {
use std::prelude::v1::*;
@ -594,4 +609,14 @@ mod test {
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());
}
}
}

View File

@ -385,6 +385,7 @@ pub trait SeedableRng<Seed>: Rng {
/// RNGs"](http://www.jstatsoft.org/v08/i14/paper). *Journal of
/// Statistical Software*. Vol. 8 (Issue 14).
#[allow(missing_copy_implementations)]
#[deriving(Clone)]
pub struct XorShiftRng {
x: u32,
y: u32,
@ -392,17 +393,6 @@ pub struct XorShiftRng {
w: u32,
}
impl Clone for XorShiftRng {
fn clone(&self) -> XorShiftRng {
XorShiftRng {
x: self.x,
y: self.y,
z: self.z,
w: self.w,
}
}
}
impl XorShiftRng {
/// Creates a new XorShiftRng instance which is not seeded.
///
@ -507,6 +497,7 @@ pub struct Closed01<F>(pub F);
#[cfg(not(test))]
mod std {
pub use core::{option, fmt}; // panic!()
pub use core::clone; // derive Clone
pub use core::kinds;
}

View File

@ -245,7 +245,7 @@ pub mod reader;
/// The standard RNG. This is designed to be efficient on the current
/// platform.
#[derive(Copy)]
#[deriving(Copy, Clone)]
pub struct StdRng {
rng: IsaacWordRng,
}
@ -322,6 +322,7 @@ static THREAD_RNG_RESEED_THRESHOLD: uint = 32_768;
type ThreadRngInner = reseeding::ReseedingRng<StdRng, ThreadRngReseeder>;
/// The thread-local RNG.
#[deriving(Clone)]
pub struct ThreadRng {
rng: Rc<RefCell<ThreadRngInner>>,
}