Skip to content

Commit f39a215

Browse files
committed
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.
1 parent 39a69d3 commit f39a215

File tree

1 file changed

+54
-7
lines changed

1 file changed

+54
-7
lines changed

src/libstd/rand/mod.rs

Lines changed: 54 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -643,8 +643,46 @@ pub trait Rng {
643643
/// available in Rust. If you require a specifically seeded `Rng` for
644644
/// consistency over time you should pick one algorithm and create the
645645
/// `Rng` yourself.
646-
pub fn rng() -> IsaacRng {
647-
IsaacRng::new()
646+
///
647+
/// This is a very expensive operation as it has to read randomness
648+
/// from the operating system and use this in an expensive seeding
649+
/// operation. If one does not require high performance, `task_rng`
650+
/// and/or `random` may be more appropriate.
651+
pub fn rng() -> StdRng {
652+
StdRng::new()
653+
}
654+
655+
/// The standard RNG. This is designed to be efficient on the current
656+
/// platform.
657+
#[cfg(not(target_word_size="64"))]
658+
pub struct StdRng { priv rng: IsaacRng }
659+
660+
/// The standard RNG. This is designed to be efficient on the current
661+
/// platform.
662+
#[cfg(target_word_size="64")]
663+
pub struct StdRng { priv rng: Isaac64Rng }
664+
665+
impl StdRng {
666+
#[cfg(not(target_word_size="64"))]
667+
fn new() -> StdRng {
668+
StdRng { rng: IsaacRng::new() }
669+
}
670+
#[cfg(target_word_size="64")]
671+
fn new() -> StdRng {
672+
StdRng { rng: Isaac64Rng::new() }
673+
}
674+
}
675+
676+
impl Rng for StdRng {
677+
#[inline]
678+
fn next_u32(&mut self) -> u32 {
679+
self.rng.next_u32()
680+
}
681+
682+
#[inline]
683+
fn next_u64(&mut self) -> u64 {
684+
self.rng.next_u64()
685+
}
648686
}
649687

650688
/// Create a weak random number generator with a default algorithm and seed.
@@ -728,23 +766,23 @@ pub fn seed(n: uint) -> ~[u8] {
728766
}
729767

730768
// used to make space in TLS for a random number generator
731-
local_data_key!(tls_rng_state: @@mut IsaacRng)
769+
local_data_key!(tls_rng_state: @mut StdRng)
732770

733771
/**
734772
* Gives back a lazily initialized task-local random number generator,
735773
* seeded by the system. Intended to be used in method chaining style, ie
736774
* `task_rng().gen::<int>()`.
737775
*/
738776
#[inline]
739-
pub fn task_rng() -> @mut IsaacRng {
777+
pub fn task_rng() -> @mut StdRng {
740778
let r = local_data::get(tls_rng_state, |k| k.map(|&k| *k));
741779
match r {
742780
None => {
743-
let rng = @@mut IsaacRng::new();
781+
let rng = @mut StdRng::new();
744782
local_data::set(tls_rng_state, rng);
745-
*rng
783+
rng
746784
}
747-
Some(rng) => *rng
785+
Some(rng) => rng
748786
}
749787
}
750788

@@ -985,6 +1023,15 @@ mod bench {
9851023
bh.bytes = size_of::<uint>() as u64;
9861024
}
9871025

1026+
#[bench]
1027+
fn rand_std(bh: &mut BenchHarness) {
1028+
let mut rng = StdRng::new();
1029+
do bh.iter {
1030+
rng.gen::<uint>();
1031+
}
1032+
bh.bytes = size_of::<uint>() as u64;
1033+
}
1034+
9881035
#[bench]
9891036
fn rand_shuffle_100(bh: &mut BenchHarness) {
9901037
let mut rng = XorShiftRng::new();

0 commit comments

Comments
 (0)