diff --git a/mk/crates.mk b/mk/crates.mk index a4dc0c0465e77..a683528c847aa 100644 --- a/mk/crates.mk +++ b/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 diff --git a/src/doc/guide-tasks.md b/src/doc/guide-tasks.md index ad6ec65ef44ba..6b45174591462 100644 --- a/src/doc/guide-tasks.md +++ b/src/doc/guide-tasks.md @@ -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::()); @@ -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() { diff --git a/src/libcollections/bitv.rs b/src/libcollections/bitv.rs index 0b5d499c533bc..48491222be47e 100644 --- a/src/libcollections/bitv.rs +++ b/src/libcollections/bitv.rs @@ -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; diff --git a/src/libcollections/deque.rs b/src/libcollections/deque.rs index e031b07f87296..fa2cb233873d9 100644 --- a/src/libcollections/deque.rs +++ b/src/libcollections/deque.rs @@ -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>(n: uint, map: &mut M, diff --git a/src/libcollections/dlist.rs b/src/libcollections/dlist.rs index 8072ee02bc012..957299197386f 100644 --- a/src/libcollections/dlist.rs +++ b/src/libcollections/dlist.rs @@ -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(list: &DList) { diff --git a/src/libcollections/hashmap.rs b/src/libcollections/hashmap.rs index 42b57a1ea4063..6f5c0a8c2402e 100644 --- a/src/libcollections/hashmap.rs +++ b/src/libcollections/hashmap.rs @@ -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; diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs index cbf4ae03a7670..d1c75b895798a 100644 --- a/src/libcollections/lib.rs +++ b/src/libcollections/lib.rs @@ -24,7 +24,6 @@ #![deny(deprecated_owned_vector)] -extern crate rand; extern crate debug; #[cfg(test)] extern crate test; diff --git a/src/libcollections/treemap.rs b/src/libcollections/treemap.rs index fb663d91131af..3e862f280606c 100644 --- a/src/libcollections/treemap.rs +++ b/src/libcollections/treemap.rs @@ -1000,8 +1000,8 @@ impl Extendable for TreeSet { mod test_treemap { use super::{TreeMap, TreeNode}; - use rand::Rng; - use rand; + use std::rand::Rng; + use std::rand; #[test] fn find_empty() { diff --git a/src/libcollections/trie.rs b/src/libcollections/trie.rs index 9d64b3c2394b0..e6df4fd87e12e 100644 --- a/src/libcollections/trie.rs +++ b/src/libcollections/trie.rs @@ -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] diff --git a/src/libcore/any.rs b/src/libcore/any.rs index 94ac344db3485..f463c194424da 100644 --- a/src/libcore/any.rs +++ b/src/libcore/any.rs @@ -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; diff --git a/src/libcore/char.rs b/src/libcore/char.rs index 0c5d3151af0f5..2d1cab5d84156 100644 --- a/src/libcore/char.rs +++ b/src/libcore/char.rs @@ -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() { diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 13236a1f654d0..f41efdbc1db6f 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -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: &mut T, b: &[u8]) { diff --git a/src/libcore/fmt/num.rs b/src/libcore/fmt/num.rs index 731911185ff7e..7ad78df2fe8ce 100644 --- a/src/libcore/fmt/num.rs +++ b/src/libcore/fmt/num.rs @@ -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::()); }) } #[bench] fn format_oct(b: &mut Bencher) { - let mut rng = XorShiftRng::new().unwrap(); + let mut rng = weak_rng(); b.iter(|| { format!("{:o}", rng.gen::()); }) } #[bench] fn format_dec(b: &mut Bencher) { - let mut rng = XorShiftRng::new().unwrap(); + let mut rng = weak_rng(); b.iter(|| { format!("{:u}", rng.gen::()); }) } #[bench] fn format_hex(b: &mut Bencher) { - let mut rng = XorShiftRng::new().unwrap(); + let mut rng = weak_rng(); b.iter(|| { format!("{:x}", rng.gen::()); }) } #[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::(), 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::()); }) } #[bench] fn format_oct(b: &mut Bencher) { - let mut rng = XorShiftRng::new().unwrap(); + let mut rng = weak_rng(); b.iter(|| { format!("{:o}", rng.gen::()); }) } #[bench] fn format_dec(b: &mut Bencher) { - let mut rng = XorShiftRng::new().unwrap(); + let mut rng = weak_rng(); b.iter(|| { format!("{:d}", rng.gen::()); }) } #[bench] fn format_hex(b: &mut Bencher) { - let mut rng = XorShiftRng::new().unwrap(); + let mut rng = weak_rng(); b.iter(|| { format!("{:x}", rng.gen::()); }) } #[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::(), 36)); }) } } diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 56cbe2e2a30d1..2ff2dca0c8673 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -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; diff --git a/src/libcore/result.rs b/src/libcore/result.rs index 926605dddb3e6..fd51ede204ff1 100644 --- a/src/libcore/result.rs +++ b/src/libcore/result.rs @@ -637,11 +637,10 @@ pub fn fold_>>(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 { Ok(666) } diff --git a/src/libcore/tuple.rs b/src/libcore/tuple.rs index 059b96ffac713..edcb37dbb64c2 100644 --- a/src/libcore/tuple.rs +++ b/src/libcore/tuple.rs @@ -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() { diff --git a/src/libflate/lib.rs b/src/libflate/lib.rs index 54f147dead8b6..8bfd2d867c130 100644 --- a/src/libflate/lib.rs +++ b/src/libflate/lib.rs @@ -108,10 +108,9 @@ pub fn inflate_bytes_zlib(bytes: &[u8]) -> Option> { #[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::(range)); + let v = r.gen_iter::().take(range).collect::>(); + words.push(v); } for _ in range(0, 20) { let mut input = vec![]; diff --git a/src/libgreen/lib.rs b/src/libgreen/lib.rs index 4584c08cbd898..31fd8950c804c 100644 --- a/src/libgreen/lib.rs +++ b/src/libgreen/lib.rs @@ -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; diff --git a/src/libgreen/sched.rs b/src/libgreen/sched.rs index d28e74a2b80b7..401c438988316 100644 --- a/src/libgreen/sched.rs +++ b/src/libgreen/sched.rs @@ -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) } diff --git a/src/libnum/bigint.rs b/src/libnum/bigint.rs index cc35cd749d663..c6af8ac9b4b89 100644 --- a/src/libnum/bigint.rs +++ b/src/libnum/bigint.rs @@ -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] diff --git a/src/librand/distributions/exponential.rs b/src/librand/distributions/exponential.rs index 03c87eb931d60..d4e689ccb5c59 100644 --- a/src/librand/distributions/exponential.rs +++ b/src/librand/distributions/exponential.rs @@ -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 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::() as u64 * RAND_BENCH_N; + b.bytes = size_of::() as u64 * ::RAND_BENCH_N; } } diff --git a/src/librand/distributions/gamma.rs b/src/librand/distributions/gamma.rs index 1bb2c35bce206..445fe9acbeca0 100644 --- a/src/librand/distributions/gamma.rs +++ b/src/librand/distributions/gamma.rs @@ -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 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 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 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 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::() as u64 * RAND_BENCH_N; + b.bytes = size_of::() 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::() as u64 * RAND_BENCH_N; + b.bytes = size_of::() as u64 * ::RAND_BENCH_N; } } diff --git a/src/librand/distributions/mod.rs b/src/librand/distributions/mod.rs index b3535a695eaf3..bb09db4880269 100644 --- a/src/librand/distributions/mod.rs +++ b/src/librand/distributions/mod.rs @@ -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 { /// # 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 { - items: Vec>, +pub struct WeightedChoice<'a, T> { + items: &'a mut [Weighted], weight_range: Range } -impl WeightedChoice { +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>) -> WeightedChoice { + pub fn new<'a>(items: &'a mut [Weighted]) -> 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 WeightedChoice { // 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 WeightedChoice { } } -impl Sample for WeightedChoice { +impl<'a, T: Clone> Sample for WeightedChoice<'a, T> { fn sample(&mut self, rng: &mut R) -> T { self.ind_sample(rng) } } -impl IndependentSample for WeightedChoice { +impl<'a, T: Clone> IndependentSample for WeightedChoice<'a, T> { fn ind_sample(&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 IndependentSample for WeightedChoice { 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 IndependentSample for WeightedChoice { // 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 IndependentSample for WeightedChoice { } modifier /= 2; } - return self.items.get(idx + 1).item.clone(); + return self.items[idx + 1].item.clone(); } } @@ -247,7 +255,9 @@ fn ziggurat( #[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::; - 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::::new(vec!()); + WeightedChoice::::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 }]); } } diff --git a/src/librand/distributions/normal.rs b/src/librand/distributions/normal.rs index dea73945b4384..47ab7d32e0575 100644 --- a/src/librand/distributions/normal.rs +++ b/src/librand/distributions/normal.rs @@ -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 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 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::() as u64 * RAND_BENCH_N; + b.bytes = size_of::() as u64 * ::RAND_BENCH_N; } } diff --git a/src/librand/distributions/range.rs b/src/librand/distributions/range.rs index cee80b62e3dec..f0e1d1715a2ba 100644 --- a/src/librand/distributions/range.rs +++ b/src/librand/distributions/range.rs @@ -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),*) => {{ $( diff --git a/src/librand/isaac.rs b/src/librand/isaac.rs index 1d9da40f18b6e..50ecabfc638be 100644 --- a/src/librand/isaac.rs +++ b/src/librand/isaac.rs @@ -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 { - 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(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 { - 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(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::(256); + let s = ::test::rng().gen_iter::().take(256).collect::>(); 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::(256); + let s = ::test::rng().gen_iter::().take(256).collect::>(); 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::(256); + let s = ::test::rng().gen_iter::().take(256).collect::>(); 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::(256); + let s = ::test::rng().gen_iter::().take(256).collect::>(); 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); } diff --git a/src/librand/lib.rs b/src/librand/lib.rs index 4a11b69207600..93a00c4e0a63a 100644 --- a/src/librand/lib.rs +++ b/src/librand/lib.rs @@ -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::()`. - -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::(), rng.gen::()) -} -``` - -```rust -let tuple_ptr = rand::random::>(); -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 = rng.gen_vec(10); + /// let x = rng.gen_iter::().take(10).collect::>(); /// println!("{}", x); - /// println!("{}", rng.gen_vec::<(f64, bool)>(5)); + /// println!("{}", rng.gen_iter::<(f64, bool)>().take(5) + /// .collect::>()); /// ``` - fn gen_vec(&mut self, len: uint) -> Vec { - 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>(&mut self, iter: T, n: uint) -> Vec { - 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 for Generator<'a, T, R> { + fn next(&mut self) -> Option { + 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 for AsciiGenerator<'a, R> { + fn next(&mut self) -> Option { + 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: 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::()); @@ -373,7 +320,7 @@ pub trait SeedableRng: 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::()); @@ -381,89 +328,6 @@ pub trait SeedableRng: 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 { - 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 { - 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,122 +402,16 @@ impl SeedableRng<[u32, .. 4]> for XorShiftRng { } } -impl XorShiftRng { - /// Create an xor shift random number generator with a random seed. - pub fn new() -> IoResult { - let mut s = [0u8, ..16]; - let mut r = try!(OSRng::new()); - loop { - r.fill_bytes(s); - - if !s.iter().all(|x| *x == 0) { - break; - } - } - let s: [u32, ..4] = unsafe { mem::transmute(s) }; - Ok(SeedableRng::from_seed(s)) - } -} - -/// Controls how the task-local RNG is reseeded. -struct TaskRngReseeder; - -impl reseeding::Reseeder 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) +impl Rand for XorShiftRng { + fn rand(rng: &mut R) -> XorShiftRng { + let mut tuple: (u32, u32, u32, u32) = rng.gen(); + while tuple == (0, 0, 0, 0) { + tuple = rng.gen(); } + let (x, y, z, w) = tuple; + XorShiftRng { x: x, y: y, z: z, w: w } } } -static TASK_RNG_RESEED_THRESHOLD: uint = 32_768; -type TaskRngInner = reseeding::ReseedingRng; -/// 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::()`. -/// -/// 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) - - 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::()); -/// } -/// ``` -#[inline] -pub fn random() -> 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 { /// /// # Example /// ```rust -/// use rand::{random, Open01}; +/// use std::rand::{random, Open01}; /// /// let Open01(val) = random::>(); /// println!("f32 from (0,1): {}", val); @@ -662,263 +437,41 @@ pub struct Open01(pub F); /// `[0,1)`. /// /// # Example +/// /// ```rust -/// use rand::{random, Closed01}; +/// use std::rand::{random, Closed01}; /// /// let Closed01(val) = random::>(); /// println!("f32 from [0,1]: {}", val); /// ``` pub struct Closed01(pub F); -#[cfg(test)] -mod test { - use super::{Rng, task_rng, random, SeedableRng, StdRng}; - - 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::(); - let b = r.gen::(); - 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::(0u).len(), 0u); - assert_eq!(r.gen_vec::(10u).len(), 10u); - assert_eq!(r.gen_vec::(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::(); - 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> = random(); - let _many : ((), - (Box, - @int, - Box)>>>), - (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::>(); - 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::(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::(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(not(test))] +mod std { + pub use core::{option, fmt}; // fail!() } #[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::(); - } - }); - b.bytes = size_of::() as u64 * RAND_BENCH_N; - } +mod test { + use std::rand; - #[bench] - fn rand_isaac(b: &mut Bencher) { - let mut rng = IsaacRng::new().unwrap(); - b.iter(|| { - for _ in range(0, RAND_BENCH_N) { - rng.gen::(); - } - }); - b.bytes = size_of::() as u64 * RAND_BENCH_N; - } + pub struct MyRng { inner: R } - #[bench] - fn rand_isaac64(b: &mut Bencher) { - let mut rng = Isaac64Rng::new().unwrap(); - b.iter(|| { - for _ in range(0, RAND_BENCH_N) { - rng.gen::(); + impl ::Rng for MyRng { + fn next_u32(&mut self) -> u32 { + fn next(t: &mut T) -> u32 { + use std::rand::Rng; + t.next_u32() } - }); - b.bytes = size_of::() as u64 * RAND_BENCH_N; + next(&mut self.inner) + } } - #[bench] - fn rand_std(b: &mut Bencher) { - let mut rng = StdRng::new().unwrap(); - b.iter(|| { - for _ in range(0, RAND_BENCH_N) { - rng.gen::(); - } - }); - b.bytes = size_of::() as u64 * RAND_BENCH_N; + pub fn rng() -> MyRng { + MyRng { inner: rand::task_rng() } } - #[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 { + MyRng { inner: rand::weak_rng() } } } diff --git a/src/librand/rand_impls.rs b/src/librand/rand_impls.rs index 5846cb5f312ca..458a9ba378d98 100644 --- a/src/librand/rand_impls.rs +++ b/src/librand/rand_impls.rs @@ -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 Rand for Option { } } -impl Rand for Box { - #[inline] - fn rand(rng: &mut R) -> Box { box rng.gen() } -} - -impl Rand for @T { - #[inline] - fn rand(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 { diff --git a/src/librand/reseeding.rs b/src/librand/reseeding.rs index fe2ff319c1cad..09265f28c36fa 100644 --- a/src/librand/reseeding.rs +++ b/src/librand/reseeding.rs @@ -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> Rng for ReseedingRng { } } -impl, Rsdr: Reseeder> +impl, Rsdr: Reseeder + Default> SeedableRng<(Rsdr, S)> for ReseedingRng { 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 { @@ -100,8 +103,8 @@ impl, Rsdr: Reseeder> /// # 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 for TickTockReseeder { @@ -118,7 +121,8 @@ impl, Rsdr: Reseeder> /// 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. diff --git a/src/libregex/test/bench.rs b/src/libregex/test/bench.rs index 8dc6484a13629..7c806ece5c85b 100644 --- a/src/libregex/test/bench.rs +++ b/src/libregex/test/bench.rs @@ -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::>(); for (i, b) in bytes.mut_iter().enumerate() { if i % 20 == 0 { *b = '\n' as u8 diff --git a/src/libserialize/base64.rs b/src/libserialize/base64.rs index 5d2f229beb675..5a8759540c8b5 100644 --- a/src/libserialize/base64.rs +++ b/src/libserialize/base64.rs @@ -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); diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index c1bc68b3e1293..b63ccbef55faa 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -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; diff --git a/src/libstd/num/strconv.rs b/src/libstd/num/strconv.rs index 1efe83217f48d..20f5927c9bd50 100644 --- a/src/libstd/num/strconv.rs +++ b/src/libstd/num/strconv.rs @@ -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::().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::().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::().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::().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::().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::().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::().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::().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::().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::().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()); }) } } diff --git a/src/libstd/os.rs b/src/libstd/os.rs index f960228c63c68..f6b9a7b24bc93 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -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::()); assert!(getenv(n.as_slice()).is_none()); n } diff --git a/src/libstd/rand/mod.rs b/src/libstd/rand/mod.rs new file mode 100644 index 0000000000000..c7ae6331d11d9 --- /dev/null +++ b/src/libstd/rand/mod.rs @@ -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 or the MIT license +// , 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::()`. + +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::(), rng.gen::()) +} +``` + +```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 { + 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 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; + +/// The task-local RNG. +pub struct TaskRng { + rng: Rc>, +} + +/// 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::()`. +/// +/// 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>) + + 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::()); +/// } +/// ``` +#[inline] +pub fn random() -> 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, R: Rng>(rng: &mut R, + mut iter: I, + amt: uint) -> Vec { + let mut reservoir: Vec = 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::(); + let b = r.gen::(); + 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::().take(0).len(), 0u); + assert_eq!(r.gen_iter::().take(10).len(), 10u); + assert_eq!(r.gen_iter::().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::(); + 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> = 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::>(); + 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::().take(256).collect::>(); + 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::().take(256).collect::>(); + let mut r: StdRng = SeedableRng::from_seed(s.as_slice()); + let string1 = r.gen_ascii_chars().take(100).collect::(); + + r.reseed(s.as_slice()); + + let string2 = r.gen_ascii_chars().take(100).collect::(); + 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::(); + } + }); + b.bytes = size_of::() 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::(); + } + }); + b.bytes = size_of::() 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::(); + } + }); + b.bytes = size_of::() 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::(); + } + }); + b.bytes = size_of::() 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); + }) + } +} diff --git a/src/librand/os.rs b/src/libstd/rand/os.rs similarity index 95% rename from src/librand/os.rs rename to src/libstd/rand/os.rs index 0e1d01a45c986..ea4d7ad25a31f 100644 --- a/src/librand/os.rs +++ b/src/libstd/rand/os.rs @@ -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() { diff --git a/src/librand/reader.rs b/src/libstd/rand/reader.rs similarity index 94% rename from src/librand/reader.rs rename to src/libstd/rand/reader.rs index e800f64463b4e..170884073f3c3 100644 --- a/src/librand/reader.rs +++ b/src/libstd/rand/reader.rs @@ -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 Rng for ReaderRng { #[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() { diff --git a/src/libstd/slice.rs b/src/libstd/slice.rs index e5c0cc3babd03..55bea068641e1 100644 --- a/src/libstd/slice.rs +++ b/src/libstd/slice.rs @@ -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::(len); + let mut v = task_rng().gen_iter::().take(len) + .collect::>(); 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::(5); + let mut v = rng.gen_iter::().take(5).collect::>(); v.as_mut_slice().sort(); }); b.bytes = 5 * mem::size_of::() 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::(100); + let mut v = rng.gen_iter::().take(100).collect::>(); v.as_mut_slice().sort(); }); b.bytes = 100 * mem::size_of::() 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::(10000); + let mut v = rng.gen_iter::().take(10000).collect::>(); v.as_mut_slice().sort(); }); b.bytes = 10000 * mem::size_of::() 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::(5); + let mut v = rng.gen_iter::().take(5) + .collect::>(); v.sort(); }); b.bytes = 5 * mem::size_of::() 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::(100); + let mut v = rng.gen_iter::().take(100) + .collect::>(); v.sort(); }); b.bytes = 100 * mem::size_of::() 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::(10000); + let mut v = rng.gen_iter::().take(10000) + .collect::>(); v.sort(); }); b.bytes = 10000 * mem::size_of::() as u64; diff --git a/src/libsyntax/ext/deriving/rand.rs b/src/libsyntax/ext/deriving/rand.rs index 397b99925c8ec..5314b39f8056d 100644 --- a/src/libsyntax/ext/deriving/rand.rs +++ b/src/libsyntax/ext/deriving/rand.rs @@ -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") diff --git a/src/libuuid/lib.rs b/src/libuuid/lib.rs index 99dd7d8503c82..8263fcda314f8 100644 --- a/src/libuuid/lib.rs +++ b/src/libuuid/lib.rs @@ -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::().take(16).collect::>(); 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, E> Decodable for Uuid { impl rand::Rand for Uuid { #[inline] fn rand(rng: &mut R) -> Uuid { - let ub = rng.gen_vec(16); + let ub = rng.gen_iter::().take(16).collect::>(); 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 = rand::Rand::rand(&mut rng); + let u: Uuid = rand::Rand::rand(&mut rng); let ub = u.as_bytes(); assert!(ub.len() == 16); diff --git a/src/test/bench/core-std.rs b/src/test/bench/core-std.rs index d53a89684213d..bf50736b7e6d1 100644 --- a/src/test/bench/core-std.rs +++ b/src/test/bench/core-std.rs @@ -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; diff --git a/src/test/bench/noise.rs b/src/test/bench/noise.rs index 27540cc5bbf94..816a752921222 100644 --- a/src/test/bench/noise.rs +++ b/src/test/bench/noise.rs @@ -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, diff --git a/src/test/compile-fail/task-rng-isnt-sendable.rs b/src/test/compile-fail/task-rng-isnt-sendable.rs index 8b9d4de9f04c1..366e1fd4dcae4 100644 --- a/src/test/compile-fail/task-rng-isnt-sendable.rs +++ b/src/test/compile-fail/task-rng-isnt-sendable.rs @@ -10,11 +10,11 @@ // ensure that the TaskRng isn't/doesn't become accidentally sendable. -extern crate rand; +use std::rand; fn test_send() {} pub fn main() { - test_send::<::rand::TaskRng>(); - //~^ ERROR: incompatible type `rand::TaskRng`, which does not fulfill `Send` + test_send::(); + //~^ ERROR: incompatible type `std::rand::TaskRng`, which does not fulfill `Send` } diff --git a/src/test/run-make/unicode-input/multiple_files.rs b/src/test/run-make/unicode-input/multiple_files.rs index e41c5d1b6266e..3711503ee2b59 100644 --- a/src/test/run-make/unicode-input/multiple_files.rs +++ b/src/test/run-make/unicode-input/multiple_files.rs @@ -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 diff --git a/src/test/run-make/unicode-input/span_length.rs b/src/test/run-make/unicode-input/span_length.rs index b875f676982dc..ebb03435fe4d9 100644 --- a/src/test/run-make/unicode-input/span_length.rs +++ b/src/test/run-make/unicode-input/span_length.rs @@ -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() { }` and checks the // compiler emits a span of the appropriate length (for the diff --git a/src/test/run-pass/deriving-rand.rs b/src/test/run-pass/deriving-rand.rs index c455aebbe46ed..4e9592950d3da 100644 --- a/src/test/run-pass/deriving-rand.rs +++ b/src/test/run-pass/deriving-rand.rs @@ -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; diff --git a/src/test/run-pass/vector-sort-failure-safe.rs b/src/test/run-pass/vector-sort-failure-safe.rs index 00bc95b36f7a7..e5f1c48464de3 100644 --- a/src/test/run-pass/vector-sort-failure-safe.rs +++ b/src/test/run-pass/vector-sort-failure-safe.rs @@ -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::(len); + let main = task_rng().gen_iter::() + .take(len) + .collect::>(); // work out the total number of comparisons required to sort // this array...