From fb923c7d3f8b37661f49dc2d384749f0296896a0 Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Fri, 20 Sep 2013 21:47:05 +1000 Subject: [PATCH] std: merge rand::{Rng,RngUtil} with default methods. Also, documentation & general clean-up: - remove `gen_char_from`: better served by `sample` or `choose`. - `gen_bytes` generalised to `gen_vec`. - `gen_int_range`/`gen_uint_range` merged into `gen_integer_range` and made to be properly uniformly distributed. Fixes #8644. Minor adjustments to other functions. --- src/libextra/base64.rs | 4 +- src/libextra/container.rs | 2 +- src/libextra/crypto/cryptoutil.rs | 5 +- src/libextra/flate.rs | 6 +- src/libextra/num/bigint.rs | 2 +- src/libextra/sort.rs | 16 +- src/libextra/tempfile.rs | 4 +- src/libextra/treemap.rs | 4 +- src/libextra/uuid.rs | 6 +- src/libstd/hashmap.rs | 2 +- src/libstd/num/strconv.rs | 2 +- src/libstd/os.rs | 4 +- src/libstd/rand/mod.rs | 621 +++++++++++++----------------- src/libstd/rt/comm.rs | 4 +- src/libstd/rt/sched.rs | 4 +- src/test/bench/core-std.rs | 8 +- src/test/bench/noise.rs | 2 +- 17 files changed, 309 insertions(+), 387 deletions(-) diff --git a/src/libextra/base64.rs b/src/libextra/base64.rs index f50108d4eae..191ecbe8d16 100644 --- a/src/libextra/base64.rs +++ b/src/libextra/base64.rs @@ -311,11 +311,11 @@ fn test_from_base64_invalid_padding() { #[test] fn test_base64_random() { - use std::rand::{task_rng, random, RngUtil}; + use std::rand::{task_rng, random, Rng}; use std::vec; do 1000.times { - let times = task_rng().gen_uint_range(1, 100); + let times = task_rng().gen_integer_range(1u, 100); let v = vec::from_fn(times, |_| random::()); assert_eq!(v.to_base64(STANDARD).from_base64().unwrap(), v); } diff --git a/src/libextra/container.rs b/src/libextra/container.rs index 623a9d5f452..c5311d210ab 100644 --- a/src/libextra/container.rs +++ b/src/libextra/container.rs @@ -43,7 +43,7 @@ pub trait Deque : Mutable { mod bench { use std::container::MutableMap; use std::{vec, rand}; - use std::rand::RngUtil; + use std::rand::Rng; use test::BenchHarness; pub fn insert_rand_n>(n: uint, diff --git a/src/libextra/crypto/cryptoutil.rs b/src/libextra/crypto/cryptoutil.rs index 9516517d9f7..4eba3e13eea 100644 --- a/src/libextra/crypto/cryptoutil.rs +++ b/src/libextra/crypto/cryptoutil.rs @@ -347,8 +347,7 @@ fn standard_padding(&mut self, rem: uint, func: &fn(&[u8])) { #[cfg(test)] mod test { - use std::rand::IsaacRng; - use std::rand::RngUtil; + use std::rand::{IsaacRng, Rng}; use std::vec; use cryptoutil::{add_bytes_to_bits, add_bytes_to_bits_tuple}; @@ -365,7 +364,7 @@ pub fn test_digest_1million_random(digest: &mut D, blocksize: uint, e digest.reset(); while count < total_size { - let next: uint = rng.gen_uint_range(0, 2 * blocksize + 1); + let next: uint = rng.gen_integer_range(0, 2 * blocksize + 1); let remaining = total_size - count; let size = if next > remaining { remaining } else { next }; digest.input(buffer.slice_to(size)); diff --git a/src/libextra/flate.rs b/src/libextra/flate.rs index 65d4f79c640..e12ac276482 100644 --- a/src/libextra/flate.rs +++ b/src/libextra/flate.rs @@ -106,15 +106,15 @@ pub fn inflate_bytes_zlib(bytes: &[u8]) -> ~[u8] { mod tests { use super::*; use std::rand; - use std::rand::RngUtil; + use std::rand::Rng; #[test] fn test_flate_round_trip() { let mut r = rand::rng(); let mut words = ~[]; do 20.times { - let range = r.gen_uint_range(1, 10); - words.push(r.gen_bytes(range)); + let range = r.gen_integer_range(1u, 10); + words.push(r.gen_vec::(range)); } do 20.times { let mut input = ~[]; diff --git a/src/libextra/num/bigint.rs b/src/libextra/num/bigint.rs index 936efed94e4..f7462ae2943 100644 --- a/src/libextra/num/bigint.rs +++ b/src/libextra/num/bigint.rs @@ -23,7 +23,7 @@ use std::int; use std::num; use std::num::{IntConvertible, Zero, One, ToStrRadix, FromStrRadix, Orderable}; -use std::rand::{Rng, RngUtil}; +use std::rand::Rng; use std::str; use std::uint; use std::vec; diff --git a/src/libextra/sort.rs b/src/libextra/sort.rs index bea7868fd32..bab889ff924 100644 --- a/src/libextra/sort.rs +++ b/src/libextra/sort.rs @@ -909,7 +909,7 @@ fn ile(x: &(&'static str), y: &(&'static str)) -> bool mod test_tim_sort { use sort::tim_sort; - use std::rand::RngUtil; + use std::rand::Rng; use std::rand; use std::vec; @@ -1008,7 +1008,7 @@ mod big_tests { use sort::*; - use std::rand::RngUtil; + use std::rand::Rng; use std::rand; use std::vec; @@ -1069,8 +1069,8 @@ fn isSorted(arr: &[T]) { isSorted(arr); do 3.times { - let i1 = rng.gen_uint_range(0, n); - let i2 = rng.gen_uint_range(0, n); + let i1 = rng.gen_integer_range(0u, n); + let i2 = rng.gen_integer_range(0u, n); arr.swap(i1, i2); } tim_sort(arr); // 3sort @@ -1088,7 +1088,7 @@ fn isSorted(arr: &[T]) { isSorted(arr); do (n/100).times { - let idx = rng.gen_uint_range(0, n); + let idx = rng.gen_integer_range(0u, n); arr[idx] = rng.gen(); } tim_sort(arr); @@ -1141,8 +1141,8 @@ fn isSorted(arr: &[@T]) { isSorted(arr); do 3.times { - let i1 = rng.gen_uint_range(0, n); - let i2 = rng.gen_uint_range(0, n); + let i1 = rng.gen_integer_range(0u, n); + let i2 = rng.gen_integer_range(0u, n); arr.swap(i1, i2); } tim_sort(arr); // 3sort @@ -1160,7 +1160,7 @@ fn isSorted(arr: &[@T]) { isSorted(arr); do (n/100).times { - let idx = rng.gen_uint_range(0, n); + let idx = rng.gen_integer_range(0u, n); arr[idx] = @rng.gen(); } tim_sort(arr); diff --git a/src/libextra/tempfile.rs b/src/libextra/tempfile.rs index 9044c23ff7a..13e0c47433f 100644 --- a/src/libextra/tempfile.rs +++ b/src/libextra/tempfile.rs @@ -12,7 +12,7 @@ use std::os; -use std::rand::RngUtil; +use std::rand::Rng; use std::rand; /// Attempts to make a temporary directory inside of `tmpdir` whose name will @@ -20,7 +20,7 @@ pub fn mkdtemp(tmpdir: &Path, suffix: &str) -> Option { let mut r = rand::rng(); for _ in range(0u, 1000) { - let p = tmpdir.push(r.gen_str(16) + suffix); + let p = tmpdir.push(r.gen_ascii_str(16) + suffix); if os::make_dir(&p, 0x1c0) { // 700 return Some(p); } diff --git a/src/libextra/treemap.rs b/src/libextra/treemap.rs index 99643e643b7..8ddc0413aa3 100644 --- a/src/libextra/treemap.rs +++ b/src/libextra/treemap.rs @@ -874,7 +874,7 @@ mod test_treemap { use super::*; - use std::rand::RngUtil; + use std::rand::Rng; use std::rand; #[test] @@ -1028,7 +1028,7 @@ fn test_rand_int() { } do 30.times { - let r = rng.gen_uint_range(0, ctrl.len()); + let r = rng.gen_integer_range(0, ctrl.len()); let (key, _) = ctrl.remove(r); assert!(map.remove(&key)); check_structure(&map); diff --git a/src/libextra/uuid.rs b/src/libextra/uuid.rs index 2641c1379e4..8eff9a02299 100644 --- a/src/libextra/uuid.rs +++ b/src/libextra/uuid.rs @@ -62,7 +62,7 @@ fn main() { use std::container::Container; use std::to_str::ToStr; use std::rand; -use std::rand::RngUtil; +use std::rand::Rng; use std::cmp::Eq; use std::cast::{transmute,transmute_copy}; @@ -170,7 +170,7 @@ pub fn new(v: UuidVersion) -> Option { /// 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_bytes(16); + let ub = rand::task_rng().gen_vec(16); let mut uuid = Uuid{ bytes: [0, .. 16] }; vec::bytes::copy_memory(uuid.bytes, ub, 16); uuid.set_variant(VariantRFC4122); @@ -488,7 +488,7 @@ fn equals(&self, other: &Uuid) -> bool { impl rand::Rand for Uuid { #[inline] fn rand(rng: &mut R) -> Uuid { - let ub = rng.gen_bytes(16); + let ub = rng.gen_vec(16); let mut uuid = Uuid{ bytes: [0, .. 16] }; vec::bytes::copy_memory(uuid.bytes, ub, 16); uuid.set_variant(VariantRFC4122); diff --git a/src/libstd/hashmap.rs b/src/libstd/hashmap.rs index 800eca4291f..f496e89acf7 100644 --- a/src/libstd/hashmap.rs +++ b/src/libstd/hashmap.rs @@ -24,7 +24,7 @@ use iter::{FilterMap, Chain, Repeat, Zip}; use num; use option::{None, Option, Some}; -use rand::RngUtil; +use rand::Rng; use rand; use uint; use util::replace; diff --git a/src/libstd/num/strconv.rs b/src/libstd/num/strconv.rs index 94156f6e81f..ca524a255ae 100644 --- a/src/libstd/num/strconv.rs +++ b/src/libstd/num/strconv.rs @@ -734,7 +734,7 @@ fn from_str_issue7588() { #[cfg(test)] mod bench { use extra::test::BenchHarness; - use rand::{XorShiftRng,RngUtil}; + use rand::{XorShiftRng, Rng}; use float; use to_str::ToStr; diff --git a/src/libstd/os.rs b/src/libstd/os.rs index 1dc1d1d6776..08a1f879e78 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -1718,7 +1718,7 @@ mod tests { use os::{remove_file, setenv, unsetenv}; use os; use path::Path; - use rand::RngUtil; + use rand::Rng; use rand; use run; use str::StrSlice; @@ -1738,7 +1738,7 @@ pub fn test_args() { fn make_rand_name() -> ~str { let mut rng = rand::rng(); - let n = ~"TEST" + rng.gen_str(10u); + let n = ~"TEST" + rng.gen_ascii_str(10u); assert!(getenv(n).is_none()); n } diff --git a/src/libstd/rand/mod.rs b/src/libstd/rand/mod.rs index cc1e7bc80ff..525e8a68d58 100644 --- a/src/libstd/rand/mod.rs +++ b/src/libstd/rand/mod.rs @@ -11,7 +11,7 @@ /*! Random number generation. -The key functions are `random()` and `RngUtil::gen()`. These are polymorphic +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::()`. @@ -23,7 +23,7 @@ ~~~ {.rust} use std::rand; -use std::rand::RngUtil; +use std::rand::Rng; fn main() { let mut rng = rand::rng(); @@ -44,17 +44,16 @@ fn main () { */ use cast; -use clone::Clone; use cmp; use container::Container; use int; use iter::{Iterator, range, range_step}; use local_data; -use num; use prelude::*; use str; use sys; use u32; +use u64; use uint; use vec; use libc::size_t; @@ -248,12 +247,6 @@ pub mod rustrt { } } -/// A random number generator -pub trait Rng { - /// Return the next random integer - fn next(&mut self) -> u32; -} - /// A value with a particular weight compared to other values pub struct Weighted { /// The numerical weight of this item @@ -262,311 +255,187 @@ pub struct Weighted { item: T, } -/// Helper functions attached to the Rng type -pub trait RngUtil { - /// Return a random value of a Rand type - fn gen(&mut self) -> T; - /** - * Return a int randomly chosen from the range [start, end), - * failing if start >= end - */ - fn gen_int_range(&mut self, start: int, end: int) -> int; - /** - * Return a uint randomly chosen from the range [start, end), - * failing if start >= end - */ - fn gen_uint_range(&mut self, start: uint, end: uint) -> uint; - /** - * Return a char randomly chosen from chars, failing if chars is empty - */ - fn gen_char_from(&mut self, chars: &str) -> char; - /** - * Return a bool with a 1 in n chance of true - * - * # Example - * - * ~~~ {.rust} - * - * use std::rand; - * use std::rand::RngUtil; - * - * fn main() { - * let mut rng = rand::rng(); - * printfln!("%b", rng.gen_weighted_bool(3)); - * } - * ~~~ - */ - fn gen_weighted_bool(&mut self, n: uint) -> bool; - /** - * Return a random string of the specified length composed of A-Z,a-z,0-9 - * - * # Example - * - * ~~~ {.rust} - * - * use std::rand; - * use std::rand::RngUtil; - * - * fn main() { - * let mut rng = rand::rng(); - * println(rng.gen_str(8)); - * } - * ~~~ - */ - fn gen_str(&mut self, len: uint) -> ~str; - /** - * Return a random byte string of the specified length - * - * # Example - * - * ~~~ {.rust} - * - * use std::rand; - * use std::rand::RngUtil; - * - * fn main() { - * let mut rng = rand::rng(); - * printfln!(rng.gen_bytes(8)); - * } - * ~~~ - */ - fn gen_bytes(&mut self, len: uint) -> ~[u8]; - /** - * Choose an item randomly, failing if values is empty - * - * # Example - * - * ~~~ {.rust} - * - * use std::rand; - * use std::rand::RngUtil; - * - * fn main() { - * let mut rng = rand::rng(); - * printfln!("%d", rng.choose([1,2,4,8,16,32])); - * } - * ~~~ - */ - fn choose(&mut self, values: &[T]) -> T; - /// Choose Some(item) randomly, returning None if values is empty - fn choose_option(&mut self, values: &[T]) -> Option; - /** - * Choose an item respecting the relative weights, failing if the sum of - * the weights is 0 - * - * # Example - * - * ~~~ {.rust} - * - * use std::rand; - * use std::rand::RngUtil; - * - * fn main() { - * let mut rng = rand::rng(); - * let x = [rand::Weighted {weight: 4, item: 'a'}, - * rand::Weighted {weight: 2, item: 'b'}, - * rand::Weighted {weight: 2, item: 'c'}]; - * printfln!("%c", rng.choose_weighted(x)); - * } - * ~~~ - */ - fn choose_weighted(&mut self, v : &[Weighted]) -> T; - /** - * Choose Some(item) respecting the relative weights, returning none if - * the sum of the weights is 0 - * - * # Example - * - * ~~~ {.rust} - * - * use std::rand; - * use std::rand::RngUtil; - * - * fn main() { - * let mut rng = rand::rng(); - * let x = [rand::Weighted {weight: 4, item: 'a'}, - * rand::Weighted {weight: 2, item: 'b'}, - * rand::Weighted {weight: 2, item: 'c'}]; - * printfln!(rng.choose_weighted_option(x)); - * } - * ~~~ - */ - fn choose_weighted_option(&mut self, v: &[Weighted]) - -> Option; - /** - * Return a vec containing copies of the items, in order, where - * the weight of the item determines how many copies there are - * - * # Example - * - * ~~~ {.rust} - * - * use std::rand; - * use std::rand::RngUtil; - * - * fn main() { - * let mut rng = rand::rng(); - * let x = [rand::Weighted {weight: 4, item: 'a'}, - * rand::Weighted {weight: 2, item: 'b'}, - * rand::Weighted {weight: 2, item: 'c'}]; - * printfln!(rng.weighted_vec(x)); - * } - * ~~~ - */ - fn weighted_vec(&mut self, v: &[Weighted]) -> ~[T]; - /** - * Shuffle a vec - * - * # Example - * - * ~~~ {.rust} - * - * use std::rand; - * use std::rand::RngUtil; - * - * fn main() { - * let mut rng = rand::rng(); - * printfln!(rng.shuffle([1,2,3])); - * } - * ~~~ - */ - fn shuffle(&mut self, values: &[T]) -> ~[T]; - /** - * Shuffle a mutable vec in place - * - * # Example - * - * ~~~ {.rust} - * - * use std::rand; - * use std::rand::RngUtil; - * - * fn main() { - * let mut rng = rand::rng(); - * let mut y = [1,2,3]; - * rng.shuffle_mut(y); - * printfln!(y); - * rng.shuffle_mut(y); - * printfln!(y); - * } - * ~~~ - */ - fn shuffle_mut(&mut self, values: &mut [T]); +/// A random number generator +pub trait Rng { + /// Return the next random integer + fn next(&mut self) -> u32; - /** - * Sample up to `n` values from an iterator. - * - * # Example - * - * ~~~ {.rust} - * - * use std::rand; - * use std::rand::RngUtil; - * - * fn main() { - * let mut rng = rand::rng(); - * let vals = range(1, 100).to_owned_vec(); - * let sample = rng.sample(vals.iter(), 5); - * printfln!(sample); - * } - * ~~~ - */ - fn sample>(&mut self, iter: T, n: uint) -> ~[A]; -} -/// Extension methods for random number generators -impl RngUtil for R { - /// Return a random value for a Rand type - #[inline] + /// Return a random value of a Rand type. + /// + /// # Example + /// + /// ~~~ {.rust} + /// use std::rand; + /// + /// fn main() { + /// let rng = rand::task_rng(); + /// let x: uint = rng.gen(); + /// printfln!(x); + /// printfln!(rng.gen::<(float, bool)>()); + /// } + /// ~~~ + #[inline(always)] fn gen(&mut self) -> T { Rand::rand(self) } - /** - * Return an int randomly chosen from the range [start, end), - * failing if start >= end - */ - fn gen_int_range(&mut self, start: int, end: int) -> int { - assert!(start < end); - start + num::abs(self.gen::() % (end - start)) - } - - /** - * Return a uint randomly chosen from the range [start, end), - * failing if start >= end - */ - fn gen_uint_range(&mut self, start: uint, end: uint) -> uint { - assert!(start < end); - start + (self.gen::() % (end - start)) - } - - /** - * Return a char randomly chosen from chars, failing if chars is empty - */ - fn gen_char_from(&mut self, chars: &str) -> char { - assert!(!chars.is_empty()); - let mut cs = ~[]; - for c in chars.iter() { cs.push(c) } - self.choose(cs) - } - - /// Return a bool with a 1-in-n chance of true - fn gen_weighted_bool(&mut self, n: uint) -> bool { - if n == 0u { - true - } else { - self.gen_uint_range(1u, n + 1u) == 1u + /// Return a random vector of the specified length. + /// + /// # Example + /// + /// ~~~ {.rust} + /// use std::rand; + /// + /// fn main() { + /// let rng = rand::task_rng(); + /// let x: ~[uint] = rng.gen_vec(10); + /// printfln!(x); + /// printfln!(rng.gen_vec::<(float, bool)>(5)); + /// } + /// ~~~ + fn gen_vec(&mut self, len: uint) -> ~[T] { + vec::from_fn(len, |_| self.gen()) + } + + /// Generate a random primitive integer in the range [`low`, + /// `high`). Fails if `low >= high`. + /// + /// This gives a uniform distribution (assuming this RNG is itself + /// uniform), even for edge cases like `gen_integer_range(0u8, + /// 170)`, which a naive modulo operation would return numbers + /// less than 85 with double the probability to those greater than + /// 85. + /// + /// # Example + /// + /// ~~~ {.rust} + /// use std::rand; + /// + /// fn main() { + /// let rng = rand::task_rng(); + /// let n: uint = rng.gen_integer_range(0u, 10); + /// printfln!(n); + /// let m: i16 = rng.gen_integer_range(-40, 400); + /// printfln!(m); + /// } + /// ~~~ + fn gen_integer_range(&mut self, low: T, high: T) -> T { + assert!(low < high, "RNG.gen_integer_range called with low >= high"); + let range = (high - low).to_u64(); + let accept_zone = u64::max_value - u64::max_value % range; + loop { + let rand = self.gen::(); + if rand < accept_zone { + return low + NumCast::from(rand % range); + } } } - /** - * Return a random string of the specified length composed of A-Z,a-z,0-9 - */ - fn gen_str(&mut self, len: uint) -> ~str { - let charset = ~"ABCDEFGHIJKLMNOPQRSTUVWXYZ\ - abcdefghijklmnopqrstuvwxyz\ - 0123456789"; - let mut s = ~""; - let mut i = 0u; - while (i < len) { - s = s + str::from_char(self.gen_char_from(charset)); - i += 1u; + /// Return a bool with a 1 in n chance of true + /// + /// # Example + /// + /// ~~~ {.rust} + /// use std::rand; + /// use std::rand::Rng; + /// + /// fn main() { + /// let mut rng = rand::rng(); + /// printfln!("%b", rng.gen_weighted_bool(3)); + /// } + /// ~~~ + fn gen_weighted_bool(&mut self, n: uint) -> bool { + n == 0 || self.gen_integer_range(0, n) == 0 + } + + /// Return a random string of the specified length composed of + /// A-Z,a-z,0-9. + /// + /// # Example + /// + /// ~~~ {.rust} + /// use std::rand; + /// + /// fn main() { + /// println(rand::task_rng().gen_ascii_str(10)); + /// } + /// ~~~ + fn gen_ascii_str(&mut self, len: uint) -> ~str { + static GEN_ASCII_STR_CHARSET: &'static [u8] = bytes!("ABCDEFGHIJKLMNOPQRSTUVWXYZ\ + abcdefghijklmnopqrstuvwxyz\ + 0123456789"); + let mut s = str::with_capacity(len); + for _ in range(0, len) { + s.push_char(self.choose(GEN_ASCII_STR_CHARSET) as char) } s } - /// Return a random byte string of the specified length - fn gen_bytes(&mut self, len: uint) -> ~[u8] { - do vec::from_fn(len) |_i| { - self.gen() - } - } - - /// Choose an item randomly, failing if values is empty - fn choose(&mut self, values: &[T]) -> T { - self.choose_option(values).unwrap() - } - - /// Choose Some(item) randomly, returning None if values is empty - fn choose_option(&mut self, values: &[T]) -> Option { + /// Choose an item randomly, failing if `values` is empty. + fn choose(&mut self, values: &[T]) -> T { + self.choose_option(values).expect("Rng.choose: `values` is empty").clone() + } + + /// Choose `Some(&item)` randomly, returning `None` if values is + /// empty. + /// + /// # Example + /// + /// ~~~ {.rust} + /// use std::rand; + /// + /// fn main() { + /// printfln!(rand::task_rng().choose_option([1,2,4,8,16,32])); + /// printfln!(rand::task_rng().choose_option([])); + /// } + /// ~~~ + fn choose_option<'a, T>(&mut self, values: &'a [T]) -> Option<&'a T> { if values.is_empty() { None } else { - Some(values[self.gen_uint_range(0u, values.len())].clone()) + Some(&values[self.gen_integer_range(0u, values.len())]) } } - /** - * Choose an item respecting the relative weights, failing if the sum of - * the weights is 0 - */ - fn choose_weighted(&mut self, v: &[Weighted]) -> T { - self.choose_weighted_option(v).unwrap() - } - /** - * Choose Some(item) respecting the relative weights, returning none if - * the sum of the weights is 0 - */ + /// Choose an item respecting the relative weights, failing if the sum of + /// the weights is 0 + /// + /// # Example + /// + /// ~~~ {.rust} + /// use std::rand; + /// use std::rand::Rng; + /// + /// fn main() { + /// let mut rng = rand::rng(); + /// let x = [rand::Weighted {weight: 4, item: 'a'}, + /// rand::Weighted {weight: 2, item: 'b'}, + /// rand::Weighted {weight: 2, item: 'c'}]; + /// printfln!("%c", rng.choose_weighted(x)); + /// } + /// ~~~ + fn choose_weighted(&mut self, v: &[Weighted]) -> T { + self.choose_weighted_option(v).expect("Rng.choose_weighted: total weight is 0") + } + + /// Choose Some(item) respecting the relative weights, returning none if + /// the sum of the weights is 0 + /// + /// # Example + /// + /// ~~~ {.rust} + /// use std::rand; + /// use std::rand::Rng; + /// + /// fn main() { + /// let mut rng = rand::rng(); + /// let x = [rand::Weighted {weight: 4, item: 'a'}, + /// rand::Weighted {weight: 2, item: 'b'}, + /// rand::Weighted {weight: 2, item: 'c'}]; + /// printfln!(rng.choose_weighted_option(x)); + /// } + /// ~~~ fn choose_weighted_option(&mut self, v: &[Weighted]) -> Option { let mut total = 0u; @@ -576,7 +445,7 @@ fn choose_weighted_option(&mut self, v: &[Weighted]) if total == 0u { return None; } - let chosen = self.gen_uint_range(0u, total); + let chosen = self.gen_integer_range(0u, total); let mut so_far = 0u; for item in v.iter() { so_far += item.weight; @@ -587,10 +456,23 @@ fn choose_weighted_option(&mut self, v: &[Weighted]) unreachable!(); } - /** - * Return a vec containing copies of the items, in order, where - * the weight of the item determines how many copies there are - */ + /// Return a vec containing copies of the items, in order, where + /// the weight of the item determines how many copies there are + /// + /// # Example + /// + /// ~~~ {.rust} + /// use std::rand; + /// use std::rand::Rng; + /// + /// fn main() { + /// let mut rng = rand::rng(); + /// let x = [rand::Weighted {weight: 4, item: 'a'}, + /// rand::Weighted {weight: 2, item: 'b'}, + /// rand::Weighted {weight: 2, item: 'c'}]; + /// printfln!(rng.weighted_vec(x)); + /// } + /// ~~~ fn weighted_vec(&mut self, v: &[Weighted]) -> ~[T] { let mut r = ~[]; for item in v.iter() { @@ -602,24 +484,61 @@ fn weighted_vec(&mut self, v: &[Weighted]) -> ~[T] { } /// Shuffle a vec - fn shuffle(&mut self, values: &[T]) -> ~[T] { - let mut m = values.to_owned(); - self.shuffle_mut(m); - m - } - - /// Shuffle a mutable vec in place + /// + /// # Example + /// + /// ~~~ {.rust} + /// use std::rand; + /// + /// fn main() { + /// printfln!(rand::task_rng().shuffle(~[1,2,3])); + /// } + /// ~~~ + fn shuffle(&mut self, values: ~[T]) -> ~[T] { + let mut v = values; + self.shuffle_mut(v); + v + } + + /// Shuffle a mutable vector in place. + /// + /// # Example + /// + /// ~~~ {.rust} + /// use std::rand; + /// + /// fn main() { + /// let rng = rand::task_rng(); + /// let mut y = [1,2,3]; + /// rng.shuffle_mut(y); + /// printfln!(y); + /// rng.shuffle_mut(y); + /// printfln!(y); + /// } + /// ~~~ fn shuffle_mut(&mut self, values: &mut [T]) { let mut i = values.len(); while i >= 2u { // invariant: elements with index >= i have been locked in place. i -= 1u; // lock element i in place. - values.swap(i, self.gen_uint_range(0u, i + 1u)); + values.swap(i, self.gen_integer_range(0u, i + 1u)); } } - /// Randomly sample up to `n` elements from an iterator + /// Randomly sample up to `n` elements from an iterator. + /// + /// # Example + /// + /// ~~~ {.rust} + /// use std::rand; + /// + /// fn main() { + /// let rng = rand::task_rng(); + /// let sample = rng.sample(range(1, 100), 5); + /// printfln!(sample); + /// } + /// ~~~ fn sample>(&mut self, iter: T, n: uint) -> ~[A] { let mut reservoir : ~[A] = vec::with_capacity(n); for (i, elem) in iter.enumerate() { @@ -628,7 +547,7 @@ fn sample>(&mut self, iter: T, n: uint) -> ~[A] { loop } - let k = self.gen_uint_range(0, i + 1); + let k = self.gen_integer_range(0, i + 1); if k < reservoir.len() { reservoir[k] = elem } @@ -961,7 +880,7 @@ fn test_rng_seeded() { let seed = seed(); let mut ra = IsaacRng::new_seeded(seed); let mut rb = IsaacRng::new_seeded(seed); - assert_eq!(ra.gen_str(100u), rb.gen_str(100u)); + assert_eq!(ra.gen_ascii_str(100u), rb.gen_ascii_str(100u)); } #[test] @@ -970,7 +889,7 @@ fn test_rng_seeded_custom_seed() { let seed = [2u8, 32u8, 4u8, 32u8, 51u8]; let mut ra = IsaacRng::new_seeded(seed); let mut rb = IsaacRng::new_seeded(seed); - assert_eq!(ra.gen_str(100u), rb.gen_str(100u)); + assert_eq!(ra.gen_ascii_str(100u), rb.gen_ascii_str(100u)); } #[test] @@ -985,35 +904,36 @@ fn test_rng_seeded_custom_seed2() { } #[test] - fn test_gen_int_range() { + fn test_gen_integer_range() { let mut r = rng(); - let a = r.gen_int_range(-3, 42); - assert!(a >= -3 && a < 42); - assert_eq!(r.gen_int_range(0, 1), 0); - assert_eq!(r.gen_int_range(-12, -11), -12); - } + for _ in range(0, 1000) { + let a = r.gen_integer_range(-3i, 42); + assert!(a >= -3 && a < 42); + assert_eq!(r.gen_integer_range(0, 1), 0); + assert_eq!(r.gen_integer_range(-12, -11), -12); + } + + for _ in range(0, 1000) { + let a = r.gen_integer_range(10, 42); + assert!(a >= 10 && a < 42); + assert_eq!(r.gen_integer_range(0, 1), 0); + assert_eq!(r.gen_integer_range(3_000_000u, 3_000_001), 3_000_000); + } - #[test] - #[should_fail] - fn test_gen_int_from_fail() { - let mut r = rng(); - r.gen_int_range(5, -2); } #[test] - fn test_gen_uint_range() { + #[should_fail] + fn test_gen_integer_range_fail_int() { let mut r = rng(); - let a = r.gen_uint_range(3u, 42u); - assert!(a >= 3u && a < 42u); - assert_eq!(r.gen_uint_range(0u, 1u), 0u); - assert_eq!(r.gen_uint_range(12u, 13u), 12u); + r.gen_integer_range(5i, -2); } #[test] #[should_fail] - fn test_gen_uint_range_fail() { + fn test_gen_integer_range_fail_uint() { let mut r = rng(); - r.gen_uint_range(5u, 2u); + r.gen_integer_range(5u, 2u); } #[test] @@ -1032,22 +952,22 @@ fn test_gen_weighted_bool() { } #[test] - fn test_gen_str() { + fn test_gen_ascii_str() { let mut r = rng(); - debug!(r.gen_str(10u)); - debug!(r.gen_str(10u)); - debug!(r.gen_str(10u)); - assert_eq!(r.gen_str(0u).len(), 0u); - assert_eq!(r.gen_str(10u).len(), 10u); - assert_eq!(r.gen_str(16u).len(), 16u); + 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_bytes() { + fn test_gen_vec() { let mut r = rng(); - assert_eq!(r.gen_bytes(0u).len(), 0u); - assert_eq!(r.gen_bytes(10u).len(), 10u); - assert_eq!(r.gen_bytes(16u).len(), 16u); + assert_eq!(r.gen_vec::(0u).len(), 0u); + assert_eq!(r.gen_vec::(10u).len(), 10u); + assert_eq!(r.gen_vec::(16u).len(), 16u); } #[test] @@ -1059,9 +979,12 @@ fn test_choose() { #[test] fn test_choose_option() { let mut r = rng(); - let x: Option = r.choose_option([]); - assert!(x.is_none()); - assert_eq!(r.choose_option([1, 1, 1]), Some(1)); + let v: &[int] = &[]; + assert!(r.choose_option(v).is_none()); + + let i = 1; + let v = [1,1,1]; + assert_eq!(r.choose_option(v), Some(&i)); } #[test] @@ -1106,16 +1029,16 @@ fn test_weighted_vec() { fn test_shuffle() { let mut r = rng(); let empty: ~[int] = ~[]; - assert_eq!(r.shuffle([]), empty); - assert_eq!(r.shuffle([1, 1, 1]), ~[1, 1, 1]); + assert_eq!(r.shuffle(~[]), empty); + assert_eq!(r.shuffle(~[1, 1, 1]), ~[1, 1, 1]); } #[test] fn test_task_rng() { let mut r = task_rng(); r.gen::(); - assert_eq!(r.shuffle([1, 1, 1]), ~[1, 1, 1]); - assert_eq!(r.gen_uint_range(0u, 1u), 0u); + assert_eq!(r.shuffle(~[1, 1, 1]), ~[1, 1, 1]); + assert_eq!(r.gen_integer_range(0u, 1u), 0u); } #[test] diff --git a/src/libstd/rt/comm.rs b/src/libstd/rt/comm.rs index a8cd9bd66d7..6336b1cbe2e 100644 --- a/src/libstd/rt/comm.rs +++ b/src/libstd/rt/comm.rs @@ -1095,7 +1095,7 @@ fn shared_port_close() { #[test] fn megapipe_stress() { use rand; - use rand::RngUtil; + use rand::Rng; if util::limit_thread_creation_due_to_osx_and_valgrind() { return; } @@ -1106,7 +1106,7 @@ fn megapipe_stress() { let total = stress_factor() + 10; let mut rng = rand::rng(); do total.times { - let msgs = rng.gen_uint_range(0, 10); + let msgs = rng.gen_integer_range(0u, 10); let pipe_clone = pipe.clone(); let end_chan_clone = end_chan.clone(); do spawntask_random { diff --git a/src/libstd/rt/sched.rs b/src/libstd/rt/sched.rs index 22888d79984..9c6c53c2064 100644 --- a/src/libstd/rt/sched.rs +++ b/src/libstd/rt/sched.rs @@ -26,7 +26,7 @@ use rt::rtio::{RemoteCallback, PausibleIdleCallback}; use borrow::{to_uint}; use cell::Cell; -use rand::{XorShiftRng, RngUtil}; +use rand::{XorShiftRng, Rng}; use iter::range; use vec::{OwnedVector}; @@ -391,7 +391,7 @@ fn find_work(&mut self) -> Option<~Task> { fn try_steals(&mut self) -> Option<~Task> { let work_queues = &mut self.work_queues; let len = work_queues.len(); - let start_index = self.rng.gen_uint_range(0, len); + let start_index = self.rng.gen_integer_range(0, len); for index in range(0, len).map(|i| (i + start_index) % len) { match work_queues[index].steal() { Some(task) => { diff --git a/src/test/bench/core-std.rs b/src/test/bench/core-std.rs index 5bfef47902b..807f62ece7a 100644 --- a/src/test/bench/core-std.rs +++ b/src/test/bench/core-std.rs @@ -15,7 +15,7 @@ use extra::time::precise_time_s; use std::io; use std::os; -use std::rand::RngUtil; +use std::rand::Rng; use std::rand; use std::str; use std::util; @@ -85,7 +85,7 @@ fn vec_plus() { let mut v = ~[]; let mut i = 0; while i < 1500 { - let rv = vec::from_elem(r.gen_uint_range(0, i + 1), i); + let rv = vec::from_elem(r.gen_integer_range(0u, i + 1), i); if r.gen() { v.push_all_move(rv); } else { @@ -101,7 +101,7 @@ fn vec_append() { let mut v = ~[]; let mut i = 0; while i < 1500 { - let rv = vec::from_elem(r.gen_uint_range(0, i + 1), i); + let rv = vec::from_elem(r.gen_integer_range(0u, i + 1), i); if r.gen() { v = vec::append(v, rv); } @@ -117,7 +117,7 @@ fn vec_push_all() { let mut v = ~[]; for i in range(0u, 1500) { - let mut rv = vec::from_elem(r.gen_uint_range(0, i + 1), i); + let mut rv = vec::from_elem(r.gen_integer_range(0u, i + 1), i); if r.gen() { v.push_all(rv); } diff --git a/src/test/bench/noise.rs b/src/test/bench/noise.rs index 6565fc36dd2..1a3a188b86f 100644 --- a/src/test/bench/noise.rs +++ b/src/test/bench/noise.rs @@ -1,7 +1,7 @@ // Perlin noise benchmark from https://gist.github.com/1170424 use std::float; -use std::rand::{Rng, RngUtil}; +use std::rand::Rng; use std::rand; struct Vec2 { -- GitLab