]> git.lizzy.rs Git - rust.git/commitdiff
std: Recreate a `rand` module
authorAlex Crichton <alex@alexcrichton.com>
Sun, 25 May 2014 08:39:37 +0000 (01:39 -0700)
committerAlex Crichton <alex@alexcrichton.com>
Thu, 29 May 2014 23:18:26 +0000 (16:18 -0700)
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]

49 files changed:
mk/crates.mk
src/doc/guide-tasks.md
src/libcollections/bitv.rs
src/libcollections/deque.rs
src/libcollections/dlist.rs
src/libcollections/hashmap.rs
src/libcollections/lib.rs
src/libcollections/treemap.rs
src/libcollections/trie.rs
src/libcore/any.rs
src/libcore/char.rs
src/libcore/fmt/mod.rs
src/libcore/fmt/num.rs
src/libcore/lib.rs
src/libcore/result.rs
src/libcore/tuple.rs
src/libflate/lib.rs
src/libgreen/lib.rs
src/libgreen/sched.rs
src/libnum/bigint.rs
src/librand/distributions/exponential.rs
src/librand/distributions/gamma.rs
src/librand/distributions/mod.rs
src/librand/distributions/normal.rs
src/librand/distributions/range.rs
src/librand/isaac.rs
src/librand/lib.rs
src/librand/os.rs [deleted file]
src/librand/rand_impls.rs
src/librand/reader.rs [deleted file]
src/librand/reseeding.rs
src/libregex/test/bench.rs
src/libserialize/base64.rs
src/libstd/lib.rs
src/libstd/num/strconv.rs
src/libstd/os.rs
src/libstd/rand/mod.rs [new file with mode: 0644]
src/libstd/rand/os.rs [new file with mode: 0644]
src/libstd/rand/reader.rs [new file with mode: 0644]
src/libstd/slice.rs
src/libsyntax/ext/deriving/rand.rs
src/libuuid/lib.rs
src/test/bench/core-std.rs
src/test/bench/noise.rs
src/test/compile-fail/task-rng-isnt-sendable.rs
src/test/run-make/unicode-input/multiple_files.rs
src/test/run-make/unicode-input/span_length.rs
src/test/run-pass/deriving-rand.rs
src/test/run-pass/vector-sort-failure-safe.rs

index a4dc0c0465e77cdf7f4385773709583b317a7c43..a683528c847aa6757fc309972a021c2653d679f7 100644 (file)
@@ -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
index ad6ec65ef44baae93570575db8fe0e50aad1e311..6b45174591462776f7cf027c5376316fb8eab2f8 100644 (file)
@@ -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() {
index 0b5d499c533bc37d7bac5da57568bde590690000..48491222be47ea3c6a4aa0973f4df6b5e370cf7e 100644 (file)
@@ -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;
 
index e031b07f87296829973100303c09d68bc9d036b0..fa2cb233873d969e6dd426f241850251399d9f13 100644 (file)
@@ -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,
index 8072ee02bc0121ffd49d95131f94d580cd267fcc..957299197386f3e61b34a51b449bd5e551fd4fab 100644 (file)
@@ -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>) {
index 42b57a1ea40632844dac9c1fbea763bb3de72e1a..6f5c0a8c2402e2d643c6df200077d6d2aff71b81 100644 (file)
@@ -24,8 +24,8 @@
 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;
 
index cbf4ae03a767086dbd2f9088df62df240bbde4c8..d1c75b895798ab33c95db763a7664382977cabbc 100644 (file)
@@ -24,7 +24,6 @@
 
 #![deny(deprecated_owned_vector)]
 
-extern crate rand;
 extern crate debug;
 
 #[cfg(test)] extern crate test;
index fb663d91131af970c3204f824299c3e3713e7f48..3e862f280606cac480d7034cb4af72e6054b3ca2 100644 (file)
@@ -1000,8 +1000,8 @@ fn extend<Iter: Iterator<T>>(&mut self, mut iter: Iter) {
 mod test_treemap {
     use super::{TreeMap, TreeNode};
 
-    use rand::Rng;
-    use rand;
+    use std::rand::Rng;
+    use std::rand;
 
     #[test]
     fn find_empty() {
index 9d64b3c2394b02d7cf47c93deeb47cdfff52809f..e6df4fd87e12e976b9054823b8c09389ce3e975d 100644 (file)
@@ -915,7 +915,7 @@ fn test_mut_bound() {
 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]
index 94ac344db3485e64993b489de63e25fcfdb97e62..f463c194424da14250241b022764a6529dbbb7e1 100644 (file)
@@ -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;
index 0c5d3151af0f5b8418a7be97c6707d37b8b05131..2d1cab5d841561b7e62f6c631c5a89d12560a9ad 100644 (file)
@@ -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() {
index 13236a1f654d0333eedce9337567c4f07428d7f0..f41efdbc1db6f131390a5dd296170d74b19bcbc2 100644 (file)
@@ -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]) {
index 731911185ff7e4e0b382cb2c5e0772977507e99f..7ad78df2fe8cecf0b945f700dec9840affa72166 100644 (file)
@@ -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 @@ fn format_base_36(b: &mut Bencher) {
     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)); })
         }
     }
index 56cbe2e2a30d187ec32bea4f82fc34ed6f1febe0..2ff2dca0c867300fa1f0182b642495167fd005f2 100644 (file)
@@ -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;
index 926605dddb3e6713606f4f7b8c717cdde4adccd4..fd51ede204ff1f4f344696843bc4f0e3116fd453 100644 (file)
@@ -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) }
index 059b96ffac713fcbc6a3598d0f5c553cc23fc949..edcb37dbb64c2342c3ed8d11aa4ae567555b507a 100644 (file)
@@ -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() {
index 54f147dead8b68f02807ebaeb2c987e7b22b0acc..8bfd2d867c130ad749497202ef0d56b40b62d1c4 100644 (file)
@@ -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 @@ fn test_flate_round_trip() {
         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![];
index 4584c08cbd8984f093ff58639a72c0467f0e0be9..31fd8950c804c2d48fa5d1ece63ff3b3903bdb9a 100644 (file)
 
 #[cfg(test)] #[phase(syntax, link)] extern crate log;
 #[cfg(test)] extern crate rustuv;
-extern crate rand;
 extern crate libc;
 extern crate alloc;
 
index d28e74a2b80b7c14d823c5a4175b822c43f5a76d..401c438988316ef222083d6dd993138dde4bef9a 100644 (file)
@@ -17,7 +17,7 @@
 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 @@ fn to_fn(self) -> |&mut Scheduler, Box<GreenTask>| {
 // 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) }
index cc35cd749d6638a5dd5ba7783d019f7a63ec90bf..c6af8ac9b4b89075b6ac17ced547382089f523a0 100644 (file)
@@ -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]
index 03c87eb931d604428fead709072ffa1ba6d572b9..d4e689ccb5c5998a3fb685dadc264a554c94b47f 100644 (file)
@@ -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 @@ fn zero_case<R:Rng>(rng: &mut R, _u: f64) -> f64 {
 /// # 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 @@ fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
 
 #[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 @@ fn test_exp_invalid_lambda_neg() {
 #[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;
     }
 }
index 1bb2c35bce206bd05ba6be5913f540fca6e4c188..445fe9acbeca0f6ff0fb09349c7a3abe308f6e6d 100644 (file)
@@ -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 @@
 /// # 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 @@ fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
 /// # 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 @@ fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
 /// # 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 @@ fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
 /// # 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 @@ fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
 
 #[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 @@ fn test_chi_squared_one() {
     #[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 @@ fn test_chi_squared_small() {
     #[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 @@ fn test_chi_squared_invalid_dof() {
     #[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 @@ fn test_f() {
     #[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 @@ fn test_t() {
 #[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;
     }
 }
index b3535a695eaf310e331350dd44c38a2a3e711dce..bb09db48802690f53774f2ab9a1d6aa67b17c319 100644 (file)
 
 */
 
-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 @@ pub fn new(mut items: Vec<Weighted<T>>) -> 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 @@ pub fn new(mut items: Vec<Weighted<T>>) -> 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 @@ fn ind_sample<R: Rng>(&self, rng: &mut R) -> 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 @@ fn ind_sample<R: Rng>(&self, rng: &mut R) -> 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 @@ fn ind_sample<R: Rng>(&self, rng: &mut R) -> 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 @@ fn next_u64(&mut self) -> u64 {
     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 @@ fn test_weighted_choice() {
 
         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 @@ macro_rules! t (
 
     #[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 }]);
     }
 }
index dea73945b4384058a5e23c4a0bdb91f147942dda..47ab7d32e05751c080679c4a807d85fdb69e24dd 100644 (file)
@@ -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 @@ fn zero_case<R:Rng>(rng: &mut R, u: f64) -> f64 {
 /// # 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 @@ fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
 /// # 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 @@ fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
 
 #[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 @@ fn test_normal_invalid_sd() {
     #[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 @@ fn test_log_normal_invalid_sd() {
 #[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;
     }
 }
index cee80b62e3dec45b5358c158e8a82e1e11c4f035..f0e1d1715a2baeab3fc0bd915029b6dc7466a487 100644 (file)
@@ -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 @@
 /// # 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 @@ fn sample_range<R: Rng>(r: &Range<$ty>, rng: &mut R) -> $ty {
 
 #[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 @@ fn test_range_bad_limits_flipped() {
 
     #[test]
     fn test_integers() {
-        let mut rng = task_rng();
+        let mut rng = ::test::rng();
         macro_rules! t (
             ($($ty:ty),*) => {{
                 $(
@@ -204,7 +207,7 @@ macro_rules! t (
 
     #[test]
     fn test_floats() {
-        let mut rng = task_rng();
+        let mut rng = ::test::rng();
         macro_rules! t (
             ($($ty:ty),*) => {{
                 $(
index 1d9da40f18b6efc6418a2453e0b581cb9e663f69..50ecabfc638beab400a1d3e788328f5b9184c904 100644 (file)
 
 //! 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 @@ pub struct 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 @@ fn from_seed(seed: &'a [u32]) -> 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 @@ pub struct 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 @@ fn from_seed(seed: &'a [u64]) -> 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 @@ fn test_rng_32_seeded() {
         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);
     }
 
index 4a11b692076008c70c2e204fad02ba9cb1b270da..93a00c4e0a63a435d283537ce70411c22621163c 100644 (file)
@@ -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 @@ fn next_u64(&mut self) -> u64 {
     /// # 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 @@ fn fill_bytes(&mut self, dest: &mut [u8]) {
     /// # 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 @@ fn gen<T: Rand>(&mut self) -> T {
         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 @@ fn gen_vec<T: Rand>(&mut self, len: uint) -> Vec<T> {
     /// # 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 @@ fn gen_range<T: Ord + SampleRange>(&mut self, low: T, high: T) -> T {
     /// # 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 @@ fn gen_weighted_bool(&mut self, n: uint) -> bool {
         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 @@ fn gen_ascii_str(&mut self, len: uint) -> String {
     /// # 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 @@ fn choose_option<'a, T>(&mut self, values: &'a [T]) -> Option<&'a T> {
     /// # 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 @@ fn shuffle<T>(&mut self, values: &mut [T]) {
             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,122 +402,16 @@ fn from_seed(seed: [u32, .. 4]) -> 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;
-            }
-        }
-        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<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)
+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 (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<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 fn random<T: Rand>() -> T {
 /// `[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(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::<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(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::<uint>();
-            }
-        });
-        b.bytes = size_of::<uint>() 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::<uint>();
-            }
-        });
-        b.bytes = size_of::<uint>() as u64 * RAND_BENCH_N;
-    }
+    pub struct MyRng<R> { 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::<uint>();
+    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()
             }
-        });
-        b.bytes = size_of::<uint>() 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::<uint>();
-            }
-        });
-        b.bytes = size_of::<uint>() as u64 * RAND_BENCH_N;
+    pub fn rng() -> MyRng<rand::TaskRng> {
+        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<rand::XorShiftRng> {
+        MyRng { inner: rand::weak_rng() }
     }
 }
diff --git a/src/librand/os.rs b/src/librand/os.rs
deleted file mode 100644 (file)
index 0e1d01a..0000000
+++ /dev/null
@@ -1,240 +0,0 @@
-// 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.
-
-//! Interfaces to the operating system provided random number
-//! generators.
-
-pub use self::imp::OSRng;
-
-#[cfg(unix)]
-mod imp {
-    use Rng;
-    use reader::ReaderRng;
-    use std::io::{IoResult, File};
-
-    /// A random number generator that retrieves randomness straight from
-    /// the operating system. Platform sources:
-    ///
-    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
-    ///   `/dev/urandom`.
-    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
-    ///   service provider with the `PROV_RSA_FULL` type.
-    ///
-    /// This does not block.
-    #[cfg(unix)]
-    pub struct OSRng {
-        inner: ReaderRng<File>
-    }
-
-    impl OSRng {
-        /// Create a new `OSRng`.
-        pub fn new() -> IoResult<OSRng> {
-            let reader = try!(File::open(&Path::new("/dev/urandom")));
-            let reader_rng = ReaderRng::new(reader);
-
-            Ok(OSRng { inner: reader_rng })
-        }
-    }
-
-    impl Rng for OSRng {
-        fn next_u32(&mut self) -> u32 {
-            self.inner.next_u32()
-        }
-        fn next_u64(&mut self) -> u64 {
-            self.inner.next_u64()
-        }
-        fn fill_bytes(&mut self, v: &mut [u8]) {
-            self.inner.fill_bytes(v)
-        }
-    }
-}
-
-#[cfg(windows)]
-mod imp {
-    extern crate libc;
-
-    use Rng;
-    use std::io::{IoResult, IoError};
-    use std::mem;
-    use std::os;
-    use std::rt::stack;
-    use self::libc::{c_ulong, DWORD, BYTE, LPCSTR, BOOL};
-
-    type HCRYPTPROV = c_ulong;
-
-    /// A random number generator that retrieves randomness straight from
-    /// the operating system. Platform sources:
-    ///
-    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
-    ///   `/dev/urandom`.
-    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
-    ///   service provider with the `PROV_RSA_FULL` type.
-    ///
-    /// This does not block.
-    pub struct OSRng {
-        hcryptprov: HCRYPTPROV
-    }
-
-    static PROV_RSA_FULL: DWORD = 1;
-    static CRYPT_SILENT: DWORD = 64;
-    static CRYPT_VERIFYCONTEXT: DWORD = 0xF0000000;
-    static NTE_BAD_SIGNATURE: DWORD = 0x80090006;
-
-    extern "system" {
-        fn CryptAcquireContextA(phProv: *mut HCRYPTPROV,
-                                pszContainer: LPCSTR,
-                                pszProvider: LPCSTR,
-                                dwProvType: DWORD,
-                                dwFlags: DWORD) -> BOOL;
-        fn CryptGenRandom(hProv: HCRYPTPROV,
-                          dwLen: DWORD,
-                          pbBuffer: *mut BYTE) -> BOOL;
-        fn CryptReleaseContext(hProv: HCRYPTPROV, dwFlags: DWORD) -> BOOL;
-    }
-
-    impl OSRng {
-        /// Create a new `OSRng`.
-        pub fn new() -> IoResult<OSRng> {
-            let mut hcp = 0;
-            let mut ret = unsafe {
-                CryptAcquireContextA(&mut hcp, 0 as LPCSTR, 0 as LPCSTR,
-                                     PROV_RSA_FULL,
-                                     CRYPT_VERIFYCONTEXT | CRYPT_SILENT)
-            };
-
-            // FIXME #13259:
-            // It turns out that if we can't acquire a context with the
-            // NTE_BAD_SIGNATURE error code, the documentation states:
-            //
-            //     The provider DLL signature could not be verified. Either the
-            //     DLL or the digital signature has been tampered with.
-            //
-            // Sounds fishy, no? As it turns out, our signature can be bad
-            // because our Thread Information Block (TIB) isn't exactly what it
-            // expects. As to why, I have no idea. The only data we store in the
-            // TIB is the stack limit for each thread, but apparently that's
-            // enough to make the signature valid.
-            //
-            // Furthermore, this error only happens the *first* time we call
-            // CryptAcquireContext, so we don't have to worry about future
-            // calls.
-            //
-            // Anyway, the fix employed here is that if we see this error, we
-            // pray that we're not close to the end of the stack, temporarily
-            // set the stack limit to 0 (what the TIB originally was), acquire a
-            // context, and then reset the stack limit.
-            //
-            // Again, I'm not sure why this is the fix, nor why we're getting
-            // this error. All I can say is that this seems to allow libnative
-            // to progress where it otherwise would be hindered. Who knew?
-            if ret == 0 && os::errno() as DWORD == NTE_BAD_SIGNATURE {
-                unsafe {
-                    let limit = stack::get_sp_limit();
-                    stack::record_sp_limit(0);
-                    ret = CryptAcquireContextA(&mut hcp, 0 as LPCSTR, 0 as LPCSTR,
-                                               PROV_RSA_FULL,
-                                               CRYPT_VERIFYCONTEXT | CRYPT_SILENT);
-                    stack::record_sp_limit(limit);
-                }
-            }
-
-            if ret == 0 {
-                Err(IoError::last_error())
-            } else {
-                Ok(OSRng { hcryptprov: hcp })
-            }
-        }
-    }
-
-    impl Rng for OSRng {
-        fn next_u32(&mut self) -> u32 {
-            let mut v = [0u8, .. 4];
-            self.fill_bytes(v);
-            unsafe { mem::transmute(v) }
-        }
-        fn next_u64(&mut self) -> u64 {
-            let mut v = [0u8, .. 8];
-            self.fill_bytes(v);
-            unsafe { mem::transmute(v) }
-        }
-        fn fill_bytes(&mut self, v: &mut [u8]) {
-            let ret = unsafe {
-                CryptGenRandom(self.hcryptprov, v.len() as DWORD,
-                               v.as_mut_ptr())
-            };
-            if ret == 0 {
-                fail!("couldn't generate random bytes: {}", os::last_os_error());
-            }
-        }
-    }
-
-    impl Drop for OSRng {
-        fn drop(&mut self) {
-            let ret = unsafe {
-                CryptReleaseContext(self.hcryptprov, 0)
-            };
-            if ret == 0 {
-                fail!("couldn't release context: {}", os::last_os_error());
-            }
-        }
-    }
-}
-
-#[cfg(test)]
-mod test {
-    use super::OSRng;
-    use Rng;
-    use std::task;
-
-    #[test]
-    fn test_os_rng() {
-        let mut r = OSRng::new().unwrap();
-
-        r.next_u32();
-        r.next_u64();
-
-        let mut v = [0u8, .. 1000];
-        r.fill_bytes(v);
-    }
-
-    #[test]
-    fn test_os_rng_tasks() {
-
-        let mut txs = vec!();
-        for _ in range(0, 20) {
-            let (tx, rx) = channel();
-            txs.push(tx);
-            task::spawn(proc() {
-                // wait until all the tasks are ready to go.
-                rx.recv();
-
-                // deschedule to attempt to interleave things as much
-                // as possible (XXX: is this a good test?)
-                let mut r = OSRng::new().unwrap();
-                task::deschedule();
-                let mut v = [0u8, .. 1000];
-
-                for _ in range(0, 100) {
-                    r.next_u32();
-                    task::deschedule();
-                    r.next_u64();
-                    task::deschedule();
-                    r.fill_bytes(v);
-                    task::deschedule();
-                }
-            })
-        }
-
-        // start all the tasks
-        for tx in txs.iter() {
-            tx.send(())
-        }
-    }
-}
index 5846cb5f312cad42c0ebc0c1ea0148d6e47209b5..458a9ba378d98d31a1c805de64c2849c1c0b1c17 100644 (file)
 
 //! 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 @@ fn rand<R: Rng>(rng: &mut R) -> 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 {
diff --git a/src/librand/reader.rs b/src/librand/reader.rs
deleted file mode 100644 (file)
index e800f64..0000000
+++ /dev/null
@@ -1,118 +0,0 @@
-// 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.
-
-//! A wrapper around any Reader to treat it as an RNG.
-
-use Rng;
-
-/// An RNG that reads random bytes straight from a `Reader`. This will
-/// work best with an infinite reader, but this is not required.
-///
-/// It will fail if it there is insufficient data to fulfill a request.
-///
-/// # Example
-///
-/// ```rust
-/// use rand::{reader, Rng};
-/// use std::io::MemReader;
-///
-/// let mut rng = reader::ReaderRng::new(MemReader::new(vec!(1,2,3,4,5,6,7,8)));
-/// println!("{:x}", rng.gen::<uint>());
-/// ```
-pub struct ReaderRng<R> {
-    reader: R
-}
-
-impl<R: Reader> ReaderRng<R> {
-    /// Create a new `ReaderRng` from a `Reader`.
-    pub fn new(r: R) -> ReaderRng<R> {
-        ReaderRng {
-            reader: r
-        }
-    }
-}
-
-impl<R: Reader> Rng for ReaderRng<R> {
-    fn next_u32(&mut self) -> u32 {
-        // This is designed for speed: reading a LE integer on a LE
-        // platform just involves blitting the bytes into the memory
-        // of the u32, similarly for BE on BE; avoiding byteswapping.
-        if cfg!(target_endian="little") {
-            self.reader.read_le_u32().unwrap()
-        } else {
-            self.reader.read_be_u32().unwrap()
-        }
-    }
-    fn next_u64(&mut self) -> u64 {
-        // see above for explanation.
-        if cfg!(target_endian="little") {
-            self.reader.read_le_u64().unwrap()
-        } else {
-            self.reader.read_be_u64().unwrap()
-        }
-    }
-    fn fill_bytes(&mut self, v: &mut [u8]) {
-        if v.len() == 0 { return }
-        match self.reader.read_at_least(v.len(), v) {
-            Ok(_) => {}
-            Err(e) => fail!("ReaderRng.fill_bytes error: {}", e)
-        }
-    }
-}
-
-#[cfg(test)]
-#[allow(deprecated_owned_vector)]
-mod test {
-    use super::ReaderRng;
-    use std::io::MemReader;
-    use std::mem;
-    use Rng;
-
-    #[test]
-    fn test_reader_rng_u64() {
-        // transmute from the target to avoid endianness concerns.
-        let v = box [1u64, 2u64, 3u64];
-        let bytes: ~[u8] = unsafe {mem::transmute(v)};
-        let mut rng = ReaderRng::new(MemReader::new(bytes.move_iter().collect()));
-
-        assert_eq!(rng.next_u64(), 1);
-        assert_eq!(rng.next_u64(), 2);
-        assert_eq!(rng.next_u64(), 3);
-    }
-    #[test]
-    fn test_reader_rng_u32() {
-        // transmute from the target to avoid endianness concerns.
-        let v = box [1u32, 2u32, 3u32];
-        let bytes: ~[u8] = unsafe {mem::transmute(v)};
-        let mut rng = ReaderRng::new(MemReader::new(bytes.move_iter().collect()));
-
-        assert_eq!(rng.next_u32(), 1);
-        assert_eq!(rng.next_u32(), 2);
-        assert_eq!(rng.next_u32(), 3);
-    }
-    #[test]
-    fn test_reader_rng_fill_bytes() {
-        let v = [1u8, 2, 3, 4, 5, 6, 7, 8];
-        let mut w = [0u8, .. 8];
-
-        let mut rng = ReaderRng::new(MemReader::new(Vec::from_slice(v)));
-        rng.fill_bytes(w);
-
-        assert!(v == w);
-    }
-
-    #[test]
-    #[should_fail]
-    fn test_reader_rng_insufficient_bytes() {
-        let mut rng = ReaderRng::new(MemReader::new(vec!()));
-        let mut v = [0u8, .. 3];
-        rng.fill_bytes(v);
-    }
-}
index fe2ff319c1cadb2ad4ffb0e440fa9d475648278a..09265f28c36fa84f8fb37e59e693b774f4273cfb 100644 (file)
 //! 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 @@ fn fill_bytes(&mut self, dest: &mut [u8]) {
     }
 }
 
-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 @@ fn from_seed((rsdr, seed): (Rsdr, S)) -> ReseedingRng<R, Rsdr> {
 /// # 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 @@ fn from_seed((rsdr, seed): (Rsdr, S)) -> ReseedingRng<R, Rsdr> {
 ///     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 @@ fn default() -> ReseedWithDefault { 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 @@ fn test_reseeding() {
     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.
index 8dc6484a13629c02d1535bf4990c3324a2e068cd..7c806ece5c85baaea19b060a44eaea5eac875afb 100644 (file)
@@ -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
index 5d2f229beb675e3a7a99a983f17d892207c25bf4..5a8759540c8b5655fbc86dda7034868905b36149 100644 (file)
@@ -261,7 +261,6 @@ fn from_base64(&self) -> Result<Vec<u8>, FromBase64Error> {
 #[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 @@ fn test_from_base64_invalid_padding() {
 
     #[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);
index c1bc68b3e1293cbd3776c2692cd042c93fa7225b..b63ccbef55faadbdf2f12fc8f9424576ed37173f 100644 (file)
 #[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 @@ fn start(argc: int, argv: **u8) -> int {
 pub mod vec;
 pub mod str;
 pub mod string;
+pub mod rand;
 
 pub mod ascii;
 
index 1efe83217f48d3b4042f98aa364f47e5be733057..20f5927c9bd503a3abd759a97b43e3e7d0539d35 100644 (file)
@@ -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()); })
         }
     }
index f960228c63c684978a291e3c121a81b3598283b1..f6b9a7b24bc9338f7328bad8a0b5891fcdc0427e 100644 (file)
@@ -1513,7 +1513,8 @@ pub fn last_os_error() {
 
     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
     }
diff --git a/src/libstd/rand/mod.rs b/src/libstd/rand/mod.rs
new file mode 100644 (file)
index 0000000..c7ae633
--- /dev/null
@@ -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);
+        })
+    }
+}
diff --git a/src/libstd/rand/os.rs b/src/libstd/rand/os.rs
new file mode 100644 (file)
index 0000000..ea4d7ad
--- /dev/null
@@ -0,0 +1,248 @@
+// 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.
+
+//! Interfaces to the operating system provided random number
+//! generators.
+
+pub use self::imp::OSRng;
+
+#[cfg(unix)]
+mod imp {
+    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:
+    ///
+    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
+    ///   `/dev/urandom`.
+    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
+    ///   service provider with the `PROV_RSA_FULL` type.
+    ///
+    /// This does not block.
+    #[cfg(unix)]
+    pub struct OSRng {
+        inner: ReaderRng<File>
+    }
+
+    impl OSRng {
+        /// Create a new `OSRng`.
+        pub fn new() -> IoResult<OSRng> {
+            let reader = try!(File::open(&Path::new("/dev/urandom")));
+            let reader_rng = ReaderRng::new(reader);
+
+            Ok(OSRng { inner: reader_rng })
+        }
+    }
+
+    impl Rng for OSRng {
+        fn next_u32(&mut self) -> u32 {
+            self.inner.next_u32()
+        }
+        fn next_u64(&mut self) -> u64 {
+            self.inner.next_u64()
+        }
+        fn fill_bytes(&mut self, v: &mut [u8]) {
+            self.inner.fill_bytes(v)
+        }
+    }
+}
+
+#[cfg(windows)]
+mod imp {
+    extern crate libc;
+
+    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;
+
+    /// A random number generator that retrieves randomness straight from
+    /// the operating system. Platform sources:
+    ///
+    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
+    ///   `/dev/urandom`.
+    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
+    ///   service provider with the `PROV_RSA_FULL` type.
+    ///
+    /// This does not block.
+    pub struct OSRng {
+        hcryptprov: HCRYPTPROV
+    }
+
+    static PROV_RSA_FULL: DWORD = 1;
+    static CRYPT_SILENT: DWORD = 64;
+    static CRYPT_VERIFYCONTEXT: DWORD = 0xF0000000;
+    static NTE_BAD_SIGNATURE: DWORD = 0x80090006;
+
+    extern "system" {
+        fn CryptAcquireContextA(phProv: *mut HCRYPTPROV,
+                                pszContainer: LPCSTR,
+                                pszProvider: LPCSTR,
+                                dwProvType: DWORD,
+                                dwFlags: DWORD) -> BOOL;
+        fn CryptGenRandom(hProv: HCRYPTPROV,
+                          dwLen: DWORD,
+                          pbBuffer: *mut BYTE) -> BOOL;
+        fn CryptReleaseContext(hProv: HCRYPTPROV, dwFlags: DWORD) -> BOOL;
+    }
+
+    impl OSRng {
+        /// Create a new `OSRng`.
+        pub fn new() -> IoResult<OSRng> {
+            let mut hcp = 0;
+            let mut ret = unsafe {
+                CryptAcquireContextA(&mut hcp, 0 as LPCSTR, 0 as LPCSTR,
+                                     PROV_RSA_FULL,
+                                     CRYPT_VERIFYCONTEXT | CRYPT_SILENT)
+            };
+
+            // FIXME #13259:
+            // It turns out that if we can't acquire a context with the
+            // NTE_BAD_SIGNATURE error code, the documentation states:
+            //
+            //     The provider DLL signature could not be verified. Either the
+            //     DLL or the digital signature has been tampered with.
+            //
+            // Sounds fishy, no? As it turns out, our signature can be bad
+            // because our Thread Information Block (TIB) isn't exactly what it
+            // expects. As to why, I have no idea. The only data we store in the
+            // TIB is the stack limit for each thread, but apparently that's
+            // enough to make the signature valid.
+            //
+            // Furthermore, this error only happens the *first* time we call
+            // CryptAcquireContext, so we don't have to worry about future
+            // calls.
+            //
+            // Anyway, the fix employed here is that if we see this error, we
+            // pray that we're not close to the end of the stack, temporarily
+            // set the stack limit to 0 (what the TIB originally was), acquire a
+            // context, and then reset the stack limit.
+            //
+            // Again, I'm not sure why this is the fix, nor why we're getting
+            // this error. All I can say is that this seems to allow libnative
+            // to progress where it otherwise would be hindered. Who knew?
+            if ret == 0 && os::errno() as DWORD == NTE_BAD_SIGNATURE {
+                unsafe {
+                    let limit = stack::get_sp_limit();
+                    stack::record_sp_limit(0);
+                    ret = CryptAcquireContextA(&mut hcp, 0 as LPCSTR, 0 as LPCSTR,
+                                               PROV_RSA_FULL,
+                                               CRYPT_VERIFYCONTEXT | CRYPT_SILENT);
+                    stack::record_sp_limit(limit);
+                }
+            }
+
+            if ret == 0 {
+                Err(IoError::last_error())
+            } else {
+                Ok(OSRng { hcryptprov: hcp })
+            }
+        }
+    }
+
+    impl Rng for OSRng {
+        fn next_u32(&mut self) -> u32 {
+            let mut v = [0u8, .. 4];
+            self.fill_bytes(v);
+            unsafe { mem::transmute(v) }
+        }
+        fn next_u64(&mut self) -> u64 {
+            let mut v = [0u8, .. 8];
+            self.fill_bytes(v);
+            unsafe { mem::transmute(v) }
+        }
+        fn fill_bytes(&mut self, v: &mut [u8]) {
+            let ret = unsafe {
+                CryptGenRandom(self.hcryptprov, v.len() as DWORD,
+                               v.as_mut_ptr())
+            };
+            if ret == 0 {
+                fail!("couldn't generate random bytes: {}", os::last_os_error());
+            }
+        }
+    }
+
+    impl Drop for OSRng {
+        fn drop(&mut self) {
+            let ret = unsafe {
+                CryptReleaseContext(self.hcryptprov, 0)
+            };
+            if ret == 0 {
+                fail!("couldn't release context: {}", os::last_os_error());
+            }
+        }
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use prelude::*;
+
+    use super::OSRng;
+    use rand::Rng;
+    use task;
+
+    #[test]
+    fn test_os_rng() {
+        let mut r = OSRng::new().unwrap();
+
+        r.next_u32();
+        r.next_u64();
+
+        let mut v = [0u8, .. 1000];
+        r.fill_bytes(v);
+    }
+
+    #[test]
+    fn test_os_rng_tasks() {
+
+        let mut txs = vec!();
+        for _ in range(0, 20) {
+            let (tx, rx) = channel();
+            txs.push(tx);
+            task::spawn(proc() {
+                // wait until all the tasks are ready to go.
+                rx.recv();
+
+                // deschedule to attempt to interleave things as much
+                // as possible (XXX: is this a good test?)
+                let mut r = OSRng::new().unwrap();
+                task::deschedule();
+                let mut v = [0u8, .. 1000];
+
+                for _ in range(0, 100) {
+                    r.next_u32();
+                    task::deschedule();
+                    r.next_u64();
+                    task::deschedule();
+                    r.fill_bytes(v);
+                    task::deschedule();
+                }
+            })
+        }
+
+        // start all the tasks
+        for tx in txs.iter() {
+            tx.send(())
+        }
+    }
+}
diff --git a/src/libstd/rand/reader.rs b/src/libstd/rand/reader.rs
new file mode 100644 (file)
index 0000000..1708840
--- /dev/null
@@ -0,0 +1,123 @@
+// 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.
+
+//! A wrapper around any Reader to treat it as an 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.
+///
+/// It will fail if it there is insufficient data to fulfill a request.
+///
+/// # Example
+///
+/// ```rust
+/// 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)));
+/// println!("{:x}", rng.gen::<uint>());
+/// ```
+pub struct ReaderRng<R> {
+    reader: R
+}
+
+impl<R: Reader> ReaderRng<R> {
+    /// Create a new `ReaderRng` from a `Reader`.
+    pub fn new(r: R) -> ReaderRng<R> {
+        ReaderRng {
+            reader: r
+        }
+    }
+}
+
+impl<R: Reader> Rng for ReaderRng<R> {
+    fn next_u32(&mut self) -> u32 {
+        // This is designed for speed: reading a LE integer on a LE
+        // platform just involves blitting the bytes into the memory
+        // of the u32, similarly for BE on BE; avoiding byteswapping.
+        if cfg!(target_endian="little") {
+            self.reader.read_le_u32().unwrap()
+        } else {
+            self.reader.read_be_u32().unwrap()
+        }
+    }
+    fn next_u64(&mut self) -> u64 {
+        // see above for explanation.
+        if cfg!(target_endian="little") {
+            self.reader.read_le_u64().unwrap()
+        } else {
+            self.reader.read_be_u64().unwrap()
+        }
+    }
+    fn fill_bytes(&mut self, v: &mut [u8]) {
+        if v.len() == 0 { return }
+        match self.reader.read_at_least(v.len(), v) {
+            Ok(_) => {}
+            Err(e) => fail!("ReaderRng.fill_bytes error: {}", e)
+        }
+    }
+}
+
+#[cfg(test)]
+#[allow(deprecated_owned_vector)]
+mod test {
+    use prelude::*;
+
+    use super::ReaderRng;
+    use io::MemReader;
+    use mem;
+    use rand::Rng;
+
+    #[test]
+    fn test_reader_rng_u64() {
+        // transmute from the target to avoid endianness concerns.
+        let v = box [1u64, 2u64, 3u64];
+        let bytes: ~[u8] = unsafe {mem::transmute(v)};
+        let mut rng = ReaderRng::new(MemReader::new(bytes.move_iter().collect()));
+
+        assert_eq!(rng.next_u64(), 1);
+        assert_eq!(rng.next_u64(), 2);
+        assert_eq!(rng.next_u64(), 3);
+    }
+    #[test]
+    fn test_reader_rng_u32() {
+        // transmute from the target to avoid endianness concerns.
+        let v = box [1u32, 2u32, 3u32];
+        let bytes: ~[u8] = unsafe {mem::transmute(v)};
+        let mut rng = ReaderRng::new(MemReader::new(bytes.move_iter().collect()));
+
+        assert_eq!(rng.next_u32(), 1);
+        assert_eq!(rng.next_u32(), 2);
+        assert_eq!(rng.next_u32(), 3);
+    }
+    #[test]
+    fn test_reader_rng_fill_bytes() {
+        let v = [1u8, 2, 3, 4, 5, 6, 7, 8];
+        let mut w = [0u8, .. 8];
+
+        let mut rng = ReaderRng::new(MemReader::new(Vec::from_slice(v)));
+        rng.fill_bytes(w);
+
+        assert!(v == w);
+    }
+
+    #[test]
+    #[should_fail]
+    fn test_reader_rng_insufficient_bytes() {
+        let mut rng = ReaderRng::new(MemReader::new(vec!()));
+        let mut v = [0u8, .. 3];
+        rng.fill_bytes(v);
+    }
+}
index e5c0cc3babd0377dadc41e5c32b3118b1e07ffcb..55bea068641e128266028140f62b08198f477bb5 100644 (file)
@@ -1303,7 +1303,8 @@ fn test_sort() {
         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 @@ fn random_removes(b: &mut Bencher) {
     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 @@ fn sort_random_small(b: &mut Bencher) {
     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 @@ fn sort_random_medium(b: &mut Bencher) {
     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 @@ fn sort_sorted(b: &mut Bencher) {
     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 @@ fn sort_big_random_small(b: &mut Bencher) {
     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 @@ fn sort_big_random_medium(b: &mut Bencher) {
     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;
index 397b99925c8ec6a33e57e350f7d1dd3c65bddc3f..5314b39f8056dce9b897cbe0978db2c618c41974 100644 (file)
@@ -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")
index 99dd7d8503c82079753442b0c55cb7760722dc9f..8263fcda314f8b3ddb4703272ff9cbdc0b058a36 100644 (file)
@@ -67,21 +67,19 @@ fn main() {
 // 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 @@ pub fn new(v: UuidVersion) -> Option<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 @@ fn decode(d: &mut T) -> Result<Uuid, E> {
 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 @@ fn rand<R: rand::Rng>(rng: &mut R) -> 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 @@ fn test_operator_eq() {
     #[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);
index d53a89684213d19446ad7197101f4f4021d3d0a5..bf50736b7e6d1bfef9887fd828699e4993f907bc 100644 (file)
 
 #![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;
index 27540cc5bbf945baecb2d3409d9d49baa7700337..816a752921222b5594add561527501a0e68fba84 100644 (file)
 // 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,
index 8b9d4de9f04c1d3194a439c1bbcd43e61150aef1..366e1fd4dcae4b7e9ca41f132e2506de7aeac13e 100644 (file)
 
 // 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`
 }
index e41c5d1b6266e5c86c4e0f9f661599f43c05a7a7..3711503ee2b590889380d019d74225d55cb583f5 100644 (file)
@@ -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
index b875f676982dc0928e7e899855f0332847814127..ebb03435fe4d9226b5eb6ce324b42cbdf49c0288 100644 (file)
@@ -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
index c455aebbe46ed348c5d85fd62c92eac2462983d0..4e9592950d3da20027ff64c0f591a1c5ca8d9015 100644 (file)
@@ -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;
index 00bc95b36f7a70b2b1f14771d12792eac16bd622..e5f1c48464de34030e60b65ff1c3489e21013981 100644 (file)
@@ -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...