std::rand: add the StdRng wrapper for a blessed RNG.

This is implemented as a wrapper around another RNG. It is designed
to allow the actual implementation to be changed without changing
the external API (e.g. it currently uses a 64-bit generator on 64-
bit platforms, and a 32-bit one on 32-bit platforms; but one could
imagine that the IsaacRng may be deprecated later, and having this
ability to switch algorithms without having to update the points of
use is convenient.)

This is the recommended general use RNG.
This commit is contained in:
Huon Wilson 2013-09-26 19:08:44 +10:00
parent 39a69d323d
commit f39a215f27

View File

@ -643,8 +643,46 @@ pub trait Rng {
/// available in Rust. If you require a specifically seeded `Rng` for
/// consistency over time you should pick one algorithm and create the
/// `Rng` yourself.
pub fn rng() -> IsaacRng {
IsaacRng::new()
///
/// This is a very expensive operation as it has to read randomness
/// from the operating system and use this in an expensive seeding
/// operation. If one does not require high performance, `task_rng`
/// and/or `random` may be more appropriate.
pub fn rng() -> StdRng {
StdRng::new()
}
/// The standard RNG. This is designed to be efficient on the current
/// platform.
#[cfg(not(target_word_size="64"))]
pub struct StdRng { priv rng: IsaacRng }
/// The standard RNG. This is designed to be efficient on the current
/// platform.
#[cfg(target_word_size="64")]
pub struct StdRng { priv rng: Isaac64Rng }
impl StdRng {
#[cfg(not(target_word_size="64"))]
fn new() -> StdRng {
StdRng { rng: IsaacRng::new() }
}
#[cfg(target_word_size="64")]
fn new() -> StdRng {
StdRng { rng: Isaac64Rng::new() }
}
}
impl Rng for StdRng {
#[inline]
fn next_u32(&mut self) -> u32 {
self.rng.next_u32()
}
#[inline]
fn next_u64(&mut self) -> u64 {
self.rng.next_u64()
}
}
/// Create a weak random number generator with a default algorithm and seed.
@ -728,7 +766,7 @@ pub fn seed(n: uint) -> ~[u8] {
}
// used to make space in TLS for a random number generator
local_data_key!(tls_rng_state: @@mut IsaacRng)
local_data_key!(tls_rng_state: @mut StdRng)
/**
* Gives back a lazily initialized task-local random number generator,
@ -736,15 +774,15 @@ local_data_key!(tls_rng_state: @@mut IsaacRng)
* `task_rng().gen::<int>()`.
*/
#[inline]
pub fn task_rng() -> @mut IsaacRng {
pub fn task_rng() -> @mut StdRng {
let r = local_data::get(tls_rng_state, |k| k.map(|&k| *k));
match r {
None => {
let rng = @@mut IsaacRng::new();
let rng = @mut StdRng::new();
local_data::set(tls_rng_state, rng);
*rng
rng
}
Some(rng) => *rng
Some(rng) => rng
}
}
@ -985,6 +1023,15 @@ mod bench {
bh.bytes = size_of::<uint>() as u64;
}
#[bench]
fn rand_std(bh: &mut BenchHarness) {
let mut rng = StdRng::new();
do bh.iter {
rng.gen::<uint>();
}
bh.bytes = size_of::<uint>() as u64;
}
#[bench]
fn rand_shuffle_100(bh: &mut BenchHarness) {
let mut rng = XorShiftRng::new();