std: Recreate a rand
module
This commit shuffles around some of the `rand` code, along with some reorganization. The new state of the world is as follows: * The librand crate now only depends on libcore. This interface is experimental. * The standard library has a new module, `std::rand`. This interface will eventually become stable. Unfortunately, this entailed more of a breaking change than just shuffling some names around. The following breaking changes were made to the rand library: * Rng::gen_vec() was removed. This has been replaced with Rng::gen_iter() which will return an infinite stream of random values. Previous behavior can be regained with `rng.gen_iter().take(n).collect()` * Rng::gen_ascii_str() was removed. This has been replaced with Rng::gen_ascii_chars() which will return an infinite stream of random ascii characters. Similarly to gen_iter(), previous behavior can be emulated with `rng.gen_ascii_chars().take(n).collect()` * {IsaacRng, Isaac64Rng, XorShiftRng}::new() have all been removed. These all relied on being able to use an OSRng for seeding, but this is no longer available in librand (where these types are defined). To retain the same functionality, these types now implement the `Rand` trait so they can be generated with a random seed from another random number generator. This allows the stdlib to use an OSRng to create seeded instances of these RNGs. * Rand implementations for `Box<T>` and `@T` were removed. These seemed to be pretty rare in the codebase, and it allows for librand to not depend on liballoc. Additionally, other pointer types like Rc<T> and Arc<T> were not supported. If this is undesirable, librand can depend on liballoc and regain these implementations. * The WeightedChoice structure is no longer built with a `Vec<Weighted<T>>`, but rather a `&mut [Weighted<T>]`. This means that the WeightedChoice structure now has a lifetime associated with it. * The `sample` method on `Rng` has been moved to a top-level function in the `rand` module due to its dependence on `Vec`. cc #13851 [breaking-change]
This commit is contained in:
parent
bee4e6adac
commit
925ff65118
47 changed files with 963 additions and 844 deletions
13
mk/crates.mk
13
mk/crates.mk
|
@ -60,9 +60,9 @@ DEPS_core :=
|
|||
DEPS_rlibc :=
|
||||
DEPS_alloc := core libc native:jemalloc
|
||||
DEPS_debug := std
|
||||
DEPS_std := core libc alloc native:rustrt native:backtrace
|
||||
DEPS_std := core rand libc alloc native:rustrt native:backtrace
|
||||
DEPS_graphviz := std
|
||||
DEPS_green := std rand native:context_switch
|
||||
DEPS_green := std native:context_switch
|
||||
DEPS_rustuv := std native:uv native:uv_support
|
||||
DEPS_native := std
|
||||
DEPS_syntax := std term serialize collections log fmt_macros debug
|
||||
|
@ -77,16 +77,16 @@ DEPS_glob := std
|
|||
DEPS_serialize := std collections log
|
||||
DEPS_term := std collections log
|
||||
DEPS_semver := std
|
||||
DEPS_uuid := std serialize rand
|
||||
DEPS_uuid := std serialize
|
||||
DEPS_sync := std alloc
|
||||
DEPS_getopts := std
|
||||
DEPS_collections := std rand debug
|
||||
DEPS_collections := std debug
|
||||
DEPS_fourcc := syntax std
|
||||
DEPS_hexfloat := syntax std
|
||||
DEPS_num := std rand
|
||||
DEPS_num := std
|
||||
DEPS_test := std collections getopts serialize term time regex
|
||||
DEPS_time := std serialize sync
|
||||
DEPS_rand := std
|
||||
DEPS_rand := core
|
||||
DEPS_url := std collections
|
||||
DEPS_workcache := std serialize collections log
|
||||
DEPS_log := std sync
|
||||
|
@ -104,6 +104,7 @@ TOOL_SOURCE_rustc := $(S)src/driver/driver.rs
|
|||
ONLY_RLIB_core := 1
|
||||
ONLY_RLIB_rlibc := 1
|
||||
ONLY_RLIB_alloc := 1
|
||||
ONLY_RLIB_rand := 1
|
||||
|
||||
################################################################################
|
||||
# You should not need to edit below this line
|
||||
|
|
|
@ -329,10 +329,10 @@ Here is a small example showing how to use Arcs. We wish to run concurrently sev
|
|||
a single large vector of floats. Each task needs the full vector to perform its duty.
|
||||
|
||||
~~~
|
||||
extern crate rand;
|
||||
extern crate sync;
|
||||
|
||||
use sync::Arc;
|
||||
use std::rand;
|
||||
|
||||
fn pnorm(nums: &[f64], p: uint) -> f64 {
|
||||
nums.iter().fold(0.0, |a, b| a + b.powf(p as f64)).powf(1.0 / (p as f64))
|
||||
|
@ -358,7 +358,7 @@ created by the line
|
|||
|
||||
~~~
|
||||
# extern crate sync;
|
||||
# extern crate rand;
|
||||
# use std::rand;
|
||||
# use sync::Arc;
|
||||
# fn main() {
|
||||
# let numbers = Vec::from_fn(1000000, |_| rand::random::<f64>());
|
||||
|
@ -372,7 +372,7 @@ reference to the underlying vector as if it were local.
|
|||
|
||||
~~~
|
||||
# extern crate sync;
|
||||
# extern crate rand;
|
||||
# use std::rand;
|
||||
# use sync::Arc;
|
||||
# fn pnorm(nums: &[f64], p: uint) -> f64 { 4.0 }
|
||||
# fn main() {
|
||||
|
|
|
@ -980,8 +980,8 @@ mod tests {
|
|||
use bitv;
|
||||
|
||||
use std::uint;
|
||||
use rand;
|
||||
use rand::Rng;
|
||||
use std::rand;
|
||||
use std::rand::Rng;
|
||||
|
||||
static BENCH_BITS : uint = 1 << 14;
|
||||
|
||||
|
|
|
@ -44,8 +44,8 @@ pub mod bench {
|
|||
extern crate test;
|
||||
use self::test::Bencher;
|
||||
use std::container::MutableMap;
|
||||
use rand;
|
||||
use rand::Rng;
|
||||
use std::rand;
|
||||
use std::rand::Rng;
|
||||
|
||||
pub fn insert_rand_n<M:MutableMap<uint,uint>>(n: uint,
|
||||
map: &mut M,
|
||||
|
|
|
@ -610,7 +610,7 @@ mod tests {
|
|||
extern crate test;
|
||||
use self::test::Bencher;
|
||||
use deque::Deque;
|
||||
use rand;
|
||||
use std::rand;
|
||||
use super::{DList, Node, ListInsertion};
|
||||
|
||||
pub fn check_links<T>(list: &DList<T>) {
|
||||
|
|
|
@ -24,8 +24,8 @@ use std::iter::{range, range_inclusive};
|
|||
use std::mem::replace;
|
||||
use std::num;
|
||||
use std::option::{Option, Some, None};
|
||||
use rand;
|
||||
use rand::Rng;
|
||||
use std::rand;
|
||||
use std::rand::Rng;
|
||||
use std::result::{Ok, Err};
|
||||
use std::slice::ImmutableVector;
|
||||
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
|
||||
#![deny(deprecated_owned_vector)]
|
||||
|
||||
extern crate rand;
|
||||
extern crate debug;
|
||||
|
||||
#[cfg(test)] extern crate test;
|
||||
|
|
|
@ -1000,8 +1000,8 @@ impl<T: TotalOrd> Extendable<T> for TreeSet<T> {
|
|||
mod test_treemap {
|
||||
use super::{TreeMap, TreeNode};
|
||||
|
||||
use rand::Rng;
|
||||
use rand;
|
||||
use std::rand::Rng;
|
||||
use std::rand;
|
||||
|
||||
#[test]
|
||||
fn find_empty() {
|
||||
|
|
|
@ -915,7 +915,7 @@ mod test_map {
|
|||
mod bench_map {
|
||||
extern crate test;
|
||||
use super::TrieMap;
|
||||
use rand::{weak_rng, Rng};
|
||||
use std::rand::{weak_rng, Rng};
|
||||
use self::test::Bencher;
|
||||
|
||||
#[bench]
|
||||
|
|
|
@ -119,7 +119,7 @@ mod tests {
|
|||
use prelude::*;
|
||||
use super::*;
|
||||
use realstd::owned::{Box, AnyOwnExt};
|
||||
use realstd::str::{Str, StrAllocating};
|
||||
use realstd::str::Str;
|
||||
|
||||
#[deriving(Eq, Show)]
|
||||
struct Test;
|
||||
|
|
|
@ -607,7 +607,7 @@ mod test {
|
|||
use slice::ImmutableVector;
|
||||
use option::{Some, None};
|
||||
use realstd::string::String;
|
||||
use realstd::str::{Str, StrAllocating};
|
||||
use realstd::str::Str;
|
||||
|
||||
#[test]
|
||||
fn test_is_lowercase() {
|
||||
|
|
|
@ -596,7 +596,6 @@ pub fn argument<'a, T>(f: extern "Rust" fn(&T, &mut Formatter) -> Result,
|
|||
#[cfg(test)]
|
||||
pub fn format(args: &Arguments) -> ::realstd::string::String {
|
||||
use str;
|
||||
use realstd::str::StrAllocating;
|
||||
use realstd::io::MemWriter;
|
||||
|
||||
fn mywrite<T: ::realstd::io::Writer>(t: &mut T, b: &[u8]) {
|
||||
|
|
|
@ -194,7 +194,7 @@ mod tests {
|
|||
use fmt::radix;
|
||||
use super::{Binary, Octal, Decimal, LowerHex, UpperHex};
|
||||
use super::{GenericRadix, Radix};
|
||||
use realstd::str::{Str, StrAllocating};
|
||||
use realstd::str::Str;
|
||||
|
||||
#[test]
|
||||
fn test_radix_base() {
|
||||
|
@ -399,35 +399,35 @@ mod bench {
|
|||
mod uint {
|
||||
use super::test::Bencher;
|
||||
use fmt::radix;
|
||||
use rand::{XorShiftRng, Rng};
|
||||
use realstd::rand::{weak_rng, Rng};
|
||||
|
||||
#[bench]
|
||||
fn format_bin(b: &mut Bencher) {
|
||||
let mut rng = XorShiftRng::new().unwrap();
|
||||
let mut rng = weak_rng();
|
||||
b.iter(|| { format!("{:t}", rng.gen::<uint>()); })
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn format_oct(b: &mut Bencher) {
|
||||
let mut rng = XorShiftRng::new().unwrap();
|
||||
let mut rng = weak_rng();
|
||||
b.iter(|| { format!("{:o}", rng.gen::<uint>()); })
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn format_dec(b: &mut Bencher) {
|
||||
let mut rng = XorShiftRng::new().unwrap();
|
||||
let mut rng = weak_rng();
|
||||
b.iter(|| { format!("{:u}", rng.gen::<uint>()); })
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn format_hex(b: &mut Bencher) {
|
||||
let mut rng = XorShiftRng::new().unwrap();
|
||||
let mut rng = weak_rng();
|
||||
b.iter(|| { format!("{:x}", rng.gen::<uint>()); })
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn format_base_36(b: &mut Bencher) {
|
||||
let mut rng = XorShiftRng::new().unwrap();
|
||||
let mut rng = weak_rng();
|
||||
b.iter(|| { format!("{}", radix(rng.gen::<uint>(), 36)); })
|
||||
}
|
||||
}
|
||||
|
@ -435,35 +435,35 @@ mod bench {
|
|||
mod int {
|
||||
use super::test::Bencher;
|
||||
use fmt::radix;
|
||||
use rand::{XorShiftRng, Rng};
|
||||
use realstd::rand::{weak_rng, Rng};
|
||||
|
||||
#[bench]
|
||||
fn format_bin(b: &mut Bencher) {
|
||||
let mut rng = XorShiftRng::new().unwrap();
|
||||
let mut rng = weak_rng();
|
||||
b.iter(|| { format!("{:t}", rng.gen::<int>()); })
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn format_oct(b: &mut Bencher) {
|
||||
let mut rng = XorShiftRng::new().unwrap();
|
||||
let mut rng = weak_rng();
|
||||
b.iter(|| { format!("{:o}", rng.gen::<int>()); })
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn format_dec(b: &mut Bencher) {
|
||||
let mut rng = XorShiftRng::new().unwrap();
|
||||
let mut rng = weak_rng();
|
||||
b.iter(|| { format!("{:d}", rng.gen::<int>()); })
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn format_hex(b: &mut Bencher) {
|
||||
let mut rng = XorShiftRng::new().unwrap();
|
||||
let mut rng = weak_rng();
|
||||
b.iter(|| { format!("{:x}", rng.gen::<int>()); })
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn format_base_36(b: &mut Bencher) {
|
||||
let mut rng = XorShiftRng::new().unwrap();
|
||||
let mut rng = weak_rng();
|
||||
b.iter(|| { format!("{}", radix(rng.gen::<int>(), 36)); })
|
||||
}
|
||||
}
|
||||
|
|
|
@ -59,7 +59,6 @@
|
|||
#[cfg(test)] extern crate realcore = "core";
|
||||
#[cfg(test)] extern crate libc;
|
||||
#[cfg(test)] extern crate native;
|
||||
#[cfg(test)] extern crate rand;
|
||||
#[cfg(test)] extern crate realstd = "std";
|
||||
|
||||
#[cfg(test)] pub use cmp = realcore::cmp;
|
||||
|
|
|
@ -637,11 +637,10 @@ pub fn fold_<T,E,Iter:Iterator<Result<T,E>>>(iterator: Iter) -> Result<(),E> {
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use realstd::vec::Vec;
|
||||
use realstd::string::String;
|
||||
|
||||
use result::{collect, fold, fold_};
|
||||
use prelude::*;
|
||||
use realstd::str::{Str, StrAllocating};
|
||||
use realstd::str::Str;
|
||||
use iter::range;
|
||||
|
||||
pub fn op1() -> Result<int, &'static str> { Ok(666) }
|
||||
|
|
|
@ -294,7 +294,7 @@ mod tests {
|
|||
use super::*;
|
||||
use clone::Clone;
|
||||
use cmp::*;
|
||||
use realstd::str::{Str, StrAllocating};
|
||||
use realstd::str::Str;
|
||||
|
||||
#[test]
|
||||
fn test_clone() {
|
||||
|
|
|
@ -108,10 +108,9 @@ pub fn inflate_bytes_zlib(bytes: &[u8]) -> Option<CVec<u8>> {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
extern crate rand;
|
||||
|
||||
use super::{inflate_bytes, deflate_bytes};
|
||||
use self::rand::Rng;
|
||||
use std::rand;
|
||||
use std::rand::Rng;
|
||||
|
||||
#[test]
|
||||
#[allow(deprecated_owned_vector)]
|
||||
|
@ -120,7 +119,8 @@ mod tests {
|
|||
let mut words = vec!();
|
||||
for _ in range(0, 20) {
|
||||
let range = r.gen_range(1u, 10);
|
||||
words.push(r.gen_vec::<u8>(range));
|
||||
let v = r.gen_iter::<u8>().take(range).collect::<Vec<u8>>();
|
||||
words.push(v);
|
||||
}
|
||||
for _ in range(0, 20) {
|
||||
let mut input = vec![];
|
||||
|
|
|
@ -212,7 +212,6 @@
|
|||
|
||||
#[cfg(test)] #[phase(syntax, link)] extern crate log;
|
||||
#[cfg(test)] extern crate rustuv;
|
||||
extern crate rand;
|
||||
extern crate libc;
|
||||
extern crate alloc;
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ use std::sync::deque;
|
|||
use std::unstable::mutex::NativeMutex;
|
||||
use std::raw;
|
||||
|
||||
use rand::{XorShiftRng, Rng, Rand};
|
||||
use std::rand::{XorShiftRng, Rng, Rand};
|
||||
|
||||
use TaskState;
|
||||
use context::Context;
|
||||
|
@ -977,8 +977,9 @@ impl ClosureConverter for UnsafeTaskReceiver {
|
|||
// worry there.
|
||||
#[cfg(windows)]
|
||||
fn new_sched_rng() -> XorShiftRng {
|
||||
match XorShiftRng::new() {
|
||||
Ok(r) => r,
|
||||
use std::rand::OSRng;
|
||||
match OSRng::new() {
|
||||
Ok(mut r) => r.gen(),
|
||||
Err(e) => {
|
||||
rtabort!("sched: failed to create seeded RNG: {}", e)
|
||||
}
|
||||
|
@ -988,7 +989,7 @@ fn new_sched_rng() -> XorShiftRng {
|
|||
fn new_sched_rng() -> XorShiftRng {
|
||||
use libc;
|
||||
use std::mem;
|
||||
use rand::SeedableRng;
|
||||
use std::rand::SeedableRng;
|
||||
|
||||
let fd = "/dev/urandom".with_c_str(|name| {
|
||||
unsafe { libc::open(name, libc::O_RDONLY, 0) }
|
||||
|
|
|
@ -1372,7 +1372,7 @@ mod biguint_tests {
|
|||
use std::num::{Zero, One, FromStrRadix, ToStrRadix};
|
||||
use std::num::{ToPrimitive, FromPrimitive};
|
||||
use std::num::CheckedDiv;
|
||||
use rand::{task_rng};
|
||||
use std::rand::task_rng;
|
||||
use std::u64;
|
||||
|
||||
#[test]
|
||||
|
@ -2220,7 +2220,7 @@ mod bigint_tests {
|
|||
use std::num::CheckedDiv;
|
||||
use std::num::{Zero, One, FromStrRadix, ToStrRadix};
|
||||
use std::num::{ToPrimitive, FromPrimitive};
|
||||
use rand::{task_rng};
|
||||
use std::rand::task_rng;
|
||||
use std::u64;
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -10,7 +10,8 @@
|
|||
|
||||
//! The exponential distribution.
|
||||
|
||||
use std::num::Float;
|
||||
use core::num::Float;
|
||||
|
||||
use {Rng, Rand};
|
||||
use distributions::{ziggurat, ziggurat_tables, Sample, IndependentSample};
|
||||
|
||||
|
@ -58,7 +59,8 @@ impl Rand for Exp1 {
|
|||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use rand::distributions::{Exp, IndependentSample};
|
||||
/// use std::rand;
|
||||
/// use std::rand::distributions::{Exp, IndependentSample};
|
||||
///
|
||||
/// let exp = Exp::new(2.0);
|
||||
/// let v = exp.ind_sample(&mut rand::task_rng());
|
||||
|
@ -90,14 +92,15 @@ impl IndependentSample<f64> for Exp {
|
|||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use std::prelude::*;
|
||||
|
||||
use distributions::{Sample, IndependentSample};
|
||||
use {Rng, task_rng};
|
||||
use super::Exp;
|
||||
|
||||
#[test]
|
||||
fn test_exp() {
|
||||
let mut exp = Exp::new(10.0);
|
||||
let mut rng = task_rng();
|
||||
let mut rng = ::test::rng();
|
||||
for _ in range(0, 1000) {
|
||||
assert!(exp.sample(&mut rng) >= 0.0);
|
||||
assert!(exp.ind_sample(&mut rng) >= 0.0);
|
||||
|
@ -118,22 +121,24 @@ mod test {
|
|||
#[cfg(test)]
|
||||
mod bench {
|
||||
extern crate test;
|
||||
|
||||
use std::prelude::*;
|
||||
|
||||
use self::test::Bencher;
|
||||
use std::mem::size_of;
|
||||
use {XorShiftRng, RAND_BENCH_N};
|
||||
use super::Exp;
|
||||
use distributions::Sample;
|
||||
|
||||
#[bench]
|
||||
fn rand_exp(b: &mut Bencher) {
|
||||
let mut rng = XorShiftRng::new().unwrap();
|
||||
let mut rng = ::test::weak_rng();
|
||||
let mut exp = Exp::new(2.71828 * 3.14159);
|
||||
|
||||
b.iter(|| {
|
||||
for _ in range(0, RAND_BENCH_N) {
|
||||
for _ in range(0, ::RAND_BENCH_N) {
|
||||
exp.sample(&mut rng);
|
||||
}
|
||||
});
|
||||
b.bytes = size_of::<f64>() as u64 * RAND_BENCH_N;
|
||||
b.bytes = size_of::<f64>() as u64 * ::RAND_BENCH_N;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,8 @@
|
|||
|
||||
//! The Gamma and derived distributions.
|
||||
|
||||
use std::num::Float;
|
||||
use core::num::Float;
|
||||
|
||||
use {Rng, Open01};
|
||||
use super::normal::StandardNormal;
|
||||
use super::{IndependentSample, Sample, Exp};
|
||||
|
@ -34,7 +35,8 @@ use super::{IndependentSample, Sample, Exp};
|
|||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use rand::distributions::{IndependentSample, Gamma};
|
||||
/// use std::rand;
|
||||
/// use std::rand::distributions::{IndependentSample, Gamma};
|
||||
///
|
||||
/// let gamma = Gamma::new(2.0, 5.0);
|
||||
/// let v = gamma.ind_sample(&mut rand::task_rng());
|
||||
|
@ -182,7 +184,8 @@ impl IndependentSample<f64> for GammaLargeShape {
|
|||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use rand::distributions::{ChiSquared, IndependentSample};
|
||||
/// use std::rand;
|
||||
/// use std::rand::distributions::{ChiSquared, IndependentSample};
|
||||
///
|
||||
/// let chi = ChiSquared::new(11.0);
|
||||
/// let v = chi.ind_sample(&mut rand::task_rng());
|
||||
|
@ -238,7 +241,8 @@ impl IndependentSample<f64> for ChiSquared {
|
|||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use rand::distributions::{FisherF, IndependentSample};
|
||||
/// use std::rand;
|
||||
/// use std::rand::distributions::{FisherF, IndependentSample};
|
||||
///
|
||||
/// let f = FisherF::new(2.0, 32.0);
|
||||
/// let v = f.ind_sample(&mut rand::task_rng());
|
||||
|
@ -281,7 +285,8 @@ impl IndependentSample<f64> for FisherF {
|
|||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use rand::distributions::{StudentT, IndependentSample};
|
||||
/// use std::rand;
|
||||
/// use std::rand::distributions::{StudentT, IndependentSample};
|
||||
///
|
||||
/// let t = StudentT::new(11.0);
|
||||
/// let v = t.ind_sample(&mut rand::task_rng());
|
||||
|
@ -315,14 +320,15 @@ impl IndependentSample<f64> for StudentT {
|
|||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use std::prelude::*;
|
||||
|
||||
use distributions::{Sample, IndependentSample};
|
||||
use {Rng, task_rng};
|
||||
use super::{ChiSquared, StudentT, FisherF};
|
||||
|
||||
#[test]
|
||||
fn test_chi_squared_one() {
|
||||
let mut chi = ChiSquared::new(1.0);
|
||||
let mut rng = task_rng();
|
||||
let mut rng = ::test::rng();
|
||||
for _ in range(0, 1000) {
|
||||
chi.sample(&mut rng);
|
||||
chi.ind_sample(&mut rng);
|
||||
|
@ -331,7 +337,7 @@ mod test {
|
|||
#[test]
|
||||
fn test_chi_squared_small() {
|
||||
let mut chi = ChiSquared::new(0.5);
|
||||
let mut rng = task_rng();
|
||||
let mut rng = ::test::rng();
|
||||
for _ in range(0, 1000) {
|
||||
chi.sample(&mut rng);
|
||||
chi.ind_sample(&mut rng);
|
||||
|
@ -340,7 +346,7 @@ mod test {
|
|||
#[test]
|
||||
fn test_chi_squared_large() {
|
||||
let mut chi = ChiSquared::new(30.0);
|
||||
let mut rng = task_rng();
|
||||
let mut rng = ::test::rng();
|
||||
for _ in range(0, 1000) {
|
||||
chi.sample(&mut rng);
|
||||
chi.ind_sample(&mut rng);
|
||||
|
@ -355,7 +361,7 @@ mod test {
|
|||
#[test]
|
||||
fn test_f() {
|
||||
let mut f = FisherF::new(2.0, 32.0);
|
||||
let mut rng = task_rng();
|
||||
let mut rng = ::test::rng();
|
||||
for _ in range(0, 1000) {
|
||||
f.sample(&mut rng);
|
||||
f.ind_sample(&mut rng);
|
||||
|
@ -365,7 +371,7 @@ mod test {
|
|||
#[test]
|
||||
fn test_t() {
|
||||
let mut t = StudentT::new(11.0);
|
||||
let mut rng = task_rng();
|
||||
let mut rng = ::test::rng();
|
||||
for _ in range(0, 1000) {
|
||||
t.sample(&mut rng);
|
||||
t.ind_sample(&mut rng);
|
||||
|
@ -376,36 +382,36 @@ mod test {
|
|||
#[cfg(test)]
|
||||
mod bench {
|
||||
extern crate test;
|
||||
use std::prelude::*;
|
||||
use self::test::Bencher;
|
||||
use std::mem::size_of;
|
||||
use distributions::IndependentSample;
|
||||
use {XorShiftRng, RAND_BENCH_N};
|
||||
use super::Gamma;
|
||||
|
||||
|
||||
#[bench]
|
||||
fn bench_gamma_large_shape(b: &mut Bencher) {
|
||||
let gamma = Gamma::new(10., 1.0);
|
||||
let mut rng = XorShiftRng::new().unwrap();
|
||||
let mut rng = ::test::weak_rng();
|
||||
|
||||
b.iter(|| {
|
||||
for _ in range(0, RAND_BENCH_N) {
|
||||
for _ in range(0, ::RAND_BENCH_N) {
|
||||
gamma.ind_sample(&mut rng);
|
||||
}
|
||||
});
|
||||
b.bytes = size_of::<f64>() as u64 * RAND_BENCH_N;
|
||||
b.bytes = size_of::<f64>() as u64 * ::RAND_BENCH_N;
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_gamma_small_shape(b: &mut Bencher) {
|
||||
let gamma = Gamma::new(0.1, 1.0);
|
||||
let mut rng = XorShiftRng::new().unwrap();
|
||||
let mut rng = ::test::weak_rng();
|
||||
|
||||
b.iter(|| {
|
||||
for _ in range(0, RAND_BENCH_N) {
|
||||
for _ in range(0, ::RAND_BENCH_N) {
|
||||
gamma.ind_sample(&mut rng);
|
||||
}
|
||||
});
|
||||
b.bytes = size_of::<f64>() as u64 * RAND_BENCH_N;
|
||||
b.bytes = size_of::<f64>() as u64 * ::RAND_BENCH_N;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,8 +20,12 @@ that do not need to record state.
|
|||
|
||||
*/
|
||||
|
||||
use std::num;
|
||||
use std::num::CheckedAdd;
|
||||
#![experimental]
|
||||
|
||||
use core::prelude::*;
|
||||
use core::num;
|
||||
use core::num::CheckedAdd;
|
||||
|
||||
use {Rng, Rand};
|
||||
|
||||
pub use self::range::Range;
|
||||
|
@ -89,30 +93,32 @@ pub struct Weighted<T> {
|
|||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use rand::distributions::{Weighted, WeightedChoice, IndependentSample};
|
||||
/// use std::rand;
|
||||
/// use std::rand::distributions::{Weighted, WeightedChoice, IndependentSample};
|
||||
///
|
||||
/// let wc = WeightedChoice::new(vec!(Weighted { weight: 2, item: 'a' },
|
||||
/// Weighted { weight: 4, item: 'b' },
|
||||
/// Weighted { weight: 1, item: 'c' }));
|
||||
/// let mut items = vec!(Weighted { weight: 2, item: 'a' },
|
||||
/// Weighted { weight: 4, item: 'b' },
|
||||
/// Weighted { weight: 1, item: 'c' });
|
||||
/// let wc = WeightedChoice::new(items.as_mut_slice());
|
||||
/// let mut rng = rand::task_rng();
|
||||
/// for _ in range(0, 16) {
|
||||
/// // on average prints 'a' 4 times, 'b' 8 and 'c' twice.
|
||||
/// println!("{}", wc.ind_sample(&mut rng));
|
||||
/// }
|
||||
/// ```
|
||||
pub struct WeightedChoice<T> {
|
||||
items: Vec<Weighted<T>>,
|
||||
pub struct WeightedChoice<'a, T> {
|
||||
items: &'a mut [Weighted<T>],
|
||||
weight_range: Range<uint>
|
||||
}
|
||||
|
||||
impl<T: Clone> WeightedChoice<T> {
|
||||
impl<'a, T: Clone> WeightedChoice<'a, T> {
|
||||
/// Create a new `WeightedChoice`.
|
||||
///
|
||||
/// Fails if:
|
||||
/// - `v` is empty
|
||||
/// - the total weight is 0
|
||||
/// - the total weight is larger than a `uint` can contain.
|
||||
pub fn new(mut items: Vec<Weighted<T>>) -> WeightedChoice<T> {
|
||||
pub fn new<'a>(items: &'a mut [Weighted<T>]) -> WeightedChoice<'a, T> {
|
||||
// strictly speaking, this is subsumed by the total weight == 0 case
|
||||
assert!(!items.is_empty(), "WeightedChoice::new called with no items");
|
||||
|
||||
|
@ -122,9 +128,11 @@ impl<T: Clone> WeightedChoice<T> {
|
|||
// weights so we can binary search. This *could* drop elements
|
||||
// with weight == 0 as an optimisation.
|
||||
for item in items.mut_iter() {
|
||||
running_total = running_total.checked_add(&item.weight)
|
||||
.expect("WeightedChoice::new called with a total weight larger \
|
||||
than a uint can contain");
|
||||
running_total = match running_total.checked_add(&item.weight) {
|
||||
Some(n) => n,
|
||||
None => fail!("WeightedChoice::new called with a total weight \
|
||||
larger than a uint can contain")
|
||||
};
|
||||
|
||||
item.weight = running_total;
|
||||
}
|
||||
|
@ -139,11 +147,11 @@ impl<T: Clone> WeightedChoice<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: Clone> Sample<T> for WeightedChoice<T> {
|
||||
impl<'a, T: Clone> Sample<T> for WeightedChoice<'a, T> {
|
||||
fn sample<R: Rng>(&mut self, rng: &mut R) -> T { self.ind_sample(rng) }
|
||||
}
|
||||
|
||||
impl<T: Clone> IndependentSample<T> for WeightedChoice<T> {
|
||||
impl<'a, T: Clone> IndependentSample<T> for WeightedChoice<'a, T> {
|
||||
fn ind_sample<R: Rng>(&self, rng: &mut R) -> T {
|
||||
// we want to find the first element that has cumulative
|
||||
// weight > sample_weight, which we do by binary since the
|
||||
|
@ -153,8 +161,8 @@ impl<T: Clone> IndependentSample<T> for WeightedChoice<T> {
|
|||
let sample_weight = self.weight_range.ind_sample(rng);
|
||||
|
||||
// short circuit when it's the first item
|
||||
if sample_weight < self.items.get(0).weight {
|
||||
return self.items.get(0).item.clone();
|
||||
if sample_weight < self.items[0].weight {
|
||||
return self.items[0].item.clone();
|
||||
}
|
||||
|
||||
let mut idx = 0;
|
||||
|
@ -169,7 +177,7 @@ impl<T: Clone> IndependentSample<T> for WeightedChoice<T> {
|
|||
// one is exactly the total weight.)
|
||||
while modifier > 1 {
|
||||
let i = idx + modifier / 2;
|
||||
if self.items.get(i).weight <= sample_weight {
|
||||
if self.items[i].weight <= sample_weight {
|
||||
// we're small, so look to the right, but allow this
|
||||
// exact element still.
|
||||
idx = i;
|
||||
|
@ -182,7 +190,7 @@ impl<T: Clone> IndependentSample<T> for WeightedChoice<T> {
|
|||
}
|
||||
modifier /= 2;
|
||||
}
|
||||
return self.items.get(idx + 1).item.clone();
|
||||
return self.items[idx + 1].item.clone();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -247,7 +255,9 @@ fn ziggurat<R:Rng>(
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use {task_rng, Rng, Rand};
|
||||
use std::prelude::*;
|
||||
|
||||
use {Rng, Rand};
|
||||
use super::{RandSample, WeightedChoice, Weighted, Sample, IndependentSample};
|
||||
|
||||
#[deriving(Eq, Show)]
|
||||
|
@ -274,8 +284,8 @@ mod tests {
|
|||
fn test_rand_sample() {
|
||||
let mut rand_sample = RandSample::<ConstRand>;
|
||||
|
||||
assert_eq!(rand_sample.sample(&mut task_rng()), ConstRand(0));
|
||||
assert_eq!(rand_sample.ind_sample(&mut task_rng()), ConstRand(0));
|
||||
assert_eq!(rand_sample.sample(&mut ::test::rng()), ConstRand(0));
|
||||
assert_eq!(rand_sample.ind_sample(&mut ::test::rng()), ConstRand(0));
|
||||
}
|
||||
#[test]
|
||||
fn test_weighted_choice() {
|
||||
|
@ -286,7 +296,8 @@ mod tests {
|
|||
|
||||
macro_rules! t (
|
||||
($items:expr, $expected:expr) => {{
|
||||
let wc = WeightedChoice::new($items);
|
||||
let mut items = $items;
|
||||
let wc = WeightedChoice::new(items.as_mut_slice());
|
||||
let expected = $expected;
|
||||
|
||||
let mut rng = CountingRng { i: 0 };
|
||||
|
@ -332,19 +343,19 @@ mod tests {
|
|||
|
||||
#[test] #[should_fail]
|
||||
fn test_weighted_choice_no_items() {
|
||||
WeightedChoice::<int>::new(vec!());
|
||||
WeightedChoice::<int>::new([]);
|
||||
}
|
||||
#[test] #[should_fail]
|
||||
fn test_weighted_choice_zero_weight() {
|
||||
WeightedChoice::new(vec!(Weighted { weight: 0, item: 0},
|
||||
Weighted { weight: 0, item: 1}));
|
||||
WeightedChoice::new(&mut [Weighted { weight: 0, item: 0},
|
||||
Weighted { weight: 0, item: 1}]);
|
||||
}
|
||||
#[test] #[should_fail]
|
||||
fn test_weighted_choice_weight_overflows() {
|
||||
let x = (-1) as uint / 2; // x + x + 2 is the overflow
|
||||
WeightedChoice::new(vec!(Weighted { weight: x, item: 0 },
|
||||
Weighted { weight: 1, item: 1 },
|
||||
Weighted { weight: x, item: 2 },
|
||||
Weighted { weight: 1, item: 3 }));
|
||||
WeightedChoice::new(&mut [Weighted { weight: x, item: 0 },
|
||||
Weighted { weight: 1, item: 1 },
|
||||
Weighted { weight: x, item: 2 },
|
||||
Weighted { weight: 1, item: 3 }]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,8 @@
|
|||
|
||||
//! The normal and derived distributions.
|
||||
|
||||
use std::num::Float;
|
||||
use core::num::Float;
|
||||
|
||||
use {Rng, Rand, Open01};
|
||||
use distributions::{ziggurat, ziggurat_tables, Sample, IndependentSample};
|
||||
|
||||
|
@ -74,7 +75,8 @@ impl Rand for StandardNormal {
|
|||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use rand::distributions::{Normal, IndependentSample};
|
||||
/// use std::rand;
|
||||
/// use std::rand::distributions::{Normal, IndependentSample};
|
||||
///
|
||||
/// // mean 2, standard deviation 3
|
||||
/// let normal = Normal::new(2.0, 3.0);
|
||||
|
@ -116,7 +118,8 @@ impl IndependentSample<f64> for Normal {
|
|||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use rand::distributions::{LogNormal, IndependentSample};
|
||||
/// use std::rand;
|
||||
/// use std::rand::distributions::{LogNormal, IndependentSample};
|
||||
///
|
||||
/// // mean 2, standard deviation 3
|
||||
/// let log_normal = LogNormal::new(2.0, 3.0);
|
||||
|
@ -146,14 +149,15 @@ impl IndependentSample<f64> for LogNormal {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::prelude::*;
|
||||
|
||||
use distributions::{Sample, IndependentSample};
|
||||
use {Rng, task_rng};
|
||||
use super::{Normal, LogNormal};
|
||||
|
||||
#[test]
|
||||
fn test_normal() {
|
||||
let mut norm = Normal::new(10.0, 10.0);
|
||||
let mut rng = task_rng();
|
||||
let mut rng = ::test::rng();
|
||||
for _ in range(0, 1000) {
|
||||
norm.sample(&mut rng);
|
||||
norm.ind_sample(&mut rng);
|
||||
|
@ -169,7 +173,7 @@ mod tests {
|
|||
#[test]
|
||||
fn test_log_normal() {
|
||||
let mut lnorm = LogNormal::new(10.0, 10.0);
|
||||
let mut rng = task_rng();
|
||||
let mut rng = ::test::rng();
|
||||
for _ in range(0, 1000) {
|
||||
lnorm.sample(&mut rng);
|
||||
lnorm.ind_sample(&mut rng);
|
||||
|
@ -185,22 +189,22 @@ mod tests {
|
|||
#[cfg(test)]
|
||||
mod bench {
|
||||
extern crate test;
|
||||
use std::prelude::*;
|
||||
use self::test::Bencher;
|
||||
use std::mem::size_of;
|
||||
use {XorShiftRng, RAND_BENCH_N};
|
||||
use distributions::{Sample};
|
||||
use super::Normal;
|
||||
|
||||
#[bench]
|
||||
fn rand_normal(b: &mut Bencher) {
|
||||
let mut rng = XorShiftRng::new().unwrap();
|
||||
let mut rng = ::test::weak_rng();
|
||||
let mut normal = Normal::new(-2.71828, 3.14159);
|
||||
|
||||
b.iter(|| {
|
||||
for _ in range(0, RAND_BENCH_N) {
|
||||
for _ in range(0, ::RAND_BENCH_N) {
|
||||
normal.sample(&mut rng);
|
||||
}
|
||||
});
|
||||
b.bytes = size_of::<f64>() as u64 * RAND_BENCH_N;
|
||||
b.bytes = size_of::<f64>() as u64 * ::RAND_BENCH_N;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,9 @@
|
|||
|
||||
// this is surprisingly complicated to be both generic & correct
|
||||
|
||||
use std::num::Bounded;
|
||||
use core::prelude::*;
|
||||
use core::num::Bounded;
|
||||
|
||||
use Rng;
|
||||
use distributions::{Sample, IndependentSample};
|
||||
|
||||
|
@ -33,7 +35,8 @@ use distributions::{Sample, IndependentSample};
|
|||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use rand::distributions::{IndependentSample, Range};
|
||||
/// use std::rand;
|
||||
/// use std::rand::distributions::{IndependentSample, Range};
|
||||
///
|
||||
/// fn main() {
|
||||
/// let between = Range::new(10u, 10000u);
|
||||
|
@ -161,8 +164,8 @@ float_impl! { f64 }
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::prelude::*;
|
||||
use distributions::{Sample, IndependentSample};
|
||||
use {Rng, task_rng};
|
||||
use super::Range;
|
||||
use std::num::Bounded;
|
||||
|
||||
|
@ -179,7 +182,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn test_integers() {
|
||||
let mut rng = task_rng();
|
||||
let mut rng = ::test::rng();
|
||||
macro_rules! t (
|
||||
($($ty:ty),*) => {{
|
||||
$(
|
||||
|
@ -204,7 +207,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn test_floats() {
|
||||
let mut rng = task_rng();
|
||||
let mut rng = ::test::rng();
|
||||
macro_rules! t (
|
||||
($($ty:ty),*) => {{
|
||||
$(
|
||||
|
|
|
@ -10,11 +10,12 @@
|
|||
|
||||
//! The ISAAC random number generator.
|
||||
|
||||
use {Rng, SeedableRng, OSRng};
|
||||
use std::io::IoResult;
|
||||
use std::iter::{range_step, Repeat};
|
||||
use std::slice::raw;
|
||||
use std::mem;
|
||||
use core::prelude::*;
|
||||
use core::iter::{range_step, Repeat};
|
||||
use core::slice::raw;
|
||||
use core::mem;
|
||||
|
||||
use {Rng, SeedableRng, Rand};
|
||||
|
||||
static RAND_SIZE_LEN: u32 = 8;
|
||||
static RAND_SIZE: u32 = 1 << RAND_SIZE_LEN;
|
||||
|
@ -44,26 +45,6 @@ static EMPTY: IsaacRng = IsaacRng {
|
|||
};
|
||||
|
||||
impl IsaacRng {
|
||||
/// Create an ISAAC random number generator with a random seed.
|
||||
///
|
||||
/// This reads randomness from the operating system (via `OSRng`)
|
||||
/// which may fail, any error is propagated via the `IoResult`
|
||||
/// return value.
|
||||
pub fn new() -> IoResult<IsaacRng> {
|
||||
let mut rng = EMPTY;
|
||||
let mut os_rng = try!(OSRng::new());
|
||||
unsafe {
|
||||
let ptr = rng.rsl.as_mut_ptr();
|
||||
|
||||
raw::mut_buf_as_slice(ptr as *mut u8, mem::size_of_val(&rng.rsl), |slice| {
|
||||
os_rng.fill_bytes(slice);
|
||||
})
|
||||
}
|
||||
|
||||
rng.init(true);
|
||||
Ok(rng)
|
||||
}
|
||||
|
||||
/// Create an ISAAC random number generator using the default
|
||||
/// fixed seed.
|
||||
pub fn new_unseeded() -> IsaacRng {
|
||||
|
@ -221,6 +202,26 @@ impl<'a> SeedableRng<&'a [u32]> for IsaacRng {
|
|||
}
|
||||
}
|
||||
|
||||
impl Rand for IsaacRng {
|
||||
fn rand<R: Rng>(other: &mut R) -> IsaacRng {
|
||||
let mut ret = EMPTY;
|
||||
unsafe {
|
||||
let ptr = ret.rsl.as_mut_ptr();
|
||||
|
||||
raw::mut_buf_as_slice(ptr as *mut u8,
|
||||
mem::size_of_val(&ret.rsl), |slice| {
|
||||
other.fill_bytes(slice);
|
||||
})
|
||||
}
|
||||
ret.cnt = 0;
|
||||
ret.a = 0;
|
||||
ret.b = 0;
|
||||
ret.c = 0;
|
||||
|
||||
ret.init(true);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
static RAND_SIZE_64_LEN: uint = 8;
|
||||
static RAND_SIZE_64: uint = 1 << RAND_SIZE_64_LEN;
|
||||
|
@ -252,28 +253,6 @@ static EMPTY_64: Isaac64Rng = Isaac64Rng {
|
|||
};
|
||||
|
||||
impl Isaac64Rng {
|
||||
/// Create a 64-bit ISAAC random number generator with a random
|
||||
/// seed.
|
||||
///
|
||||
/// This reads randomness from the operating system (via `OSRng`)
|
||||
/// which may fail, any error is propagated via the `IoResult`
|
||||
/// return value.
|
||||
pub fn new() -> IoResult<Isaac64Rng> {
|
||||
let mut rng = EMPTY_64;
|
||||
let mut os_rng = try!(OSRng::new());
|
||||
|
||||
unsafe {
|
||||
let ptr = rng.rsl.as_mut_ptr();
|
||||
|
||||
raw::mut_buf_as_slice(ptr as *mut u8, mem::size_of_val(&rng.rsl), |slice| {
|
||||
os_rng.fill_bytes(slice);
|
||||
})
|
||||
}
|
||||
|
||||
rng.init(true);
|
||||
Ok(rng)
|
||||
}
|
||||
|
||||
/// Create a 64-bit ISAAC random number generator using the
|
||||
/// default fixed seed.
|
||||
pub fn new_unseeded() -> Isaac64Rng {
|
||||
|
@ -437,24 +416,50 @@ impl<'a> SeedableRng<&'a [u64]> for Isaac64Rng {
|
|||
}
|
||||
}
|
||||
|
||||
impl Rand for Isaac64Rng {
|
||||
fn rand<R: Rng>(other: &mut R) -> Isaac64Rng {
|
||||
let mut ret = EMPTY_64;
|
||||
unsafe {
|
||||
let ptr = ret.rsl.as_mut_ptr();
|
||||
|
||||
raw::mut_buf_as_slice(ptr as *mut u8,
|
||||
mem::size_of_val(&ret.rsl), |slice| {
|
||||
other.fill_bytes(slice);
|
||||
})
|
||||
}
|
||||
ret.cnt = 0;
|
||||
ret.a = 0;
|
||||
ret.b = 0;
|
||||
ret.c = 0;
|
||||
|
||||
ret.init(true);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use std::prelude::*;
|
||||
|
||||
use core::iter::order;
|
||||
use {Rng, SeedableRng};
|
||||
use super::{IsaacRng, Isaac64Rng};
|
||||
use {Rng, SeedableRng, task_rng};
|
||||
|
||||
#[test]
|
||||
fn test_rng_32_rand_seeded() {
|
||||
let s = task_rng().gen_vec::<u32>(256);
|
||||
let s = ::test::rng().gen_iter::<u32>().take(256).collect::<Vec<u32>>();
|
||||
let mut ra: IsaacRng = SeedableRng::from_seed(s.as_slice());
|
||||
let mut rb: IsaacRng = SeedableRng::from_seed(s.as_slice());
|
||||
assert_eq!(ra.gen_ascii_str(100u), rb.gen_ascii_str(100u));
|
||||
assert!(order::equals(ra.gen_ascii_chars().take(100),
|
||||
rb.gen_ascii_chars().take(100)));
|
||||
}
|
||||
#[test]
|
||||
fn test_rng_64_rand_seeded() {
|
||||
let s = task_rng().gen_vec::<u64>(256);
|
||||
let s = ::test::rng().gen_iter::<u64>().take(256).collect::<Vec<u64>>();
|
||||
let mut ra: Isaac64Rng = SeedableRng::from_seed(s.as_slice());
|
||||
let mut rb: Isaac64Rng = SeedableRng::from_seed(s.as_slice());
|
||||
assert_eq!(ra.gen_ascii_str(100u), rb.gen_ascii_str(100u));
|
||||
assert!(order::equals(ra.gen_ascii_chars().take(100),
|
||||
rb.gen_ascii_chars().take(100)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -462,36 +467,38 @@ mod test {
|
|||
let seed = &[1, 23, 456, 7890, 12345];
|
||||
let mut ra: IsaacRng = SeedableRng::from_seed(seed);
|
||||
let mut rb: IsaacRng = SeedableRng::from_seed(seed);
|
||||
assert_eq!(ra.gen_ascii_str(100u), rb.gen_ascii_str(100u));
|
||||
assert!(order::equals(ra.gen_ascii_chars().take(100),
|
||||
rb.gen_ascii_chars().take(100)));
|
||||
}
|
||||
#[test]
|
||||
fn test_rng_64_seeded() {
|
||||
let seed = &[1, 23, 456, 7890, 12345];
|
||||
let mut ra: Isaac64Rng = SeedableRng::from_seed(seed);
|
||||
let mut rb: Isaac64Rng = SeedableRng::from_seed(seed);
|
||||
assert_eq!(ra.gen_ascii_str(100u), rb.gen_ascii_str(100u));
|
||||
assert!(order::equals(ra.gen_ascii_chars().take(100),
|
||||
rb.gen_ascii_chars().take(100)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rng_32_reseed() {
|
||||
let s = task_rng().gen_vec::<u32>(256);
|
||||
let s = ::test::rng().gen_iter::<u32>().take(256).collect::<Vec<u32>>();
|
||||
let mut r: IsaacRng = SeedableRng::from_seed(s.as_slice());
|
||||
let string1 = r.gen_ascii_str(100);
|
||||
let string1: String = r.gen_ascii_chars().take(100).collect();
|
||||
|
||||
r.reseed(s.as_slice());
|
||||
|
||||
let string2 = r.gen_ascii_str(100);
|
||||
let string2: String = r.gen_ascii_chars().take(100).collect();
|
||||
assert_eq!(string1, string2);
|
||||
}
|
||||
#[test]
|
||||
fn test_rng_64_reseed() {
|
||||
let s = task_rng().gen_vec::<u64>(256);
|
||||
let s = ::test::rng().gen_iter::<u64>().take(256).collect::<Vec<u64>>();
|
||||
let mut r: Isaac64Rng = SeedableRng::from_seed(s.as_slice());
|
||||
let string1 = r.gen_ascii_str(100);
|
||||
let string1: String = r.gen_ascii_chars().take(100).collect();
|
||||
|
||||
r.reseed(s.as_slice());
|
||||
|
||||
let string2 = r.gen_ascii_str(100);
|
||||
let string2: String = r.gen_ascii_chars().take(100).collect();
|
||||
assert_eq!(string1, string2);
|
||||
}
|
||||
|
||||
|
|
|
@ -8,96 +8,45 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
/*!
|
||||
Utilities for random number generation
|
||||
|
||||
The key functions are `random()` and `Rng::gen()`. These are polymorphic
|
||||
and so can be used to generate any type that implements `Rand`. Type inference
|
||||
means that often a simple call to `rand::random()` or `rng.gen()` will
|
||||
suffice, but sometimes an annotation is required, e.g. `rand::random::<f64>()`.
|
||||
|
||||
See the `distributions` submodule for sampling random numbers from
|
||||
distributions like normal and exponential.
|
||||
|
||||
# Task-local RNG
|
||||
|
||||
There is built-in support for a RNG associated with each task stored
|
||||
in task-local storage. This RNG can be accessed via `task_rng`, or
|
||||
used implicitly via `random`. This RNG is normally randomly seeded
|
||||
from an operating-system source of randomness, e.g. `/dev/urandom` on
|
||||
Unix systems, and will automatically reseed itself from this source
|
||||
after generating 32 KiB of random data.
|
||||
|
||||
# Cryptographic security
|
||||
|
||||
An application that requires an entropy source for cryptographic purposes
|
||||
must use `OSRng`, which reads randomness from the source that the operating
|
||||
system provides (e.g. `/dev/urandom` on Unixes or `CryptGenRandom()` on Windows).
|
||||
The other random number generators provided by this module are not suitable
|
||||
for such purposes.
|
||||
|
||||
*Note*: many Unix systems provide `/dev/random` as well as `/dev/urandom`.
|
||||
This module uses `/dev/urandom` for the following reasons:
|
||||
|
||||
- On Linux, `/dev/random` may block if entropy pool is empty; `/dev/urandom` will not block.
|
||||
This does not mean that `/dev/random` provides better output than
|
||||
`/dev/urandom`; the kernel internally runs a cryptographically secure pseudorandom
|
||||
number generator (CSPRNG) based on entropy pool for random number generation,
|
||||
so the "quality" of `/dev/random` is not better than `/dev/urandom` in most cases.
|
||||
However, this means that `/dev/urandom` can yield somewhat predictable randomness
|
||||
if the entropy pool is very small, such as immediately after first booting.
|
||||
If an application likely to be run soon after first booting, or on a system with very
|
||||
few entropy sources, one should consider using `/dev/random` via `ReaderRng`.
|
||||
- On some systems (e.g. FreeBSD, OpenBSD and Mac OS X) there is no difference
|
||||
between the two sources. (Also note that, on some systems e.g. FreeBSD, both `/dev/random`
|
||||
and `/dev/urandom` may block once if the CSPRNG has not seeded yet.)
|
||||
|
||||
# Examples
|
||||
|
||||
```rust
|
||||
use rand::Rng;
|
||||
|
||||
let mut rng = rand::task_rng();
|
||||
if rng.gen() { // bool
|
||||
println!("int: {}, uint: {}", rng.gen::<int>(), rng.gen::<uint>())
|
||||
}
|
||||
```
|
||||
|
||||
```rust
|
||||
let tuple_ptr = rand::random::<Box<(f64, char)>>();
|
||||
println!("{}", tuple_ptr)
|
||||
```
|
||||
*/
|
||||
//! Interface to random number generators in Rust.
|
||||
//!
|
||||
//! This is an experimental library which lives underneath the standard library
|
||||
//! in its dependency chain. This library is intended to define the interface
|
||||
//! for random number generation and also provide utilities around doing so. It
|
||||
//! is not recommended to use this library directly, but rather the official
|
||||
//! interface through `std::rand`.
|
||||
|
||||
#![crate_id = "rand#0.11.0-pre"]
|
||||
#![license = "MIT/ASL2"]
|
||||
#![crate_type = "dylib"]
|
||||
#![crate_type = "rlib"]
|
||||
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk.png",
|
||||
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
|
||||
html_root_url = "http://doc.rust-lang.org/")]
|
||||
|
||||
#![feature(macro_rules, managed_boxes, phase)]
|
||||
#![deny(deprecated_owned_vector)]
|
||||
#![feature(macro_rules, phase, globs)]
|
||||
#![no_std]
|
||||
#![experimental]
|
||||
|
||||
#[phase(syntax, link)]
|
||||
extern crate core;
|
||||
|
||||
#[cfg(test)] extern crate native;
|
||||
#[cfg(test)] extern crate debug;
|
||||
#[cfg(test)] #[phase(syntax, link)] extern crate std;
|
||||
#[cfg(test)] #[phase(syntax, link)] extern crate log;
|
||||
|
||||
use std::io::IoResult;
|
||||
use std::kinds::marker;
|
||||
use std::mem;
|
||||
use std::string::String;
|
||||
use core::prelude::*;
|
||||
|
||||
pub use isaac::{IsaacRng, Isaac64Rng};
|
||||
pub use os::OSRng;
|
||||
|
||||
use distributions::{Range, IndependentSample};
|
||||
use distributions::range::SampleRange;
|
||||
|
||||
#[cfg(test)]
|
||||
static RAND_BENCH_N: u64 = 100;
|
||||
|
||||
pub mod distributions;
|
||||
pub mod isaac;
|
||||
pub mod os;
|
||||
pub mod reader;
|
||||
pub mod reseeding;
|
||||
mod rand_impls;
|
||||
|
||||
|
@ -148,7 +97,7 @@ pub trait Rng {
|
|||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use rand::{task_rng, Rng};
|
||||
/// use std::rand::{task_rng, Rng};
|
||||
///
|
||||
/// let mut v = [0u8, .. 13579];
|
||||
/// task_rng().fill_bytes(v);
|
||||
|
@ -183,7 +132,7 @@ pub trait Rng {
|
|||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use rand::{task_rng, Rng};
|
||||
/// use std::rand::{task_rng, Rng};
|
||||
///
|
||||
/// let mut rng = task_rng();
|
||||
/// let x: uint = rng.gen();
|
||||
|
@ -195,20 +144,22 @@ pub trait Rng {
|
|||
Rand::rand(self)
|
||||
}
|
||||
|
||||
/// Return a random vector of the specified length.
|
||||
/// Return an iterator which will yield an infinite number of randomly
|
||||
/// generated items.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use rand::{task_rng, Rng};
|
||||
/// ```
|
||||
/// use std::rand::{task_rng, Rng};
|
||||
///
|
||||
/// let mut rng = task_rng();
|
||||
/// let x: Vec<uint> = rng.gen_vec(10);
|
||||
/// let x = rng.gen_iter::<uint>().take(10).collect::<Vec<uint>>();
|
||||
/// println!("{}", x);
|
||||
/// println!("{}", rng.gen_vec::<(f64, bool)>(5));
|
||||
/// println!("{}", rng.gen_iter::<(f64, bool)>().take(5)
|
||||
/// .collect::<Vec<(f64, bool)>>());
|
||||
/// ```
|
||||
fn gen_vec<T: Rand>(&mut self, len: uint) -> Vec<T> {
|
||||
Vec::from_fn(len, |_| self.gen())
|
||||
fn gen_iter<'a, T: Rand>(&'a mut self) -> Generator<'a, T, Self> {
|
||||
Generator { rng: self }
|
||||
}
|
||||
|
||||
/// Generate a random value in the range [`low`, `high`). Fails if
|
||||
|
@ -223,7 +174,7 @@ pub trait Rng {
|
|||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use rand::{task_rng, Rng};
|
||||
/// use std::rand::{task_rng, Rng};
|
||||
///
|
||||
/// let mut rng = task_rng();
|
||||
/// let n: uint = rng.gen_range(0u, 10);
|
||||
|
@ -241,7 +192,7 @@ pub trait Rng {
|
|||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use rand::{task_rng, Rng};
|
||||
/// use std::rand::{task_rng, Rng};
|
||||
///
|
||||
/// let mut rng = task_rng();
|
||||
/// println!("{:b}", rng.gen_weighted_bool(3));
|
||||
|
@ -250,25 +201,18 @@ pub trait Rng {
|
|||
n == 0 || self.gen_range(0, n) == 0
|
||||
}
|
||||
|
||||
/// Return a random string of the specified length composed of
|
||||
/// A-Z,a-z,0-9.
|
||||
/// Return an iterator of random characters from the set A-Z,a-z,0-9.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use rand::{task_rng, Rng};
|
||||
/// use std::rand::{task_rng, Rng};
|
||||
///
|
||||
/// println!("{}", task_rng().gen_ascii_str(10));
|
||||
/// let s: String = task_rng().gen_ascii_chars().take(10).collect();
|
||||
/// println!("{}", s);
|
||||
/// ```
|
||||
fn gen_ascii_str(&mut self, len: uint) -> String {
|
||||
static GEN_ASCII_STR_CHARSET: &'static [u8] = bytes!("ABCDEFGHIJKLMNOPQRSTUVWXYZ\
|
||||
abcdefghijklmnopqrstuvwxyz\
|
||||
0123456789");
|
||||
let mut s = String::with_capacity(len);
|
||||
for _ in range(0, len) {
|
||||
s.push_char(*self.choose(GEN_ASCII_STR_CHARSET).unwrap() as char)
|
||||
}
|
||||
s
|
||||
fn gen_ascii_chars<'a>(&'a mut self) -> AsciiGenerator<'a, Self> {
|
||||
AsciiGenerator { rng: self }
|
||||
}
|
||||
|
||||
/// Return a random element from `values`.
|
||||
|
@ -278,7 +222,7 @@ pub trait Rng {
|
|||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use rand::{task_rng, Rng};
|
||||
/// use std::rand::{task_rng, Rng};
|
||||
///
|
||||
/// let choices = [1, 2, 4, 8, 16, 32];
|
||||
/// let mut rng = task_rng();
|
||||
|
@ -304,7 +248,7 @@ pub trait Rng {
|
|||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use rand::{task_rng, Rng};
|
||||
/// use std::rand::{task_rng, Rng};
|
||||
///
|
||||
/// let mut rng = task_rng();
|
||||
/// let mut y = [1,2,3];
|
||||
|
@ -322,32 +266,35 @@ pub trait Rng {
|
|||
values.swap(i, self.gen_range(0u, i + 1u));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Randomly sample up to `n` elements from an iterator.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use rand::{task_rng, Rng};
|
||||
///
|
||||
/// let mut rng = task_rng();
|
||||
/// let sample = rng.sample(range(1, 100), 5);
|
||||
/// println!("{}", sample);
|
||||
/// ```
|
||||
fn sample<A, T: Iterator<A>>(&mut self, iter: T, n: uint) -> Vec<A> {
|
||||
let mut reservoir = Vec::with_capacity(n);
|
||||
for (i, elem) in iter.enumerate() {
|
||||
if i < n {
|
||||
reservoir.push(elem);
|
||||
continue
|
||||
}
|
||||
/// Iterator which will generate a stream of random items.
|
||||
///
|
||||
/// This iterator is created via the `gen_iter` method on `Rng`.
|
||||
pub struct Generator<'a, T, R> {
|
||||
rng: &'a mut R,
|
||||
}
|
||||
|
||||
let k = self.gen_range(0, i + 1);
|
||||
if k < reservoir.len() {
|
||||
*reservoir.get_mut(k) = elem
|
||||
}
|
||||
}
|
||||
reservoir
|
||||
impl<'a, T: Rand, R: Rng> Iterator<T> for Generator<'a, T, R> {
|
||||
fn next(&mut self) -> Option<T> {
|
||||
Some(self.rng.gen())
|
||||
}
|
||||
}
|
||||
|
||||
/// Iterator which will continuously generate random ascii characters.
|
||||
///
|
||||
/// This iterator is created via the `gen_ascii_chars` method on `Rng`.
|
||||
pub struct AsciiGenerator<'a, R> {
|
||||
rng: &'a mut R,
|
||||
}
|
||||
|
||||
impl<'a, R: Rng> Iterator<char> for AsciiGenerator<'a, R> {
|
||||
fn next(&mut self) -> Option<char> {
|
||||
static GEN_ASCII_STR_CHARSET: &'static [u8] =
|
||||
bytes!("ABCDEFGHIJKLMNOPQRSTUVWXYZ\
|
||||
abcdefghijklmnopqrstuvwxyz\
|
||||
0123456789");
|
||||
Some(*self.rng.choose(GEN_ASCII_STR_CHARSET).unwrap() as char)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -359,7 +306,7 @@ pub trait SeedableRng<Seed>: Rng {
|
|||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use rand::{Rng, SeedableRng, StdRng};
|
||||
/// use std::rand::{Rng, SeedableRng, StdRng};
|
||||
///
|
||||
/// let mut rng: StdRng = SeedableRng::from_seed(&[1, 2, 3, 4]);
|
||||
/// println!("{}", rng.gen::<f64>());
|
||||
|
@ -373,7 +320,7 @@ pub trait SeedableRng<Seed>: Rng {
|
|||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use rand::{Rng, SeedableRng, StdRng};
|
||||
/// use std::rand::{Rng, SeedableRng, StdRng};
|
||||
///
|
||||
/// let mut rng: StdRng = SeedableRng::from_seed(&[1, 2, 3, 4]);
|
||||
/// println!("{}", rng.gen::<f64>());
|
||||
|
@ -381,89 +328,6 @@ pub trait SeedableRng<Seed>: Rng {
|
|||
fn from_seed(seed: Seed) -> Self;
|
||||
}
|
||||
|
||||
/// The standard RNG. This is designed to be efficient on the current
|
||||
/// platform.
|
||||
#[cfg(not(target_word_size="64"))]
|
||||
pub struct StdRng { rng: IsaacRng }
|
||||
|
||||
/// The standard RNG. This is designed to be efficient on the current
|
||||
/// platform.
|
||||
#[cfg(target_word_size="64")]
|
||||
pub struct StdRng { rng: Isaac64Rng }
|
||||
|
||||
impl StdRng {
|
||||
/// Create a randomly seeded instance of `StdRng`.
|
||||
///
|
||||
/// 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 is only generating a small
|
||||
/// number of random numbers, or doesn't need the utmost speed for
|
||||
/// generating each number, `task_rng` and/or `random` may be more
|
||||
/// appropriate.
|
||||
///
|
||||
/// Reading the randomness from the OS may fail, and any error is
|
||||
/// propagated via the `IoResult` return value.
|
||||
#[cfg(not(target_word_size="64"))]
|
||||
pub fn new() -> IoResult<StdRng> {
|
||||
IsaacRng::new().map(|r| StdRng { rng: r })
|
||||
}
|
||||
/// Create a randomly seeded instance of `StdRng`.
|
||||
///
|
||||
/// 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 is only generating a small
|
||||
/// number of random numbers, or doesn't need the utmost speed for
|
||||
/// generating each number, `task_rng` and/or `random` may be more
|
||||
/// appropriate.
|
||||
///
|
||||
/// Reading the randomness from the OS may fail, and any error is
|
||||
/// propagated via the `IoResult` return value.
|
||||
#[cfg(target_word_size="64")]
|
||||
pub fn new() -> IoResult<StdRng> {
|
||||
Isaac64Rng::new().map(|r| StdRng { rng: r })
|
||||
}
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> SeedableRng<&'a [uint]> for StdRng {
|
||||
fn reseed(&mut self, seed: &'a [uint]) {
|
||||
// the internal RNG can just be seeded from the above
|
||||
// randomness.
|
||||
self.rng.reseed(unsafe {mem::transmute(seed)})
|
||||
}
|
||||
|
||||
fn from_seed(seed: &'a [uint]) -> StdRng {
|
||||
StdRng { rng: SeedableRng::from_seed(unsafe {mem::transmute(seed)}) }
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a weak random number generator with a default algorithm and seed.
|
||||
///
|
||||
/// It returns the fastest `Rng` algorithm currently available in Rust without
|
||||
/// consideration for cryptography or security. If you require a specifically
|
||||
/// seeded `Rng` for consistency over time you should pick one algorithm and
|
||||
/// create the `Rng` yourself.
|
||||
///
|
||||
/// This will read randomness from the operating system to seed the
|
||||
/// generator.
|
||||
pub fn weak_rng() -> XorShiftRng {
|
||||
match XorShiftRng::new() {
|
||||
Ok(r) => r,
|
||||
Err(e) => fail!("weak_rng: failed to create seeded RNG: {}", e)
|
||||
}
|
||||
}
|
||||
|
||||
/// An Xorshift[1] random number
|
||||
/// generator.
|
||||
///
|
||||
|
@ -481,6 +345,23 @@ pub struct XorShiftRng {
|
|||
w: u32,
|
||||
}
|
||||
|
||||
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: 0x193a6754,
|
||||
y: 0xa8a7d469,
|
||||
z: 0x97830e05,
|
||||
w: 0x113ba7bb,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Rng for XorShiftRng {
|
||||
#[inline]
|
||||
fn next_u32(&mut self) -> u32 {
|
||||
|
@ -521,123 +402,17 @@ impl SeedableRng<[u32, .. 4]> for XorShiftRng {
|
|||
}
|
||||
}
|
||||
|
||||
impl XorShiftRng {
|
||||
/// Create an xor shift random number generator with a random seed.
|
||||
pub fn new() -> IoResult<XorShiftRng> {
|
||||
let mut s = [0u8, ..16];
|
||||
let mut r = try!(OSRng::new());
|
||||
loop {
|
||||
r.fill_bytes(s);
|
||||
|
||||
if !s.iter().all(|x| *x == 0) {
|
||||
break;
|
||||
}
|
||||
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 s: [u32, ..4] = unsafe { mem::transmute(s) };
|
||||
Ok(SeedableRng::from_seed(s))
|
||||
let (x, y, z, w) = tuple;
|
||||
XorShiftRng { x: x, y: y, z: z, w: w }
|
||||
}
|
||||
}
|
||||
|
||||
/// Controls how the task-local RNG is reseeded.
|
||||
struct TaskRngReseeder;
|
||||
|
||||
impl reseeding::Reseeder<StdRng> for TaskRngReseeder {
|
||||
fn reseed(&mut self, rng: &mut StdRng) {
|
||||
*rng = match StdRng::new() {
|
||||
Ok(r) => r,
|
||||
Err(e) => fail!("could not reseed task_rng: {}", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
static TASK_RNG_RESEED_THRESHOLD: uint = 32_768;
|
||||
type TaskRngInner = reseeding::ReseedingRng<StdRng, TaskRngReseeder>;
|
||||
/// The task-local RNG.
|
||||
pub struct TaskRng {
|
||||
// This points into TLS (specifically, it points to the endpoint
|
||||
// of a Box stored in TLS, to make it robust against TLS moving
|
||||
// things internally) and so this struct cannot be legally
|
||||
// transferred between tasks *and* it's unsafe to deallocate the
|
||||
// RNG other than when a task is finished.
|
||||
//
|
||||
// The use of unsafe code here is OK if the invariants above are
|
||||
// satisfied; and it allows us to avoid (unnecessarily) using a
|
||||
// GC'd or RC'd pointer.
|
||||
rng: *mut TaskRngInner,
|
||||
marker: marker::NoSend,
|
||||
}
|
||||
|
||||
/// Retrieve the lazily-initialized task-local random number
|
||||
/// generator, seeded by the system. Intended to be used in method
|
||||
/// chaining style, e.g. `task_rng().gen::<int>()`.
|
||||
///
|
||||
/// The RNG provided will reseed itself from the operating system
|
||||
/// after generating a certain amount of randomness.
|
||||
///
|
||||
/// The internal RNG used is platform and architecture dependent, even
|
||||
/// if the operating system random number generator is rigged to give
|
||||
/// the same sequence always. If absolute consistency is required,
|
||||
/// explicitly select an RNG, e.g. `IsaacRng` or `Isaac64Rng`.
|
||||
pub fn task_rng() -> TaskRng {
|
||||
// used to make space in TLS for a random number generator
|
||||
local_data_key!(TASK_RNG_KEY: Box<TaskRngInner>)
|
||||
|
||||
match TASK_RNG_KEY.get() {
|
||||
None => {
|
||||
let r = match StdRng::new() {
|
||||
Ok(r) => r,
|
||||
Err(e) => fail!("could not initialize task_rng: {}", e)
|
||||
};
|
||||
let mut rng = box reseeding::ReseedingRng::new(r,
|
||||
TASK_RNG_RESEED_THRESHOLD,
|
||||
TaskRngReseeder);
|
||||
let ptr = &mut *rng as *mut TaskRngInner;
|
||||
|
||||
TASK_RNG_KEY.replace(Some(rng));
|
||||
|
||||
TaskRng { rng: ptr, marker: marker::NoSend }
|
||||
}
|
||||
Some(rng) => TaskRng {
|
||||
rng: &**rng as *_ as *mut TaskRngInner,
|
||||
marker: marker::NoSend
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Rng for TaskRng {
|
||||
fn next_u32(&mut self) -> u32 {
|
||||
unsafe { (*self.rng).next_u32() }
|
||||
}
|
||||
|
||||
fn next_u64(&mut self) -> u64 {
|
||||
unsafe { (*self.rng).next_u64() }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn fill_bytes(&mut self, bytes: &mut [u8]) {
|
||||
unsafe { (*self.rng).fill_bytes(bytes) }
|
||||
}
|
||||
}
|
||||
|
||||
/// Generate a random value using the task-local random number
|
||||
/// generator.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use rand::random;
|
||||
///
|
||||
/// if random() {
|
||||
/// let x = random();
|
||||
/// println!("{}", 2u * x);
|
||||
/// } else {
|
||||
/// println!("{}", random::<f64>());
|
||||
/// }
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn random<T: Rand>() -> T {
|
||||
task_rng().gen()
|
||||
}
|
||||
|
||||
/// A wrapper for generating floating point numbers uniformly in the
|
||||
/// open interval `(0,1)` (not including either endpoint).
|
||||
///
|
||||
|
@ -647,7 +422,7 @@ pub fn random<T: Rand>() -> T {
|
|||
///
|
||||
/// # Example
|
||||
/// ```rust
|
||||
/// use rand::{random, Open01};
|
||||
/// use std::rand::{random, Open01};
|
||||
///
|
||||
/// let Open01(val) = random::<Open01<f32>>();
|
||||
/// println!("f32 from (0,1): {}", val);
|
||||
|
@ -662,263 +437,41 @@ pub struct Open01<F>(pub F);
|
|||
/// `[0,1)`.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use rand::{random, Closed01};
|
||||
/// use std::rand::{random, Closed01};
|
||||
///
|
||||
/// let Closed01(val) = random::<Closed01<f32>>();
|
||||
/// println!("f32 from [0,1]: {}", val);
|
||||
/// ```
|
||||
pub struct Closed01<F>(pub F);
|
||||
|
||||
#[cfg(not(test))]
|
||||
mod std {
|
||||
pub use core::{option, fmt}; // fail!()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::{Rng, task_rng, random, SeedableRng, StdRng};
|
||||
use std::rand;
|
||||
|
||||
struct ConstRng { i: u64 }
|
||||
impl Rng for ConstRng {
|
||||
fn next_u32(&mut self) -> u32 { self.i as u32 }
|
||||
fn next_u64(&mut self) -> u64 { self.i }
|
||||
pub struct MyRng<R> { inner: R }
|
||||
|
||||
// no fill_bytes on purpose
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fill_bytes_default() {
|
||||
let mut r = ConstRng { i: 0x11_22_33_44_55_66_77_88 };
|
||||
|
||||
// check every remainder mod 8, both in small and big vectors.
|
||||
let lengths = [0, 1, 2, 3, 4, 5, 6, 7,
|
||||
80, 81, 82, 83, 84, 85, 86, 87];
|
||||
for &n in lengths.iter() {
|
||||
let mut v = Vec::from_elem(n, 0u8);
|
||||
r.fill_bytes(v.as_mut_slice());
|
||||
|
||||
// use this to get nicer error messages.
|
||||
for (i, &byte) in v.iter().enumerate() {
|
||||
if byte == 0 {
|
||||
fail!("byte {} of {} is zero", i, n)
|
||||
}
|
||||
impl<R: rand::Rng> ::Rng for MyRng<R> {
|
||||
fn next_u32(&mut self) -> u32 {
|
||||
fn next<T: rand::Rng>(t: &mut T) -> u32 {
|
||||
use std::rand::Rng;
|
||||
t.next_u32()
|
||||
}
|
||||
next(&mut self.inner)
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_gen_range() {
|
||||
let mut r = task_rng();
|
||||
for _ in range(0, 1000) {
|
||||
let a = r.gen_range(-3i, 42);
|
||||
assert!(a >= -3 && a < 42);
|
||||
assert_eq!(r.gen_range(0, 1), 0);
|
||||
assert_eq!(r.gen_range(-12, -11), -12);
|
||||
}
|
||||
|
||||
for _ in range(0, 1000) {
|
||||
let a = r.gen_range(10, 42);
|
||||
assert!(a >= 10 && a < 42);
|
||||
assert_eq!(r.gen_range(0, 1), 0);
|
||||
assert_eq!(r.gen_range(3_000_000u, 3_000_001), 3_000_000);
|
||||
}
|
||||
|
||||
pub fn rng() -> MyRng<rand::TaskRng> {
|
||||
MyRng { inner: rand::task_rng() }
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_fail]
|
||||
fn test_gen_range_fail_int() {
|
||||
let mut r = task_rng();
|
||||
r.gen_range(5i, -2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_fail]
|
||||
fn test_gen_range_fail_uint() {
|
||||
let mut r = task_rng();
|
||||
r.gen_range(5u, 2u);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_gen_f64() {
|
||||
let mut r = task_rng();
|
||||
let a = r.gen::<f64>();
|
||||
let b = r.gen::<f64>();
|
||||
debug!("{:?}", (a, b));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_gen_weighted_bool() {
|
||||
let mut r = task_rng();
|
||||
assert_eq!(r.gen_weighted_bool(0u), true);
|
||||
assert_eq!(r.gen_weighted_bool(1u), true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_gen_ascii_str() {
|
||||
let mut r = task_rng();
|
||||
debug!("{}", r.gen_ascii_str(10u));
|
||||
debug!("{}", r.gen_ascii_str(10u));
|
||||
debug!("{}", r.gen_ascii_str(10u));
|
||||
assert_eq!(r.gen_ascii_str(0u).len(), 0u);
|
||||
assert_eq!(r.gen_ascii_str(10u).len(), 10u);
|
||||
assert_eq!(r.gen_ascii_str(16u).len(), 16u);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_gen_vec() {
|
||||
let mut r = task_rng();
|
||||
assert_eq!(r.gen_vec::<u8>(0u).len(), 0u);
|
||||
assert_eq!(r.gen_vec::<u8>(10u).len(), 10u);
|
||||
assert_eq!(r.gen_vec::<f64>(16u).len(), 16u);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_choose() {
|
||||
let mut r = task_rng();
|
||||
assert_eq!(r.choose([1, 1, 1]).map(|&x|x), Some(1));
|
||||
|
||||
let v: &[int] = &[];
|
||||
assert_eq!(r.choose(v), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_shuffle() {
|
||||
let mut r = task_rng();
|
||||
let empty: &mut [int] = &mut [];
|
||||
r.shuffle(empty);
|
||||
let mut one = [1];
|
||||
r.shuffle(one);
|
||||
assert_eq!(one.as_slice(), &[1]);
|
||||
|
||||
let mut two = [1, 2];
|
||||
r.shuffle(two);
|
||||
assert!(two == [1, 2] || two == [2, 1]);
|
||||
|
||||
let mut x = [1, 1, 1];
|
||||
r.shuffle(x);
|
||||
assert_eq!(x.as_slice(), &[1, 1, 1]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_task_rng() {
|
||||
let mut r = task_rng();
|
||||
r.gen::<int>();
|
||||
let mut v = [1, 1, 1];
|
||||
r.shuffle(v);
|
||||
assert_eq!(v.as_slice(), &[1, 1, 1]);
|
||||
assert_eq!(r.gen_range(0u, 1u), 0u);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_random() {
|
||||
// not sure how to test this aside from just getting some values
|
||||
let _n : uint = random();
|
||||
let _f : f32 = random();
|
||||
let _o : Option<Option<i8>> = random();
|
||||
let _many : ((),
|
||||
(Box<uint>,
|
||||
@int,
|
||||
Box<Option<Box<(@u32, Box<(@bool,)>)>>>),
|
||||
(u8, i8, u16, i16, u32, i32, u64, i64),
|
||||
(f32, (f64, (f64,)))) = random();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_sample() {
|
||||
let min_val = 1;
|
||||
let max_val = 100;
|
||||
|
||||
let mut r = task_rng();
|
||||
let vals = range(min_val, max_val).collect::<Vec<int>>();
|
||||
let small_sample = r.sample(vals.iter(), 5);
|
||||
let large_sample = r.sample(vals.iter(), vals.len() + 5);
|
||||
|
||||
assert_eq!(small_sample.len(), 5);
|
||||
assert_eq!(large_sample.len(), vals.len());
|
||||
|
||||
assert!(small_sample.iter().all(|e| {
|
||||
**e >= min_val && **e <= max_val
|
||||
}));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_std_rng_seeded() {
|
||||
let s = task_rng().gen_vec::<uint>(256);
|
||||
let mut ra: StdRng = SeedableRng::from_seed(s.as_slice());
|
||||
let mut rb: StdRng = SeedableRng::from_seed(s.as_slice());
|
||||
assert_eq!(ra.gen_ascii_str(100u), rb.gen_ascii_str(100u));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_std_rng_reseed() {
|
||||
let s = task_rng().gen_vec::<uint>(256);
|
||||
let mut r: StdRng = SeedableRng::from_seed(s.as_slice());
|
||||
let string1 = r.gen_ascii_str(100);
|
||||
|
||||
r.reseed(s.as_slice());
|
||||
|
||||
let string2 = r.gen_ascii_str(100);
|
||||
assert_eq!(string1, string2);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
static RAND_BENCH_N: u64 = 100;
|
||||
|
||||
#[cfg(test)]
|
||||
mod bench {
|
||||
extern crate test;
|
||||
use self::test::Bencher;
|
||||
use {XorShiftRng, StdRng, IsaacRng, Isaac64Rng, Rng, RAND_BENCH_N};
|
||||
use std::mem::size_of;
|
||||
|
||||
#[bench]
|
||||
fn rand_xorshift(b: &mut Bencher) {
|
||||
let mut rng = XorShiftRng::new().unwrap();
|
||||
b.iter(|| {
|
||||
for _ in range(0, RAND_BENCH_N) {
|
||||
rng.gen::<uint>();
|
||||
}
|
||||
});
|
||||
b.bytes = size_of::<uint>() as u64 * RAND_BENCH_N;
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn rand_isaac(b: &mut Bencher) {
|
||||
let mut rng = IsaacRng::new().unwrap();
|
||||
b.iter(|| {
|
||||
for _ in range(0, RAND_BENCH_N) {
|
||||
rng.gen::<uint>();
|
||||
}
|
||||
});
|
||||
b.bytes = size_of::<uint>() as u64 * RAND_BENCH_N;
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn rand_isaac64(b: &mut Bencher) {
|
||||
let mut rng = Isaac64Rng::new().unwrap();
|
||||
b.iter(|| {
|
||||
for _ in range(0, RAND_BENCH_N) {
|
||||
rng.gen::<uint>();
|
||||
}
|
||||
});
|
||||
b.bytes = size_of::<uint>() as u64 * RAND_BENCH_N;
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn rand_std(b: &mut Bencher) {
|
||||
let mut rng = StdRng::new().unwrap();
|
||||
b.iter(|| {
|
||||
for _ in range(0, RAND_BENCH_N) {
|
||||
rng.gen::<uint>();
|
||||
}
|
||||
});
|
||||
b.bytes = size_of::<uint>() as u64 * RAND_BENCH_N;
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn rand_shuffle_100(b: &mut Bencher) {
|
||||
let mut rng = XorShiftRng::new().unwrap();
|
||||
let x : &mut[uint] = [1,..100];
|
||||
b.iter(|| {
|
||||
rng.shuffle(x);
|
||||
})
|
||||
pub fn weak_rng() -> MyRng<rand::XorShiftRng> {
|
||||
MyRng { inner: rand::weak_rng() }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,9 +10,10 @@
|
|||
|
||||
//! The implementations of `Rand` for the built-in types.
|
||||
|
||||
use std::char;
|
||||
use std::int;
|
||||
use std::uint;
|
||||
use core::prelude::*;
|
||||
use core::char;
|
||||
use core::int;
|
||||
use core::uint;
|
||||
|
||||
use {Rand,Rng};
|
||||
|
||||
|
@ -214,19 +215,10 @@ impl<T:Rand> Rand for Option<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: Rand> Rand for Box<T> {
|
||||
#[inline]
|
||||
fn rand<R: Rng>(rng: &mut R) -> Box<T> { box rng.gen() }
|
||||
}
|
||||
|
||||
impl<T: Rand + 'static> Rand for @T {
|
||||
#[inline]
|
||||
fn rand<R: Rng>(rng: &mut R) -> @T { @rng.gen() }
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use {Rng, task_rng, Open01, Closed01};
|
||||
use std::prelude::*;
|
||||
use std::rand::{Rng, task_rng, Open01, Closed01};
|
||||
|
||||
struct ConstantRng(u64);
|
||||
impl Rng for ConstantRng {
|
||||
|
|
|
@ -11,8 +11,10 @@
|
|||
//! A wrapper around another RNG that reseeds it after it
|
||||
//! generates a certain number of random bytes.
|
||||
|
||||
use std::default::Default;
|
||||
use core::prelude::*;
|
||||
|
||||
use {Rng, SeedableRng};
|
||||
use core::default::Default;
|
||||
|
||||
/// How many bytes of entropy the underling RNG is allowed to generate
|
||||
/// before it is reseeded.
|
||||
|
@ -76,13 +78,14 @@ impl<R: Rng, Rsdr: Reseeder<R>> Rng for ReseedingRng<R, Rsdr> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<S, R: SeedableRng<S>, Rsdr: Reseeder<R>>
|
||||
impl<S, R: SeedableRng<S>, Rsdr: Reseeder<R> + Default>
|
||||
SeedableRng<(Rsdr, S)> for ReseedingRng<R, Rsdr> {
|
||||
fn reseed(&mut self, (rsdr, seed): (Rsdr, S)) {
|
||||
self.rng.reseed(seed);
|
||||
self.reseeder = rsdr;
|
||||
self.bytes_generated = 0;
|
||||
}
|
||||
|
||||
/// Create a new `ReseedingRng` from the given reseeder and
|
||||
/// seed. This uses a default value for `generation_threshold`.
|
||||
fn from_seed((rsdr, seed): (Rsdr, S)) -> ReseedingRng<R, Rsdr> {
|
||||
|
@ -100,8 +103,8 @@ impl<S, R: SeedableRng<S>, Rsdr: Reseeder<R>>
|
|||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use rand::{Rng, SeedableRng, StdRng};
|
||||
/// use rand::reseeding::{Reseeder, ReseedingRng};
|
||||
/// use std::rand::{Rng, SeedableRng, StdRng};
|
||||
/// use std::rand::reseeding::{Reseeder, ReseedingRng};
|
||||
///
|
||||
/// struct TickTockReseeder { tick: bool }
|
||||
/// impl Reseeder<StdRng> for TickTockReseeder {
|
||||
|
@ -118,7 +121,8 @@ impl<S, R: SeedableRng<S>, Rsdr: Reseeder<R>>
|
|||
/// let mut rng = ReseedingRng::new(inner, 10, rsdr);
|
||||
///
|
||||
/// // this will repeat, because it gets reseeded very regularly.
|
||||
/// println!("{}", rng.gen_ascii_str(100));
|
||||
/// let s: String = rng.gen_ascii_chars().take(100).collect();
|
||||
/// println!("{}", s);
|
||||
/// }
|
||||
///
|
||||
/// ```
|
||||
|
@ -142,6 +146,9 @@ impl Default for ReseedWithDefault {
|
|||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use std::prelude::*;
|
||||
|
||||
use core::iter::order;
|
||||
use super::{ReseedingRng, ReseedWithDefault};
|
||||
use std::default::Default;
|
||||
use {SeedableRng, Rng};
|
||||
|
@ -187,26 +194,26 @@ mod test {
|
|||
fn test_rng_seeded() {
|
||||
let mut ra: MyRng = SeedableRng::from_seed((ReseedWithDefault, 2));
|
||||
let mut rb: MyRng = SeedableRng::from_seed((ReseedWithDefault, 2));
|
||||
assert_eq!(ra.gen_ascii_str(100u), rb.gen_ascii_str(100u));
|
||||
assert!(order::equals(ra.gen_ascii_chars().take(100),
|
||||
rb.gen_ascii_chars().take(100)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rng_reseed() {
|
||||
let mut r: MyRng = SeedableRng::from_seed((ReseedWithDefault, 3));
|
||||
let string1 = r.gen_ascii_str(100);
|
||||
let string1: String = r.gen_ascii_chars().take(100).collect();
|
||||
|
||||
r.reseed((ReseedWithDefault, 3));
|
||||
|
||||
let string2 = r.gen_ascii_str(100);
|
||||
let string2: String = r.gen_ascii_chars().take(100).collect();
|
||||
assert_eq!(string1, string2);
|
||||
}
|
||||
|
||||
static fill_bytes_v_len: uint = 13579;
|
||||
#[test]
|
||||
fn test_rng_fill_bytes() {
|
||||
use task_rng;
|
||||
let mut v = Vec::from_elem(fill_bytes_v_len, 0u8);
|
||||
task_rng().fill_bytes(v.as_mut_slice());
|
||||
::test::rng().fill_bytes(v.as_mut_slice());
|
||||
|
||||
// Sanity test: if we've gotten here, `fill_bytes` has not infinitely
|
||||
// recursed.
|
||||
|
|
|
@ -8,9 +8,10 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use rand::{Rng, task_rng};
|
||||
use stdtest::Bencher;
|
||||
use std::rand::{Rng, task_rng};
|
||||
use std::str;
|
||||
use stdtest::Bencher;
|
||||
|
||||
use regex::{Regex, NoExpand};
|
||||
|
||||
fn bench_assert_match(b: &mut Bencher, re: Regex, text: &str) {
|
||||
|
@ -152,10 +153,10 @@ fn easy1() -> Regex { regex!("A[AB]B[BC]C[CD]D[DE]E[EF]F[FG]G[GH]H[HI]I[IJ]J$")
|
|||
fn medium() -> Regex { regex!("[XYZ]ABCDEFGHIJKLMNOPQRSTUVWXYZ$") }
|
||||
fn hard() -> Regex { regex!("[ -~]*ABCDEFGHIJKLMNOPQRSTUVWXYZ$") }
|
||||
|
||||
#[allow(deprecated_owned_vector)]
|
||||
fn gen_text(n: uint) -> String {
|
||||
let mut rng = task_rng();
|
||||
let mut bytes = rng.gen_ascii_str(n).into_bytes();
|
||||
let mut bytes = rng.gen_ascii_chars().map(|n| n as u8).take(n)
|
||||
.collect::<Vec<u8>>();
|
||||
for (i, b) in bytes.mut_iter().enumerate() {
|
||||
if i % 20 == 0 {
|
||||
*b = '\n' as u8
|
||||
|
|
|
@ -261,7 +261,6 @@ impl<'a> FromBase64 for &'a str {
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
extern crate test;
|
||||
extern crate rand;
|
||||
use self::test::Bencher;
|
||||
use base64::{Config, FromBase64, ToBase64, STANDARD, URL_SAFE};
|
||||
|
||||
|
@ -335,7 +334,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn test_base64_random() {
|
||||
use self::rand::{task_rng, random, Rng};
|
||||
use std::rand::{task_rng, random, Rng};
|
||||
|
||||
for _ in range(0, 1000) {
|
||||
let times = task_rng().gen_range(1u, 100);
|
||||
|
|
|
@ -120,12 +120,10 @@
|
|||
#[cfg(test)] extern crate debug;
|
||||
#[cfg(test)] #[phase(syntax, link)] extern crate log;
|
||||
|
||||
// Make and rand accessible for benchmarking/testcases
|
||||
#[cfg(test)] extern crate rand;
|
||||
|
||||
extern crate alloc;
|
||||
extern crate core;
|
||||
extern crate libc;
|
||||
extern crate core_rand = "rand";
|
||||
|
||||
// Make std testable by not duplicating lang items. See #2912
|
||||
#[cfg(test)] extern crate realstd = "std";
|
||||
|
@ -208,6 +206,7 @@ pub mod slice;
|
|||
pub mod vec;
|
||||
pub mod str;
|
||||
pub mod string;
|
||||
pub mod rand;
|
||||
|
||||
pub mod ascii;
|
||||
|
||||
|
|
|
@ -819,84 +819,84 @@ mod bench {
|
|||
|
||||
mod uint {
|
||||
use super::test::Bencher;
|
||||
use rand::{XorShiftRng, Rng};
|
||||
use rand::{weak_rng, Rng};
|
||||
use num::ToStrRadix;
|
||||
|
||||
#[bench]
|
||||
fn to_str_bin(b: &mut Bencher) {
|
||||
let mut rng = XorShiftRng::new().unwrap();
|
||||
let mut rng = weak_rng();
|
||||
b.iter(|| { rng.gen::<uint>().to_str_radix(2); })
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn to_str_oct(b: &mut Bencher) {
|
||||
let mut rng = XorShiftRng::new().unwrap();
|
||||
let mut rng = weak_rng();
|
||||
b.iter(|| { rng.gen::<uint>().to_str_radix(8); })
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn to_str_dec(b: &mut Bencher) {
|
||||
let mut rng = XorShiftRng::new().unwrap();
|
||||
let mut rng = weak_rng();
|
||||
b.iter(|| { rng.gen::<uint>().to_str_radix(10); })
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn to_str_hex(b: &mut Bencher) {
|
||||
let mut rng = XorShiftRng::new().unwrap();
|
||||
let mut rng = weak_rng();
|
||||
b.iter(|| { rng.gen::<uint>().to_str_radix(16); })
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn to_str_base_36(b: &mut Bencher) {
|
||||
let mut rng = XorShiftRng::new().unwrap();
|
||||
let mut rng = weak_rng();
|
||||
b.iter(|| { rng.gen::<uint>().to_str_radix(36); })
|
||||
}
|
||||
}
|
||||
|
||||
mod int {
|
||||
use super::test::Bencher;
|
||||
use rand::{XorShiftRng, Rng};
|
||||
use rand::{weak_rng, Rng};
|
||||
use num::ToStrRadix;
|
||||
|
||||
#[bench]
|
||||
fn to_str_bin(b: &mut Bencher) {
|
||||
let mut rng = XorShiftRng::new().unwrap();
|
||||
let mut rng = weak_rng();
|
||||
b.iter(|| { rng.gen::<int>().to_str_radix(2); })
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn to_str_oct(b: &mut Bencher) {
|
||||
let mut rng = XorShiftRng::new().unwrap();
|
||||
let mut rng = weak_rng();
|
||||
b.iter(|| { rng.gen::<int>().to_str_radix(8); })
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn to_str_dec(b: &mut Bencher) {
|
||||
let mut rng = XorShiftRng::new().unwrap();
|
||||
let mut rng = weak_rng();
|
||||
b.iter(|| { rng.gen::<int>().to_str_radix(10); })
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn to_str_hex(b: &mut Bencher) {
|
||||
let mut rng = XorShiftRng::new().unwrap();
|
||||
let mut rng = weak_rng();
|
||||
b.iter(|| { rng.gen::<int>().to_str_radix(16); })
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn to_str_base_36(b: &mut Bencher) {
|
||||
let mut rng = XorShiftRng::new().unwrap();
|
||||
let mut rng = weak_rng();
|
||||
b.iter(|| { rng.gen::<int>().to_str_radix(36); })
|
||||
}
|
||||
}
|
||||
|
||||
mod f64 {
|
||||
use super::test::Bencher;
|
||||
use rand::{XorShiftRng, Rng};
|
||||
use rand::{weak_rng, Rng};
|
||||
use f64;
|
||||
|
||||
#[bench]
|
||||
fn float_to_str(b: &mut Bencher) {
|
||||
let mut rng = XorShiftRng::new().unwrap();
|
||||
let mut rng = weak_rng();
|
||||
b.iter(|| { f64::to_str(rng.gen()); })
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1513,7 +1513,8 @@ mod tests {
|
|||
|
||||
fn make_rand_name() -> String {
|
||||
let mut rng = rand::task_rng();
|
||||
let n = format!("TEST{}", rng.gen_ascii_str(10u).as_slice());
|
||||
let n = format!("TEST{}", rng.gen_ascii_chars().take(10u)
|
||||
.collect::<String>());
|
||||
assert!(getenv(n.as_slice()).is_none());
|
||||
n
|
||||
}
|
||||
|
|
525
src/libstd/rand/mod.rs
Normal file
525
src/libstd/rand/mod.rs
Normal file
|
@ -0,0 +1,525 @@
|
|||
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
/*!
|
||||
|
||||
Utilities for random number generation
|
||||
|
||||
The key functions are `random()` and `Rng::gen()`. These are polymorphic
|
||||
and so can be used to generate any type that implements `Rand`. Type inference
|
||||
means that often a simple call to `rand::random()` or `rng.gen()` will
|
||||
suffice, but sometimes an annotation is required, e.g. `rand::random::<f64>()`.
|
||||
|
||||
See the `distributions` submodule for sampling random numbers from
|
||||
distributions like normal and exponential.
|
||||
|
||||
# Task-local RNG
|
||||
|
||||
There is built-in support for a RNG associated with each task stored
|
||||
in task-local storage. This RNG can be accessed via `task_rng`, or
|
||||
used implicitly via `random`. This RNG is normally randomly seeded
|
||||
from an operating-system source of randomness, e.g. `/dev/urandom` on
|
||||
Unix systems, and will automatically reseed itself from this source
|
||||
after generating 32 KiB of random data.
|
||||
|
||||
# Cryptographic security
|
||||
|
||||
An application that requires an entropy source for cryptographic purposes
|
||||
must use `OSRng`, which reads randomness from the source that the operating
|
||||
system provides (e.g. `/dev/urandom` on Unixes or `CryptGenRandom()` on Windows).
|
||||
The other random number generators provided by this module are not suitable
|
||||
for such purposes.
|
||||
|
||||
*Note*: many Unix systems provide `/dev/random` as well as `/dev/urandom`.
|
||||
This module uses `/dev/urandom` for the following reasons:
|
||||
|
||||
- On Linux, `/dev/random` may block if entropy pool is empty; `/dev/urandom` will not block.
|
||||
This does not mean that `/dev/random` provides better output than
|
||||
`/dev/urandom`; the kernel internally runs a cryptographically secure pseudorandom
|
||||
number generator (CSPRNG) based on entropy pool for random number generation,
|
||||
so the "quality" of `/dev/random` is not better than `/dev/urandom` in most cases.
|
||||
However, this means that `/dev/urandom` can yield somewhat predictable randomness
|
||||
if the entropy pool is very small, such as immediately after first booting.
|
||||
If an application likely to be run soon after first booting, or on a system with very
|
||||
few entropy sources, one should consider using `/dev/random` via `ReaderRng`.
|
||||
- On some systems (e.g. FreeBSD, OpenBSD and Mac OS X) there is no difference
|
||||
between the two sources. (Also note that, on some systems e.g. FreeBSD, both `/dev/random`
|
||||
and `/dev/urandom` may block once if the CSPRNG has not seeded yet.)
|
||||
|
||||
# Examples
|
||||
|
||||
```rust
|
||||
use std::rand;
|
||||
use std::rand::Rng;
|
||||
|
||||
let mut rng = rand::task_rng();
|
||||
if rng.gen() { // bool
|
||||
println!("int: {}, uint: {}", rng.gen::<int>(), rng.gen::<uint>())
|
||||
}
|
||||
```
|
||||
|
||||
```rust
|
||||
use std::rand;
|
||||
|
||||
let tuple = rand::random::<(f64, char)>();
|
||||
println!("{}", tuple)
|
||||
```
|
||||
*/
|
||||
|
||||
use cell::RefCell;
|
||||
use clone::Clone;
|
||||
use io::IoResult;
|
||||
use iter::Iterator;
|
||||
use mem;
|
||||
use option::{Some, None};
|
||||
use rc::Rc;
|
||||
use result::{Ok, Err};
|
||||
use vec::Vec;
|
||||
|
||||
#[cfg(not(target_word_size="64"))]
|
||||
use IsaacWordRng = core_rand::IsaacRng;
|
||||
#[cfg(target_word_size="64")]
|
||||
use IsaacWordRng = core_rand::Isaac64Rng;
|
||||
|
||||
pub use core_rand::{Rand, Rng, SeedableRng, Open01, Closed01};
|
||||
pub use core_rand::{XorShiftRng, IsaacRng, Isaac64Rng};
|
||||
pub use core_rand::{distributions, reseeding};
|
||||
pub use rand::os::OSRng;
|
||||
|
||||
pub mod os;
|
||||
pub mod reader;
|
||||
|
||||
/// The standard RNG. This is designed to be efficient on the current
|
||||
/// platform.
|
||||
pub struct StdRng { rng: IsaacWordRng }
|
||||
|
||||
impl StdRng {
|
||||
/// Create a randomly seeded instance of `StdRng`.
|
||||
///
|
||||
/// 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 is only generating a small
|
||||
/// number of random numbers, or doesn't need the utmost speed for
|
||||
/// generating each number, `task_rng` and/or `random` may be more
|
||||
/// appropriate.
|
||||
///
|
||||
/// Reading the randomness from the OS may fail, and any error is
|
||||
/// propagated via the `IoResult` return value.
|
||||
pub fn new() -> IoResult<StdRng> {
|
||||
OSRng::new().map(|mut r| StdRng { rng: r.gen() })
|
||||
}
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> SeedableRng<&'a [uint]> for StdRng {
|
||||
fn reseed(&mut self, seed: &'a [uint]) {
|
||||
// the internal RNG can just be seeded from the above
|
||||
// randomness.
|
||||
self.rng.reseed(unsafe {mem::transmute(seed)})
|
||||
}
|
||||
|
||||
fn from_seed(seed: &'a [uint]) -> StdRng {
|
||||
StdRng { rng: SeedableRng::from_seed(unsafe {mem::transmute(seed)}) }
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a weak random number generator with a default algorithm and seed.
|
||||
///
|
||||
/// It returns the fastest `Rng` algorithm currently available in Rust without
|
||||
/// consideration for cryptography or security. If you require a specifically
|
||||
/// seeded `Rng` for consistency over time you should pick one algorithm and
|
||||
/// create the `Rng` yourself.
|
||||
///
|
||||
/// This will read randomness from the operating system to seed the
|
||||
/// generator.
|
||||
pub fn weak_rng() -> XorShiftRng {
|
||||
match OSRng::new() {
|
||||
Ok(mut r) => r.gen(),
|
||||
Err(e) => fail!("weak_rng: failed to create seeded RNG: {}", e)
|
||||
}
|
||||
}
|
||||
|
||||
/// Controls how the task-local RNG is reseeded.
|
||||
struct TaskRngReseeder;
|
||||
|
||||
impl reseeding::Reseeder<StdRng> for TaskRngReseeder {
|
||||
fn reseed(&mut self, rng: &mut StdRng) {
|
||||
*rng = match StdRng::new() {
|
||||
Ok(r) => r,
|
||||
Err(e) => fail!("could not reseed task_rng: {}", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
static TASK_RNG_RESEED_THRESHOLD: uint = 32_768;
|
||||
type TaskRngInner = reseeding::ReseedingRng<StdRng, TaskRngReseeder>;
|
||||
|
||||
/// The task-local RNG.
|
||||
pub struct TaskRng {
|
||||
rng: Rc<RefCell<TaskRngInner>>,
|
||||
}
|
||||
|
||||
/// Retrieve the lazily-initialized task-local random number
|
||||
/// generator, seeded by the system. Intended to be used in method
|
||||
/// chaining style, e.g. `task_rng().gen::<int>()`.
|
||||
///
|
||||
/// The RNG provided will reseed itself from the operating system
|
||||
/// after generating a certain amount of randomness.
|
||||
///
|
||||
/// The internal RNG used is platform and architecture dependent, even
|
||||
/// if the operating system random number generator is rigged to give
|
||||
/// the same sequence always. If absolute consistency is required,
|
||||
/// explicitly select an RNG, e.g. `IsaacRng` or `Isaac64Rng`.
|
||||
pub fn task_rng() -> TaskRng {
|
||||
// used to make space in TLS for a random number generator
|
||||
local_data_key!(TASK_RNG_KEY: Rc<RefCell<TaskRngInner>>)
|
||||
|
||||
match TASK_RNG_KEY.get() {
|
||||
None => {
|
||||
let r = match StdRng::new() {
|
||||
Ok(r) => r,
|
||||
Err(e) => fail!("could not initialize task_rng: {}", e)
|
||||
};
|
||||
let rng = reseeding::ReseedingRng::new(r,
|
||||
TASK_RNG_RESEED_THRESHOLD,
|
||||
TaskRngReseeder);
|
||||
let rng = Rc::new(RefCell::new(rng));
|
||||
TASK_RNG_KEY.replace(Some(rng.clone()));
|
||||
|
||||
TaskRng { rng: rng }
|
||||
}
|
||||
Some(rng) => TaskRng { rng: rng.clone() }
|
||||
}
|
||||
}
|
||||
|
||||
impl Rng for TaskRng {
|
||||
fn next_u32(&mut self) -> u32 {
|
||||
self.rng.borrow_mut().next_u32()
|
||||
}
|
||||
|
||||
fn next_u64(&mut self) -> u64 {
|
||||
self.rng.borrow_mut().next_u64()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn fill_bytes(&mut self, bytes: &mut [u8]) {
|
||||
self.rng.borrow_mut().fill_bytes(bytes)
|
||||
}
|
||||
}
|
||||
|
||||
/// Generate a random value using the task-local random number
|
||||
/// generator.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use std::rand::random;
|
||||
///
|
||||
/// if random() {
|
||||
/// let x = random();
|
||||
/// println!("{}", 2u * x);
|
||||
/// } else {
|
||||
/// println!("{}", random::<f64>());
|
||||
/// }
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn random<T: Rand>() -> T {
|
||||
task_rng().gen()
|
||||
}
|
||||
|
||||
/// Randomly sample up to `n` elements from an iterator.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use std::rand::{task_rng, sample};
|
||||
///
|
||||
/// let mut rng = task_rng();
|
||||
/// let sample = sample(&mut rng, range(1, 100), 5);
|
||||
/// println!("{}", sample);
|
||||
/// ```
|
||||
pub fn sample<T, I: Iterator<T>, R: Rng>(rng: &mut R,
|
||||
mut iter: I,
|
||||
amt: uint) -> Vec<T> {
|
||||
let mut reservoir: Vec<T> = iter.by_ref().take(amt).collect();
|
||||
for (i, elem) in iter.enumerate() {
|
||||
let k = rng.gen_range(0, i + 1 + amt);
|
||||
if k < amt {
|
||||
*reservoir.get_mut(k) = elem;
|
||||
}
|
||||
}
|
||||
return reservoir;
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use prelude::*;
|
||||
use super::{Rng, task_rng, random, SeedableRng, StdRng, sample};
|
||||
use iter::order;
|
||||
|
||||
struct ConstRng { i: u64 }
|
||||
impl Rng for ConstRng {
|
||||
fn next_u32(&mut self) -> u32 { self.i as u32 }
|
||||
fn next_u64(&mut self) -> u64 { self.i }
|
||||
|
||||
// no fill_bytes on purpose
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fill_bytes_default() {
|
||||
let mut r = ConstRng { i: 0x11_22_33_44_55_66_77_88 };
|
||||
|
||||
// check every remainder mod 8, both in small and big vectors.
|
||||
let lengths = [0, 1, 2, 3, 4, 5, 6, 7,
|
||||
80, 81, 82, 83, 84, 85, 86, 87];
|
||||
for &n in lengths.iter() {
|
||||
let mut v = Vec::from_elem(n, 0u8);
|
||||
r.fill_bytes(v.as_mut_slice());
|
||||
|
||||
// use this to get nicer error messages.
|
||||
for (i, &byte) in v.iter().enumerate() {
|
||||
if byte == 0 {
|
||||
fail!("byte {} of {} is zero", i, n)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_gen_range() {
|
||||
let mut r = task_rng();
|
||||
for _ in range(0, 1000) {
|
||||
let a = r.gen_range(-3i, 42);
|
||||
assert!(a >= -3 && a < 42);
|
||||
assert_eq!(r.gen_range(0, 1), 0);
|
||||
assert_eq!(r.gen_range(-12, -11), -12);
|
||||
}
|
||||
|
||||
for _ in range(0, 1000) {
|
||||
let a = r.gen_range(10, 42);
|
||||
assert!(a >= 10 && a < 42);
|
||||
assert_eq!(r.gen_range(0, 1), 0);
|
||||
assert_eq!(r.gen_range(3_000_000u, 3_000_001), 3_000_000);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_fail]
|
||||
fn test_gen_range_fail_int() {
|
||||
let mut r = task_rng();
|
||||
r.gen_range(5i, -2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_fail]
|
||||
fn test_gen_range_fail_uint() {
|
||||
let mut r = task_rng();
|
||||
r.gen_range(5u, 2u);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_gen_f64() {
|
||||
let mut r = task_rng();
|
||||
let a = r.gen::<f64>();
|
||||
let b = r.gen::<f64>();
|
||||
debug!("{}", (a, b));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_gen_weighted_bool() {
|
||||
let mut r = task_rng();
|
||||
assert_eq!(r.gen_weighted_bool(0u), true);
|
||||
assert_eq!(r.gen_weighted_bool(1u), true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_gen_ascii_str() {
|
||||
let mut r = task_rng();
|
||||
assert_eq!(r.gen_ascii_chars().take(0).len(), 0u);
|
||||
assert_eq!(r.gen_ascii_chars().take(10).len(), 10u);
|
||||
assert_eq!(r.gen_ascii_chars().take(16).len(), 16u);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_gen_vec() {
|
||||
let mut r = task_rng();
|
||||
assert_eq!(r.gen_iter::<u8>().take(0).len(), 0u);
|
||||
assert_eq!(r.gen_iter::<u8>().take(10).len(), 10u);
|
||||
assert_eq!(r.gen_iter::<f64>().take(16).len(), 16u);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_choose() {
|
||||
let mut r = task_rng();
|
||||
assert_eq!(r.choose([1, 1, 1]).map(|&x|x), Some(1));
|
||||
|
||||
let v: &[int] = &[];
|
||||
assert_eq!(r.choose(v), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_shuffle() {
|
||||
let mut r = task_rng();
|
||||
let empty: &mut [int] = &mut [];
|
||||
r.shuffle(empty);
|
||||
let mut one = [1];
|
||||
r.shuffle(one);
|
||||
assert_eq!(one.as_slice(), &[1]);
|
||||
|
||||
let mut two = [1, 2];
|
||||
r.shuffle(two);
|
||||
assert!(two == [1, 2] || two == [2, 1]);
|
||||
|
||||
let mut x = [1, 1, 1];
|
||||
r.shuffle(x);
|
||||
assert_eq!(x.as_slice(), &[1, 1, 1]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_task_rng() {
|
||||
let mut r = task_rng();
|
||||
r.gen::<int>();
|
||||
let mut v = [1, 1, 1];
|
||||
r.shuffle(v);
|
||||
assert_eq!(v.as_slice(), &[1, 1, 1]);
|
||||
assert_eq!(r.gen_range(0u, 1u), 0u);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_random() {
|
||||
// not sure how to test this aside from just getting some values
|
||||
let _n : uint = random();
|
||||
let _f : f32 = random();
|
||||
let _o : Option<Option<i8>> = random();
|
||||
let _many : ((),
|
||||
(uint,
|
||||
int,
|
||||
Option<(u32, (bool,))>),
|
||||
(u8, i8, u16, i16, u32, i32, u64, i64),
|
||||
(f32, (f64, (f64,)))) = random();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_sample() {
|
||||
let min_val = 1;
|
||||
let max_val = 100;
|
||||
|
||||
let mut r = task_rng();
|
||||
let vals = range(min_val, max_val).collect::<Vec<int>>();
|
||||
let small_sample = sample(&mut r, vals.iter(), 5);
|
||||
let large_sample = sample(&mut r, vals.iter(), vals.len() + 5);
|
||||
|
||||
assert_eq!(small_sample.len(), 5);
|
||||
assert_eq!(large_sample.len(), vals.len());
|
||||
|
||||
assert!(small_sample.iter().all(|e| {
|
||||
**e >= min_val && **e <= max_val
|
||||
}));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_std_rng_seeded() {
|
||||
let s = task_rng().gen_iter::<uint>().take(256).collect::<Vec<uint>>();
|
||||
let mut ra: StdRng = SeedableRng::from_seed(s.as_slice());
|
||||
let mut rb: StdRng = SeedableRng::from_seed(s.as_slice());
|
||||
assert!(order::equals(ra.gen_ascii_chars().take(100),
|
||||
rb.gen_ascii_chars().take(100)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_std_rng_reseed() {
|
||||
let s = task_rng().gen_iter::<uint>().take(256).collect::<Vec<uint>>();
|
||||
let mut r: StdRng = SeedableRng::from_seed(s.as_slice());
|
||||
let string1 = r.gen_ascii_chars().take(100).collect::<String>();
|
||||
|
||||
r.reseed(s.as_slice());
|
||||
|
||||
let string2 = r.gen_ascii_chars().take(100).collect::<String>();
|
||||
assert_eq!(string1, string2);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
static RAND_BENCH_N: u64 = 100;
|
||||
|
||||
#[cfg(test)]
|
||||
mod bench {
|
||||
extern crate test;
|
||||
use prelude::*;
|
||||
|
||||
use self::test::Bencher;
|
||||
use super::{XorShiftRng, StdRng, IsaacRng, Isaac64Rng, Rng, RAND_BENCH_N};
|
||||
use super::{OSRng, weak_rng};
|
||||
use mem::size_of;
|
||||
|
||||
#[bench]
|
||||
fn rand_xorshift(b: &mut Bencher) {
|
||||
let mut rng: XorShiftRng = OSRng::new().unwrap().gen();
|
||||
b.iter(|| {
|
||||
for _ in range(0, RAND_BENCH_N) {
|
||||
rng.gen::<uint>();
|
||||
}
|
||||
});
|
||||
b.bytes = size_of::<uint>() as u64 * RAND_BENCH_N;
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn rand_isaac(b: &mut Bencher) {
|
||||
let mut rng: IsaacRng = OSRng::new().unwrap().gen();
|
||||
b.iter(|| {
|
||||
for _ in range(0, RAND_BENCH_N) {
|
||||
rng.gen::<uint>();
|
||||
}
|
||||
});
|
||||
b.bytes = size_of::<uint>() as u64 * RAND_BENCH_N;
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn rand_isaac64(b: &mut Bencher) {
|
||||
let mut rng: Isaac64Rng = OSRng::new().unwrap().gen();
|
||||
b.iter(|| {
|
||||
for _ in range(0, RAND_BENCH_N) {
|
||||
rng.gen::<uint>();
|
||||
}
|
||||
});
|
||||
b.bytes = size_of::<uint>() as u64 * RAND_BENCH_N;
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn rand_std(b: &mut Bencher) {
|
||||
let mut rng = StdRng::new().unwrap();
|
||||
b.iter(|| {
|
||||
for _ in range(0, RAND_BENCH_N) {
|
||||
rng.gen::<uint>();
|
||||
}
|
||||
});
|
||||
b.bytes = size_of::<uint>() as u64 * RAND_BENCH_N;
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn rand_shuffle_100(b: &mut Bencher) {
|
||||
let mut rng = weak_rng();
|
||||
let x : &mut[uint] = [1,..100];
|
||||
b.iter(|| {
|
||||
rng.shuffle(x);
|
||||
})
|
||||
}
|
||||
}
|
|
@ -15,9 +15,11 @@ pub use self::imp::OSRng;
|
|||
|
||||
#[cfg(unix)]
|
||||
mod imp {
|
||||
use Rng;
|
||||
use reader::ReaderRng;
|
||||
use std::io::{IoResult, File};
|
||||
use io::{IoResult, File};
|
||||
use path::Path;
|
||||
use rand::Rng;
|
||||
use rand::reader::ReaderRng;
|
||||
use result::{Ok, Err};
|
||||
|
||||
/// A random number generator that retrieves randomness straight from
|
||||
/// the operating system. Platform sources:
|
||||
|
@ -60,12 +62,16 @@ mod imp {
|
|||
mod imp {
|
||||
extern crate libc;
|
||||
|
||||
use Rng;
|
||||
use std::io::{IoResult, IoError};
|
||||
use std::mem;
|
||||
use std::os;
|
||||
use std::rt::stack;
|
||||
use container::Container;
|
||||
use io::{IoResult, IoError};
|
||||
use mem;
|
||||
use ops::Drop;
|
||||
use os;
|
||||
use rand::Rng;
|
||||
use result::{Ok, Err};
|
||||
use rt::stack;
|
||||
use self::libc::{c_ulong, DWORD, BYTE, LPCSTR, BOOL};
|
||||
use slice::MutableVector;
|
||||
|
||||
type HCRYPTPROV = c_ulong;
|
||||
|
||||
|
@ -189,9 +195,11 @@ mod imp {
|
|||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use prelude::*;
|
||||
|
||||
use super::OSRng;
|
||||
use Rng;
|
||||
use std::task;
|
||||
use rand::Rng;
|
||||
use task;
|
||||
|
||||
#[test]
|
||||
fn test_os_rng() {
|
|
@ -10,7 +10,10 @@
|
|||
|
||||
//! A wrapper around any Reader to treat it as an RNG.
|
||||
|
||||
use Rng;
|
||||
use container::Container;
|
||||
use io::Reader;
|
||||
use rand::Rng;
|
||||
use result::{Ok, Err};
|
||||
|
||||
/// An RNG that reads random bytes straight from a `Reader`. This will
|
||||
/// work best with an infinite reader, but this is not required.
|
||||
|
@ -20,7 +23,7 @@ use Rng;
|
|||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use rand::{reader, Rng};
|
||||
/// use std::rand::{reader, Rng};
|
||||
/// use std::io::MemReader;
|
||||
///
|
||||
/// let mut rng = reader::ReaderRng::new(MemReader::new(vec!(1,2,3,4,5,6,7,8)));
|
||||
|
@ -70,10 +73,12 @@ impl<R: Reader> Rng for ReaderRng<R> {
|
|||
#[cfg(test)]
|
||||
#[allow(deprecated_owned_vector)]
|
||||
mod test {
|
||||
use prelude::*;
|
||||
|
||||
use super::ReaderRng;
|
||||
use std::io::MemReader;
|
||||
use std::mem;
|
||||
use Rng;
|
||||
use io::MemReader;
|
||||
use mem;
|
||||
use rand::Rng;
|
||||
|
||||
#[test]
|
||||
fn test_reader_rng_u64() {
|
|
@ -1303,7 +1303,8 @@ mod tests {
|
|||
use realstd::clone::Clone;
|
||||
for len in range(4u, 25) {
|
||||
for _ in range(0, 100) {
|
||||
let mut v = task_rng().gen_vec::<uint>(len);
|
||||
let mut v = task_rng().gen_iter::<uint>().take(len)
|
||||
.collect::<Vec<uint>>();
|
||||
let mut v1 = v.clone();
|
||||
|
||||
v.as_mut_slice().sort();
|
||||
|
@ -2321,7 +2322,7 @@ mod bench {
|
|||
fn sort_random_small(b: &mut Bencher) {
|
||||
let mut rng = weak_rng();
|
||||
b.iter(|| {
|
||||
let mut v = rng.gen_vec::<u64>(5);
|
||||
let mut v = rng.gen_iter::<u64>().take(5).collect::<Vec<u64>>();
|
||||
v.as_mut_slice().sort();
|
||||
});
|
||||
b.bytes = 5 * mem::size_of::<u64>() as u64;
|
||||
|
@ -2331,7 +2332,7 @@ mod bench {
|
|||
fn sort_random_medium(b: &mut Bencher) {
|
||||
let mut rng = weak_rng();
|
||||
b.iter(|| {
|
||||
let mut v = rng.gen_vec::<u64>(100);
|
||||
let mut v = rng.gen_iter::<u64>().take(100).collect::<Vec<u64>>();
|
||||
v.as_mut_slice().sort();
|
||||
});
|
||||
b.bytes = 100 * mem::size_of::<u64>() as u64;
|
||||
|
@ -2341,7 +2342,7 @@ mod bench {
|
|||
fn sort_random_large(b: &mut Bencher) {
|
||||
let mut rng = weak_rng();
|
||||
b.iter(|| {
|
||||
let mut v = rng.gen_vec::<u64>(10000);
|
||||
let mut v = rng.gen_iter::<u64>().take(10000).collect::<Vec<u64>>();
|
||||
v.as_mut_slice().sort();
|
||||
});
|
||||
b.bytes = 10000 * mem::size_of::<u64>() as u64;
|
||||
|
@ -2362,7 +2363,8 @@ mod bench {
|
|||
fn sort_big_random_small(b: &mut Bencher) {
|
||||
let mut rng = weak_rng();
|
||||
b.iter(|| {
|
||||
let mut v = rng.gen_vec::<BigSortable>(5);
|
||||
let mut v = rng.gen_iter::<BigSortable>().take(5)
|
||||
.collect::<Vec<BigSortable>>();
|
||||
v.sort();
|
||||
});
|
||||
b.bytes = 5 * mem::size_of::<BigSortable>() as u64;
|
||||
|
@ -2372,7 +2374,8 @@ mod bench {
|
|||
fn sort_big_random_medium(b: &mut Bencher) {
|
||||
let mut rng = weak_rng();
|
||||
b.iter(|| {
|
||||
let mut v = rng.gen_vec::<BigSortable>(100);
|
||||
let mut v = rng.gen_iter::<BigSortable>().take(100)
|
||||
.collect::<Vec<BigSortable>>();
|
||||
v.sort();
|
||||
});
|
||||
b.bytes = 100 * mem::size_of::<BigSortable>() as u64;
|
||||
|
@ -2382,7 +2385,8 @@ mod bench {
|
|||
fn sort_big_random_large(b: &mut Bencher) {
|
||||
let mut rng = weak_rng();
|
||||
b.iter(|| {
|
||||
let mut v = rng.gen_vec::<BigSortable>(10000);
|
||||
let mut v = rng.gen_iter::<BigSortable>().take(10000)
|
||||
.collect::<Vec<BigSortable>>();
|
||||
v.sort();
|
||||
});
|
||||
b.bytes = 10000 * mem::size_of::<BigSortable>() as u64;
|
||||
|
|
|
@ -23,7 +23,7 @@ pub fn expand_deriving_rand(cx: &mut ExtCtxt,
|
|||
let trait_def = TraitDef {
|
||||
span: span,
|
||||
attributes: Vec::new(),
|
||||
path: Path::new(vec!("rand", "Rand")),
|
||||
path: Path::new(vec!("std", "rand", "Rand")),
|
||||
additional_bounds: Vec::new(),
|
||||
generics: LifetimeBounds::empty(),
|
||||
methods: vec!(
|
||||
|
@ -33,7 +33,7 @@ pub fn expand_deriving_rand(cx: &mut ExtCtxt,
|
|||
lifetimes: Vec::new(),
|
||||
bounds: vec!(("R",
|
||||
ast::StaticSize,
|
||||
vec!( Path::new(vec!("rand", "Rng")) )))
|
||||
vec!( Path::new(vec!("std", "rand", "Rng")) )))
|
||||
},
|
||||
explicit_self: None,
|
||||
args: vec!(
|
||||
|
@ -58,6 +58,7 @@ fn rand_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure)
|
|||
_ => cx.bug("Incorrect number of arguments to `rand` in `deriving(Rand)`")
|
||||
};
|
||||
let rand_ident = vec!(
|
||||
cx.ident_of("std"),
|
||||
cx.ident_of("rand"),
|
||||
cx.ident_of("Rand"),
|
||||
cx.ident_of("rand")
|
||||
|
|
|
@ -67,21 +67,19 @@ Examples of string representations:
|
|||
// test harness access
|
||||
#[cfg(test)]
|
||||
extern crate test;
|
||||
|
||||
extern crate rand;
|
||||
extern crate serialize;
|
||||
|
||||
use std::mem::{transmute,transmute_copy};
|
||||
use std::char::Char;
|
||||
use std::default::Default;
|
||||
use std::fmt;
|
||||
use std::from_str::FromStr;
|
||||
use std::hash::Hash;
|
||||
use std::mem::{transmute,transmute_copy};
|
||||
use std::num::FromStrRadix;
|
||||
use std::str;
|
||||
use std::rand;
|
||||
use std::rand::Rng;
|
||||
use std::slice;
|
||||
|
||||
use rand::Rng;
|
||||
use std::str;
|
||||
|
||||
use serialize::{Encoder, Encodable, Decoder, Decodable};
|
||||
|
||||
|
@ -194,7 +192,7 @@ impl Uuid {
|
|||
/// of random numbers. Use the rand::Rand trait to supply
|
||||
/// a custom generator if required.
|
||||
pub fn new_v4() -> Uuid {
|
||||
let ub = rand::task_rng().gen_vec(16);
|
||||
let ub = rand::task_rng().gen_iter::<u8>().take(16).collect::<Vec<_>>();
|
||||
let mut uuid = Uuid{ bytes: [0, .. 16] };
|
||||
slice::bytes::copy_memory(uuid.bytes, ub.as_slice());
|
||||
uuid.set_variant(VariantRFC4122);
|
||||
|
@ -510,7 +508,7 @@ impl<T: Decoder<E>, E> Decodable<T, E> for Uuid {
|
|||
impl rand::Rand for Uuid {
|
||||
#[inline]
|
||||
fn rand<R: rand::Rng>(rng: &mut R) -> Uuid {
|
||||
let ub = rng.gen_vec(16);
|
||||
let ub = rng.gen_iter::<u8>().take(16).collect::<Vec<_>>();
|
||||
let mut uuid = Uuid{ bytes: [0, .. 16] };
|
||||
slice::bytes::copy_memory(uuid.bytes, ub.as_slice());
|
||||
uuid.set_variant(VariantRFC4122);
|
||||
|
@ -522,13 +520,13 @@ impl rand::Rand for Uuid {
|
|||
#[cfg(test)]
|
||||
mod test {
|
||||
extern crate collections;
|
||||
extern crate rand;
|
||||
|
||||
use super::{Uuid, VariantMicrosoft, VariantNCS, VariantRFC4122,
|
||||
Version1Mac, Version2Dce, Version3Md5, Version4Random,
|
||||
Version5Sha1};
|
||||
use std::str;
|
||||
use std::io::MemWriter;
|
||||
use std::rand;
|
||||
|
||||
#[test]
|
||||
fn test_nil() {
|
||||
|
@ -788,7 +786,7 @@ mod test {
|
|||
#[test]
|
||||
fn test_rand_rand() {
|
||||
let mut rng = rand::task_rng();
|
||||
let u: Box<Uuid> = rand::Rand::rand(&mut rng);
|
||||
let u: Uuid = rand::Rand::rand(&mut rng);
|
||||
let ub = u.as_bytes();
|
||||
|
||||
assert!(ub.len() == 16);
|
||||
|
|
|
@ -12,11 +12,11 @@
|
|||
|
||||
#![feature(macro_rules)]
|
||||
|
||||
extern crate rand;
|
||||
extern crate time;
|
||||
|
||||
use time::precise_time_s;
|
||||
use rand::Rng;
|
||||
use std::rand;
|
||||
use std::rand::Rng;
|
||||
use std::mem::swap;
|
||||
use std::os;
|
||||
use std::str;
|
||||
|
|
|
@ -11,10 +11,8 @@
|
|||
// Multi-language Perlin noise benchmark.
|
||||
// See https://github.com/nsf/pnoise for timings and alternative implementations.
|
||||
|
||||
extern crate rand;
|
||||
|
||||
use std::f32::consts::PI;
|
||||
use rand::{Rng, StdRng};
|
||||
use std::rand::{Rng, StdRng};
|
||||
|
||||
struct Vec2 {
|
||||
x: f32,
|
||||
|
|
|
@ -10,11 +10,11 @@
|
|||
|
||||
// ensure that the TaskRng isn't/doesn't become accidentally sendable.
|
||||
|
||||
extern crate rand;
|
||||
use std::rand;
|
||||
|
||||
fn test_send<S: Send>() {}
|
||||
|
||||
pub fn main() {
|
||||
test_send::<::rand::TaskRng>();
|
||||
//~^ ERROR: incompatible type `rand::TaskRng`, which does not fulfill `Send`
|
||||
test_send::<rand::TaskRng>();
|
||||
//~^ ERROR: incompatible type `std::rand::TaskRng`, which does not fulfill `Send`
|
||||
}
|
||||
|
|
|
@ -8,11 +8,9 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
extern crate rand;
|
||||
use rand::{task_rng, Rng};
|
||||
|
||||
use std::{char, os, str};
|
||||
use std::io::{File, Command};
|
||||
use std::rand::{task_rng, Rng};
|
||||
|
||||
// creates unicode_input_multiple_files_{main,chars}.rs, where the
|
||||
// former imports the latter. `_chars` just contains an indentifier
|
||||
|
|
|
@ -8,11 +8,9 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
extern crate rand;
|
||||
use rand::{task_rng, Rng};
|
||||
|
||||
use std::{char, os, str};
|
||||
use std::io::{File, Command};
|
||||
use std::rand::{task_rng, Rng};
|
||||
|
||||
// creates a file with `fn main() { <random ident> }` and checks the
|
||||
// compiler emits a span of the appropriate length (for the
|
||||
|
|
|
@ -8,10 +8,9 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
|
||||
#![feature(struct_variant)]
|
||||
|
||||
extern crate rand;
|
||||
use std::rand;
|
||||
|
||||
#[deriving(Rand)]
|
||||
struct A;
|
||||
|
|
|
@ -8,10 +8,8 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
extern crate rand;
|
||||
|
||||
use std::task;
|
||||
use rand::{task_rng, Rng};
|
||||
use std::rand::{task_rng, Rng};
|
||||
|
||||
static MAX_LEN: uint = 20;
|
||||
static mut drop_counts: [uint, .. MAX_LEN] = [0, .. MAX_LEN];
|
||||
|
@ -46,7 +44,9 @@ pub fn main() {
|
|||
// len can't go above 64.
|
||||
for len in range(2u, MAX_LEN) {
|
||||
for _ in range(0, 10) {
|
||||
let main = task_rng().gen_vec::<DropCounter>(len);
|
||||
let main = task_rng().gen_iter::<DropCounter>()
|
||||
.take(len)
|
||||
.collect::<Vec<DropCounter>>();
|
||||
|
||||
// work out the total number of comparisons required to sort
|
||||
// this array...
|
||||
|
|
Loading…
Add table
Reference in a new issue