1 // Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
13 Utilities for random number generation
15 The key functions are `random()` and `Rng::gen()`. These are polymorphic
16 and so can be used to generate any type that implements `Rand`. Type inference
17 means that often a simple call to `rand::random()` or `rng.gen()` will
18 suffice, but sometimes an annotation is required, e.g. `rand::random::<f64>()`.
20 See the `distributions` submodule for sampling random numbers from
21 distributions like normal and exponential.
25 There is built-in support for a RNG associated with each task stored
26 in task-local storage. This RNG can be accessed via `task_rng`, or
27 used implicitly via `random`. This RNG is normally randomly seeded
28 from an operating-system source of randomness, e.g. `/dev/urandom` on
29 Unix systems, and will automatically reseed itself from this source
30 after generating 32 KiB of random data.
32 # Cryptographic security
34 An application that requires an entropy source for cryptographic purposes
35 must use `OsRng`, which reads randomness from the source that the operating
36 system provides (e.g. `/dev/urandom` on Unixes or `CryptGenRandom()` on Windows).
37 The other random number generators provided by this module are not suitable
40 *Note*: many Unix systems provide `/dev/random` as well as `/dev/urandom`.
41 This module uses `/dev/urandom` for the following reasons:
43 - On Linux, `/dev/random` may block if entropy pool is empty; `/dev/urandom` will not block.
44 This does not mean that `/dev/random` provides better output than
45 `/dev/urandom`; the kernel internally runs a cryptographically secure pseudorandom
46 number generator (CSPRNG) based on entropy pool for random number generation,
47 so the "quality" of `/dev/random` is not better than `/dev/urandom` in most cases.
48 However, this means that `/dev/urandom` can yield somewhat predictable randomness
49 if the entropy pool is very small, such as immediately after first booting.
50 If an application likely to be run soon after first booting, or on a system with very
51 few entropy sources, one should consider using `/dev/random` via `ReaderRng`.
52 - On some systems (e.g. FreeBSD, OpenBSD and Mac OS X) there is no difference
53 between the two sources. (Also note that, on some systems e.g. FreeBSD, both `/dev/random`
54 and `/dev/urandom` may block once if the CSPRNG has not seeded yet.)
62 let mut rng = rand::task_rng();
63 if rng.gen() { // random bool
64 println!("int: {}, uint: {}", rng.gen::<int>(), rng.gen::<uint>())
71 let tuple = rand::random::<(f64, char)>();
83 use option::{Some, None};
85 use result::{Ok, Err};
88 #[cfg(not(target_word_size="64"))]
89 use IsaacWordRng = core_rand::IsaacRng;
90 #[cfg(target_word_size="64")]
91 use IsaacWordRng = core_rand::Isaac64Rng;
93 pub use core_rand::{Rand, Rng, SeedableRng, Open01, Closed01};
94 pub use core_rand::{XorShiftRng, IsaacRng, Isaac64Rng};
95 pub use core_rand::{distributions, reseeding};
96 pub use rand::os::OsRng;
101 /// The standard RNG. This is designed to be efficient on the current
103 pub struct StdRng { rng: IsaacWordRng }
106 /// Create a randomly seeded instance of `StdRng`.
108 /// This is a very expensive operation as it has to read
109 /// randomness from the operating system and use this in an
110 /// expensive seeding operation. If one is only generating a small
111 /// number of random numbers, or doesn't need the utmost speed for
112 /// generating each number, `task_rng` and/or `random` may be more
115 /// Reading the randomness from the OS may fail, and any error is
116 /// propagated via the `IoResult` return value.
117 pub fn new() -> IoResult<StdRng> {
118 OsRng::new().map(|mut r| StdRng { rng: r.gen() })
122 impl Rng for StdRng {
124 fn next_u32(&mut self) -> u32 {
129 fn next_u64(&mut self) -> u64 {
134 impl<'a> SeedableRng<&'a [uint]> for StdRng {
135 fn reseed(&mut self, seed: &'a [uint]) {
136 // the internal RNG can just be seeded from the above
138 self.rng.reseed(unsafe {mem::transmute(seed)})
141 fn from_seed(seed: &'a [uint]) -> StdRng {
142 StdRng { rng: SeedableRng::from_seed(unsafe {mem::transmute(seed)}) }
146 /// Create a weak random number generator with a default algorithm and seed.
148 /// It returns the fastest `Rng` algorithm currently available in Rust without
149 /// consideration for cryptography or security. If you require a specifically
150 /// seeded `Rng` for consistency over time you should pick one algorithm and
151 /// create the `Rng` yourself.
153 /// This will read randomness from the operating system to seed the
155 pub fn weak_rng() -> XorShiftRng {
157 Ok(mut r) => r.gen(),
158 Err(e) => fail!("weak_rng: failed to create seeded RNG: {}", e)
162 /// Controls how the task-local RNG is reseeded.
163 struct TaskRngReseeder;
165 impl reseeding::Reseeder<StdRng> for TaskRngReseeder {
166 fn reseed(&mut self, rng: &mut StdRng) {
167 *rng = match StdRng::new() {
169 Err(e) => fail!("could not reseed task_rng: {}", e)
173 static TASK_RNG_RESEED_THRESHOLD: uint = 32_768;
174 type TaskRngInner = reseeding::ReseedingRng<StdRng, TaskRngReseeder>;
176 /// The task-local RNG.
178 rng: Rc<RefCell<TaskRngInner>>,
181 /// Retrieve the lazily-initialized task-local random number
182 /// generator, seeded by the system. Intended to be used in method
183 /// chaining style, e.g. `task_rng().gen::<int>()`.
185 /// The RNG provided will reseed itself from the operating system
186 /// after generating a certain amount of randomness.
188 /// The internal RNG used is platform and architecture dependent, even
189 /// if the operating system random number generator is rigged to give
190 /// the same sequence always. If absolute consistency is required,
191 /// explicitly select an RNG, e.g. `IsaacRng` or `Isaac64Rng`.
192 pub fn task_rng() -> TaskRng {
193 // used to make space in TLS for a random number generator
194 local_data_key!(TASK_RNG_KEY: Rc<RefCell<TaskRngInner>>)
196 match TASK_RNG_KEY.get() {
198 let r = match StdRng::new() {
200 Err(e) => fail!("could not initialize task_rng: {}", e)
202 let rng = reseeding::ReseedingRng::new(r,
203 TASK_RNG_RESEED_THRESHOLD,
205 let rng = Rc::new(RefCell::new(rng));
206 TASK_RNG_KEY.replace(Some(rng.clone()));
210 Some(rng) => TaskRng { rng: rng.clone() }
214 impl Rng for TaskRng {
215 fn next_u32(&mut self) -> u32 {
216 self.rng.borrow_mut().next_u32()
219 fn next_u64(&mut self) -> u64 {
220 self.rng.borrow_mut().next_u64()
224 fn fill_bytes(&mut self, bytes: &mut [u8]) {
225 self.rng.borrow_mut().fill_bytes(bytes)
229 /// Generate a random value using the task-local random number
235 /// use std::rand::random;
238 /// let x = random();
239 /// println!("{}", 2u * x);
241 /// println!("{}", random::<f64>());
245 pub fn random<T: Rand>() -> T {
249 /// Randomly sample up to `amount` elements from an iterator.
254 /// use std::rand::{task_rng, sample};
256 /// let mut rng = task_rng();
257 /// let sample = sample(&mut rng, range(1i, 100), 5);
258 /// println!("{}", sample);
260 pub fn sample<T, I: Iterator<T>, R: Rng>(rng: &mut R,
262 amount: uint) -> Vec<T> {
263 let mut reservoir: Vec<T> = iter.by_ref().take(amount).collect();
264 for (i, elem) in iter.enumerate() {
265 let k = rng.gen_range(0, i + 1 + amount);
267 *reservoir.get_mut(k) = elem;
276 use super::{Rng, task_rng, random, SeedableRng, StdRng, sample};
279 struct ConstRng { i: u64 }
280 impl Rng for ConstRng {
281 fn next_u32(&mut self) -> u32 { self.i as u32 }
282 fn next_u64(&mut self) -> u64 { self.i }
284 // no fill_bytes on purpose
288 fn test_fill_bytes_default() {
289 let mut r = ConstRng { i: 0x11_22_33_44_55_66_77_88 };
291 // check every remainder mod 8, both in small and big vectors.
292 let lengths = [0, 1, 2, 3, 4, 5, 6, 7,
293 80, 81, 82, 83, 84, 85, 86, 87];
294 for &n in lengths.iter() {
295 let mut v = Vec::from_elem(n, 0u8);
296 r.fill_bytes(v.as_mut_slice());
298 // use this to get nicer error messages.
299 for (i, &byte) in v.iter().enumerate() {
301 fail!("byte {} of {} is zero", i, n)
308 fn test_gen_range() {
309 let mut r = task_rng();
310 for _ in range(0u, 1000) {
311 let a = r.gen_range(-3i, 42);
312 assert!(a >= -3 && a < 42);
313 assert_eq!(r.gen_range(0i, 1), 0);
314 assert_eq!(r.gen_range(-12i, -11), -12);
317 for _ in range(0u, 1000) {
318 let a = r.gen_range(10i, 42);
319 assert!(a >= 10 && a < 42);
320 assert_eq!(r.gen_range(0i, 1), 0);
321 assert_eq!(r.gen_range(3_000_000u, 3_000_001), 3_000_000);
328 fn test_gen_range_fail_int() {
329 let mut r = task_rng();
335 fn test_gen_range_fail_uint() {
336 let mut r = task_rng();
342 let mut r = task_rng();
343 let a = r.gen::<f64>();
344 let b = r.gen::<f64>();
345 debug!("{}", (a, b));
349 fn test_gen_weighted_bool() {
350 let mut r = task_rng();
351 assert_eq!(r.gen_weighted_bool(0u), true);
352 assert_eq!(r.gen_weighted_bool(1u), true);
356 fn test_gen_ascii_str() {
357 let mut r = task_rng();
358 assert_eq!(r.gen_ascii_chars().take(0).count(), 0u);
359 assert_eq!(r.gen_ascii_chars().take(10).count(), 10u);
360 assert_eq!(r.gen_ascii_chars().take(16).count(), 16u);
365 let mut r = task_rng();
366 assert_eq!(r.gen_iter::<u8>().take(0).count(), 0u);
367 assert_eq!(r.gen_iter::<u8>().take(10).count(), 10u);
368 assert_eq!(r.gen_iter::<f64>().take(16).count(), 16u);
373 let mut r = task_rng();
374 assert_eq!(r.choose([1i, 1, 1]).map(|&x|x), Some(1));
377 assert_eq!(r.choose(v), None);
382 let mut r = task_rng();
383 let empty: &mut [int] = &mut [];
387 assert_eq!(one.as_slice(), &[1]);
389 let mut two = [1i, 2];
391 assert!(two == [1, 2] || two == [2, 1]);
393 let mut x = [1i, 1, 1];
395 assert_eq!(x.as_slice(), &[1, 1, 1]);
400 let mut r = task_rng();
402 let mut v = [1i, 1, 1];
404 assert_eq!(v.as_slice(), &[1, 1, 1]);
405 assert_eq!(r.gen_range(0u, 1u), 0u);
410 // not sure how to test this aside from just getting some values
411 let _n : uint = random();
412 let _f : f32 = random();
413 let _o : Option<Option<i8>> = random();
417 Option<(u32, (bool,))>),
418 (u8, i8, u16, i16, u32, i32, u64, i64),
419 (f32, (f64, (f64,)))) = random();
427 let mut r = task_rng();
428 let vals = range(min_val, max_val).collect::<Vec<int>>();
429 let small_sample = sample(&mut r, vals.iter(), 5);
430 let large_sample = sample(&mut r, vals.iter(), vals.len() + 5);
432 assert_eq!(small_sample.len(), 5);
433 assert_eq!(large_sample.len(), vals.len());
435 assert!(small_sample.iter().all(|e| {
436 **e >= min_val && **e <= max_val
441 fn test_std_rng_seeded() {
442 let s = task_rng().gen_iter::<uint>().take(256).collect::<Vec<uint>>();
443 let mut ra: StdRng = SeedableRng::from_seed(s.as_slice());
444 let mut rb: StdRng = SeedableRng::from_seed(s.as_slice());
445 assert!(order::equals(ra.gen_ascii_chars().take(100),
446 rb.gen_ascii_chars().take(100)));
450 fn test_std_rng_reseed() {
451 let s = task_rng().gen_iter::<uint>().take(256).collect::<Vec<uint>>();
452 let mut r: StdRng = SeedableRng::from_seed(s.as_slice());
453 let string1 = r.gen_ascii_chars().take(100).collect::<String>();
455 r.reseed(s.as_slice());
457 let string2 = r.gen_ascii_chars().take(100).collect::<String>();
458 assert_eq!(string1, string2);
463 static RAND_BENCH_N: u64 = 100;
470 use self::test::Bencher;
471 use super::{XorShiftRng, StdRng, IsaacRng, Isaac64Rng, Rng, RAND_BENCH_N};
472 use super::{OsRng, weak_rng};
476 fn rand_xorshift(b: &mut Bencher) {
477 let mut rng: XorShiftRng = OsRng::new().unwrap().gen();
479 for _ in range(0, RAND_BENCH_N) {
483 b.bytes = size_of::<uint>() as u64 * RAND_BENCH_N;
487 fn rand_isaac(b: &mut Bencher) {
488 let mut rng: IsaacRng = OsRng::new().unwrap().gen();
490 for _ in range(0, RAND_BENCH_N) {
494 b.bytes = size_of::<uint>() as u64 * RAND_BENCH_N;
498 fn rand_isaac64(b: &mut Bencher) {
499 let mut rng: Isaac64Rng = OsRng::new().unwrap().gen();
501 for _ in range(0, RAND_BENCH_N) {
505 b.bytes = size_of::<uint>() as u64 * RAND_BENCH_N;
509 fn rand_std(b: &mut Bencher) {
510 let mut rng = StdRng::new().unwrap();
512 for _ in range(0, RAND_BENCH_N) {
516 b.bytes = size_of::<uint>() as u64 * RAND_BENCH_N;
520 fn rand_shuffle_100(b: &mut Bencher) {
521 let mut rng = weak_rng();
522 let x : &mut[uint] = [1,..100];