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.
This commit is contained in:
Huon Wilson 2013-09-20 21:47:05 +10:00
parent 884c1e112d
commit fb923c7d3f
17 changed files with 301 additions and 379 deletions

View File

@ -311,11 +311,11 @@ mod test {
#[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::<u8>());
assert_eq!(v.to_base64(STANDARD).from_base64().unwrap(), v);
}

View File

@ -43,7 +43,7 @@ pub trait Deque<T> : 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<M:MutableMap<uint,uint>>(n: uint,

View File

@ -347,8 +347,7 @@ impl <T: FixedBuffer> StandardPadding for T {
#[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 @@ mod test {
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));

View File

@ -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::<u8>(range));
}
do 20.times {
let mut input = ~[];

View File

@ -23,7 +23,7 @@ use std::cmp::{Eq, Ord, TotalEq, TotalOrd, Ordering, Less, Equal, Greater};
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;

View File

@ -909,7 +909,7 @@ mod tests {
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 @@ mod big_tests {
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 @@ mod big_tests {
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 @@ mod big_tests {
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 @@ mod big_tests {
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);

View File

@ -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 @@ use std::rand;
pub fn mkdtemp(tmpdir: &Path, suffix: &str) -> Option<Path> {
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);
}

View File

@ -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 @@ mod test_treemap {
}
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);

View File

@ -62,7 +62,7 @@ use std::char::Char;
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 @@ impl Uuid {
/// of random numbers. Use the rand::Rand trait to supply
/// a custom generator if required.
pub fn new_v4() -> Uuid {
let ub = rand::task_rng().gen_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 @@ impl TotalEq for Uuid {
impl rand::Rand for Uuid {
#[inline]
fn rand<R: rand::Rng>(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);

View File

@ -24,7 +24,7 @@ use iter::{Iterator, FromIterator, Extendable};
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;

View File

@ -734,7 +734,7 @@ mod test {
#[cfg(test)]
mod bench {
use extra::test::BenchHarness;
use rand::{XorShiftRng,RngUtil};
use rand::{XorShiftRng, Rng};
use float;
use to_str::ToStr;

View File

@ -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 @@ mod tests {
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
}

View File

@ -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::<float>()`.
@ -23,7 +23,7 @@ distributions like normal and exponential.
~~~ {.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<T> {
/// The numerical weight of this item
@ -262,311 +255,187 @@ pub struct Weighted<T> {
item: T,
}
/// Helper functions attached to the Rng type
pub trait RngUtil {
/// Return a random value of a Rand type
fn gen<T:Rand>(&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<T:Clone>(&mut self, values: &[T]) -> T;
/// Choose Some(item) randomly, returning None if values is empty
fn choose_option<T:Clone>(&mut self, values: &[T]) -> Option<T>;
/**
* 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<T:Clone>(&mut self, v : &[Weighted<T>]) -> 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<T:Clone>(&mut self, v: &[Weighted<T>])
-> Option<T>;
/**
* 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<T:Clone>(&mut self, v: &[Weighted<T>]) -> ~[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<T:Clone>(&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<T>(&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<A, T: Iterator<A>>(&mut self, iter: T, n: uint) -> ~[A];
}
/// Extension methods for random number generators
impl<R: Rng> 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<T: Rand>(&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::<int>() % (end - start))
/// 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<T: Rand>(&mut self, len: uint) -> ~[T] {
vec::from_fn(len, |_| self.gen())
}
/**
* 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::<uint>() % (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
/// 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<T: Rand + Int>(&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::<u64>();
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<T: Clone>(&mut self, values: &[T]) -> T {
self.choose_option(values).expect("Rng.choose: `values` is empty").clone()
}
/// Choose an item randomly, failing if values is empty
fn choose<T:Clone>(&mut self, values: &[T]) -> T {
self.choose_option(values).unwrap()
}
/// Choose Some(item) randomly, returning None if values is empty
fn choose_option<T:Clone>(&mut self, values: &[T]) -> Option<T> {
/// 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
*/
/// 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<T:Clone>(&mut self, v: &[Weighted<T>]) -> T {
self.choose_weighted_option(v).unwrap()
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
*/
/// 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<T:Clone>(&mut self, v: &[Weighted<T>])
-> Option<T> {
let mut total = 0u;
@ -576,7 +445,7 @@ impl<R: Rng> RngUtil for R {
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 @@ impl<R: Rng> RngUtil for R {
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<T:Clone>(&mut self, v: &[Weighted<T>]) -> ~[T] {
let mut r = ~[];
for item in v.iter() {
@ -602,24 +484,61 @@ impl<R: Rng> RngUtil for R {
}
/// Shuffle a vec
fn shuffle<T:Clone>(&mut self, values: &[T]) -> ~[T] {
let mut m = values.to_owned();
self.shuffle_mut(m);
m
///
/// # Example
///
/// ~~~ {.rust}
/// use std::rand;
///
/// fn main() {
/// printfln!(rand::task_rng().shuffle(~[1,2,3]));
/// }
/// ~~~
fn shuffle<T>(&mut self, values: ~[T]) -> ~[T] {
let mut v = values;
self.shuffle_mut(v);
v
}
/// Shuffle a mutable vec in place
/// 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<T>(&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<A, T: Iterator<A>>(&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 @@ impl<R: Rng> RngUtil for R {
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 @@ mod test {
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 @@ mod test {
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 @@ mod test {
}
#[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() {
fn test_gen_integer_range_fail_int() {
let mut r = rng();
r.gen_int_range(5, -2);
}
#[test]
fn test_gen_uint_range() {
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 @@ mod test {
}
#[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::<u8>(0u).len(), 0u);
assert_eq!(r.gen_vec::<u8>(10u).len(), 10u);
assert_eq!(r.gen_vec::<f64>(16u).len(), 16u);
}
#[test]
@ -1059,9 +979,12 @@ mod test {
#[test]
fn test_choose_option() {
let mut r = rng();
let x: Option<int> = 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 @@ mod test {
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::<int>();
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]

View File

@ -1095,7 +1095,7 @@ mod test {
#[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 @@ mod test {
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 {

View File

@ -26,7 +26,7 @@ use rt::local::Local;
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 @@ impl Scheduler {
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) => {

View File

@ -15,7 +15,7 @@ extern mod extra;
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);
}

View File

@ -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 {