diff --git a/src/libcore/hashmap.rs b/src/libcore/hashmap.rs index 3233207b8bd6a..d2be0416371be 100644 --- a/src/libcore/hashmap.rs +++ b/src/libcore/hashmap.rs @@ -56,7 +56,7 @@ fn resize_at(capacity: uint) -> uint { pub fn linear_map_with_capacity( initial_capacity: uint) -> HashMap { let r = rand::task_rng(); - linear_map_with_capacity_and_keys((*r).gen_u64(), (*r).gen_u64(), + linear_map_with_capacity_and_keys(r.gen(), r.gen(), initial_capacity) } diff --git a/src/libcore/rand.rs b/src/libcore/rand.rs index 86509c81eb34d..367278f66f321 100644 --- a/src/libcore/rand.rs +++ b/src/libcore/rand.rs @@ -8,7 +8,34 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Random number generation +/*! +Random number generation. + +The key functions are `random()` and `RngUtil::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::()`. + +# Examples +~~~ +use core::rand::RngUtil; + +fn main() { + let rng = rand::rng(); + if rng.gen() { // bool + println(fmt!("int: %d, uint: %u", rng.gen(), rng.gen())) + } +} +~~~ + +~~~ +fn main () { + let tuple_ptr = rand::random::<~(f64, char)>(); + println(fmt!("%?", tuple_ptr)) +} +~~~ +*/ + use int; use prelude::*; @@ -20,98 +47,111 @@ use util; use vec; use libc::size_t; -/// A type that can be randomly generated using an RNG +/// A type that can be randomly generated using an Rng pub trait Rand { fn rand(rng: &R) -> Self; } impl Rand for int { fn rand(rng: &R) -> int { - rng.gen_int() + if int::bits == 32 { + rng.next() as int + } else { + rng.gen::() as int + } } } impl Rand for i8 { fn rand(rng: &R) -> i8 { - rng.gen_i8() + rng.next() as i8 } } impl Rand for i16 { fn rand(rng: &R) -> i16 { - rng.gen_i16() + rng.next() as i16 } } impl Rand for i32 { fn rand(rng: &R) -> i32 { - rng.gen_i32() + rng.next() as i32 } } impl Rand for i64 { fn rand(rng: &R) -> i64 { - rng.gen_i64() + (rng.next() as i64 << 32) | rng.next() as i64 } } impl Rand for uint { fn rand(rng: &R) -> uint { - rng.gen_uint() + if uint::bits == 32 { + rng.next() as uint + } else { + rng.gen::() as uint + } } } impl Rand for u8 { fn rand(rng: &R) -> u8 { - rng.gen_u8() + rng.next() as u8 } } impl Rand for u16 { fn rand(rng: &R) -> u16 { - rng.gen_u16() + rng.next() as u16 } } impl Rand for u32 { fn rand(rng: &R) -> u32 { - rng.gen_u32() + rng.next() } } impl Rand for u64 { fn rand(rng: &R) -> u64 { - rng.gen_u64() + (rng.next() as u64 << 32) | rng.next() as u64 } } impl Rand for float { fn rand(rng: &R) -> float { - rng.gen_float() + rng.gen::() as float } } impl Rand for f32 { fn rand(rng: &R) -> f32 { - rng.gen_f32() + rng.gen::() as f32 } } +static scale : f64 = (u32::max_value as f64) + 1.0f64; impl Rand for f64 { fn rand(rng: &R) -> f64 { - rng.gen_f64() + let u1 = rng.next() as f64; + let u2 = rng.next() as f64; + let u3 = rng.next() as f64; + + ((u1 / scale + u2) / scale + u3) / scale } } impl Rand for char { fn rand(rng: &R) -> char { - rng.gen_char() + rng.next() as char } } impl Rand for bool { fn rand(rng: &R) -> bool { - rng.gen_bool() + rng.next() & 1u32 == 1u32 } } @@ -151,7 +191,7 @@ tuple_impl!{A, B, C, D, E, F, G, H, I, J} impl Rand for Option { fn rand(rng: &R) -> Option { - if rng.gen_bool() { + if rng.gen() { Some(rng.gen()) } else { None @@ -195,93 +235,24 @@ pub struct Weighted { weight: uint, item: T, } -// this should be in gen_f64, but it causes an ICE there. -static scale : f64 = (u32::max_value as f64) + 1.0f64; + pub trait RngUtil { /// Return a random value of a Rand type fn gen(&self) -> T; /** - * Return a random int - * - * *Example* - * - * ~~~ - * - * use core::rand::RngUtil; - * - * fn main() { - * rng = rand::rng(); - * println(fmt!("%d",rng.gen_int())); - * } - * ~~~ + * Return a int randomly chosen from the range [start, end), + * failing if start >= end */ - fn gen_int(&self) -> int; fn gen_int_range(&self, start: int, end: int) -> int; - /// Return a random i8 - fn gen_i8(&self) -> i8; - /// Return a random i16 - fn gen_i16(&self) -> i16; - /// Return a random i32 - fn gen_i32(&self) -> i32; - /// Return a random i64 - fn gen_i64(&self) -> i64; - /// Return a random uint - fn gen_uint(&self) -> uint; /** * Return a uint randomly chosen from the range [start, end), * failing if start >= end */ fn gen_uint_range(&self, start: uint, end: uint) -> uint; - /// Return a random u8 - fn gen_u8(&self) -> u8; - /// Return a random u16 - fn gen_u16(&self) -> u16; - /// Return a random u32 - fn gen_u32(&self) -> u32; - /// Return a random u64 - fn gen_u64(&self) -> u64; - /** - * Return random float in the interval [0,1] - * - * *Example* - * - * ~~~ - * - * use core::rand::RngUtil; - * - * fn main() { - * rng = rand::rng(); - * println(fmt!("%f",rng.gen_float())); - * } - * ~~~ - */ - fn gen_float(&self) -> float; - /// Return a random f32 in the interval [0,1] - fn gen_f32(&self) -> f32; - /// Return a random f64 in the interval [0,1] - fn gen_f64(&self) -> f64; - /// Return a random char - fn gen_char(&self) -> char; /** * Return a char randomly chosen from chars, failing if chars is empty */ fn gen_char_from(&self, chars: &str) -> char; - /** - * Return a random bool - * - * *Example* - * - * ~~~ - * - * use core::rand::RngUtil; - * - * fn main() { - * rng = rand::rng(); - * println(fmt!("%b",rng.gen_bool())); - * } - * ~~~ - */ - fn gen_bool(&self) -> bool; /** * Return a bool with a 1 in n chance of true * @@ -453,43 +424,13 @@ impl RngUtil for R { Rand::rand(self) } - /// Return a random int - fn gen_int(&self) -> int { - self.gen_i64() as int - } - /** * Return an int randomly chosen from the range [start, end), * failing if start >= end */ fn gen_int_range(&self, start: int, end: int) -> int { assert!(start < end); - start + int::abs(self.gen_int() % (end - start)) - } - - /// Return a random i8 - fn gen_i8(&self) -> i8 { - self.next() as i8 - } - - /// Return a random i16 - fn gen_i16(&self) -> i16 { - self.next() as i16 - } - - /// Return a random i32 - fn gen_i32(&self) -> i32 { - self.next() as i32 - } - - /// Return a random i64 - fn gen_i64(&self) -> i64 { - (self.next() as i64 << 32) | self.next() as i64 - } - - /// Return a random uint - fn gen_uint(&self) -> uint { - self.gen_u64() as uint + start + int::abs(self.gen::() % (end - start)) } /** @@ -498,51 +439,7 @@ impl RngUtil for R { */ fn gen_uint_range(&self, start: uint, end: uint) -> uint { assert!(start < end); - start + (self.gen_uint() % (end - start)) - } - - /// Return a random u8 - fn gen_u8(&self) -> u8 { - self.next() as u8 - } - - /// Return a random u16 - fn gen_u16(&self) -> u16 { - self.next() as u16 - } - - /// Return a random u32 - fn gen_u32(&self) -> u32 { - self.next() - } - - /// Return a random u64 - fn gen_u64(&self) -> u64 { - (self.next() as u64 << 32) | self.next() as u64 - } - - /// Return a random float in the interval [0,1] - fn gen_float(&self) -> float { - self.gen_f64() as float - } - - /// Return a random f32 in the interval [0,1] - fn gen_f32(&self) -> f32 { - self.gen_f64() as f32 - } - - /// Return a random f64 in the interval [0,1] - fn gen_f64(&self) -> f64 { - let u1 = self.next() as f64; - let u2 = self.next() as f64; - let u3 = self.next() as f64; - - return ((u1 / scale + u2) / scale + u3) / scale; - } - - /// Return a random char - fn gen_char(&self) -> char { - self.next() as char + start + (self.gen::() % (end - start)) } /** @@ -555,11 +452,6 @@ impl RngUtil for R { self.choose(cs) } - /// Return a random bool - fn gen_bool(&self) -> bool { - self.next() & 1u32 == 1u32 - } - /// Return a bool with a 1-in-n chance of true fn gen_weighted_bool(&self, n: uint) -> bool { if n == 0u { @@ -588,7 +480,7 @@ impl RngUtil for R { /// Return a random byte string of the specified length fn gen_bytes(&self, len: uint) -> ~[u8] { do vec::from_fn(len) |_i| { - self.gen_u8() + self.gen() } } @@ -777,7 +669,7 @@ fn tls_rng_state(_v: @IsaacRng) {} /** * Gives back a lazily initialized task-local random number generator, * seeded by the system. Intended to be used in method chaining style, ie - * task_rng().gen_int(). + * `task_rng().gen::()`. */ pub fn task_rng() -> @IsaacRng { let r : Option<@IsaacRng>; @@ -796,6 +688,11 @@ pub fn task_rng() -> @IsaacRng { } } +// Allow direct chaining with `task_rng` +impl Rng for @R { + fn next(&self) -> u32 { (*self).next() } +} + /** * Returns a random value of a Rand type, using the task's random number * generator. @@ -872,8 +769,8 @@ mod tests { #[test] fn test_gen_float() { let r = rng(); - let a = r.gen_float(); - let b = r.gen_float(); + let a = r.gen::(); + let b = r.gen::(); debug!((a, b)); } @@ -966,9 +863,9 @@ mod tests { #[test] fn test_task_rng() { let r = task_rng(); - (*r).gen_int(); - assert!((*r).shuffle(~[1, 1, 1]) == ~[1, 1, 1]); - assert!((*r).gen_uint_range(0u, 1u) == 0u); + r.gen::(); + assert!(r.shuffle(~[1, 1, 1]) == ~[1, 1, 1]); + assert!(r.gen_uint_range(0u, 1u) == 0u); } #[test] diff --git a/src/librustpkg/path_util.rs b/src/librustpkg/path_util.rs index b35b9face2a8f..cd9b44c278e46 100644 --- a/src/librustpkg/path_util.rs +++ b/src/librustpkg/path_util.rs @@ -73,8 +73,8 @@ pub fn normalize(p: ~Path) -> ~Path { mod test { use core::{os, rand}; use core::path::Path; - use core::rand::RngUtil; use path_util::*; + use core::rand::RngUtil; // Helper function to create a directory name that doesn't exist pub fn mk_nonexistent(tmpdir: &Path, suffix: &str) -> Path { diff --git a/src/libstd/bitv.rs b/src/libstd/bitv.rs index 5f4d507568a10..8bfa201395069 100644 --- a/src/libstd/bitv.rs +++ b/src/libstd/bitv.rs @@ -1425,7 +1425,7 @@ mod tests { assert!(a.capacity() == uint::bits); } - fn rng() -> rand::RandRes { + fn rng() -> rand::IsaacRng { let seed = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]; rand::IsaacRng::new_seeded(seed) } diff --git a/src/libstd/sort.rs b/src/libstd/sort.rs index be32fb2565755..db6efdf3f52aa 100644 --- a/src/libstd/sort.rs +++ b/src/libstd/sort.rs @@ -902,12 +902,8 @@ mod tests { #[cfg(test)] mod test_tim_sort { use core::prelude::*; - use sort::tim_sort; - use core::rand::RngUtil; - use core::rand; - use core::vec; struct CVal { val: float, @@ -916,7 +912,7 @@ mod test_tim_sort { impl Ord for CVal { fn lt(&self, other: &CVal) -> bool { let rng = rand::rng(); - if rng.gen_float() > 0.995 { fail!(~"It's happening!!!"); } + if rng.gen::() > 0.995 { fail!(~"It's happening!!!"); } (*self).val < other.val } fn le(&self, other: &CVal) -> bool { (*self).val <= other.val } @@ -966,8 +962,7 @@ mod test_tim_sort { fn crash_test() { let rng = rand::rng(); let mut arr = do vec::from_fn(1000) |_i| { - let randVal = rng.gen_float(); - CVal { val: randVal } + CVal { val: rng.gen() } }; tim_sort(arr); @@ -987,8 +982,7 @@ mod test_tim_sort { fn test_bad_Ord_impl() { let rng = rand::rng(); let mut arr = do vec::from_fn(500) |_i| { - let randVal = rng.gen_uint(); - DVal { val: randVal } + DVal { val: rng.gen() } }; tim_sort(arr); @@ -998,14 +992,8 @@ mod test_tim_sort { #[cfg(test)] mod big_tests { use core::prelude::*; - use sort::*; - use core::rand::RngUtil; - use core::rand; - use core::task; - use core::uint; - use core::vec; #[test] fn test_unique() { @@ -1049,10 +1037,9 @@ mod big_tests { for uint::range(lo, hi) |i| { let n = 1 << i; - let arr = do vec::from_fn(n) |_i| { - rng.gen_float() + let mut arr: ~[float] = do vec::from_fn(n) |_i| { + rng.gen() }; - let mut arr = arr; tim_sort(arr); // *sort isSorted(arr); @@ -1076,7 +1063,7 @@ mod big_tests { let size = arr.len(); let mut idx = 1; while idx <= 10 { - arr[size-idx] = rng.gen_float(); + arr[size-idx] = rng.gen(); idx += 1; } } @@ -1085,7 +1072,7 @@ mod big_tests { for (n/100).times { let idx = rng.gen_uint_range(0, n); - arr[idx] = rng.gen_float(); + arr[idx] = rng.gen(); } tim_sort(arr); isSorted(arr); @@ -1121,8 +1108,8 @@ mod big_tests { for uint::range(lo, hi) |i| { let n = 1 << i; - let arr = do vec::from_fn(n) |_i| { - @rng.gen_float() + let arr: ~[@float] = do vec::from_fn(n) |_i| { + @rng.gen() }; let mut arr = arr; @@ -1148,7 +1135,7 @@ mod big_tests { let size = arr.len(); let mut idx = 1; while idx <= 10 { - arr[size-idx] = @rng.gen_float(); + arr[size-idx] = @rng.gen(); idx += 1; } } @@ -1157,7 +1144,7 @@ mod big_tests { for (n/100).times { let idx = rng.gen_uint_range(0, n); - arr[idx] = @rng.gen_float(); + arr[idx] = @rng.gen(); } tim_sort(arr); isSorted(arr); diff --git a/src/libstd/tempfile.rs b/src/libstd/tempfile.rs index b92e652b7af9b..c9bcb3b8952be 100644 --- a/src/libstd/tempfile.rs +++ b/src/libstd/tempfile.rs @@ -10,10 +10,8 @@ //! Temporary files and directories -use core::os; use core::prelude::*; use core::rand::RngUtil; -use core::rand; pub fn mkdtemp(tmpdir: &Path, suffix: &str) -> Option { let r = rand::rng(); diff --git a/src/libstd/test.rs b/src/libstd/test.rs index 113d66b30204d..f82cc25e0f618 100644 --- a/src/libstd/test.rs +++ b/src/libstd/test.rs @@ -19,20 +19,9 @@ use getopts; use sort; use term; -use core::cmp::Eq; - use core::to_str::ToStr; -use core::either::Either; -use core::either; -use core::io::WriterUtil; -use core::io; use core::comm::{stream, SharedChan}; -use core::option; use core::prelude::*; -use core::result; -use core::str; -use core::task; -use core::vec; pub mod rustrt { use core::libc::size_t; @@ -608,12 +597,8 @@ pub mod bench { use time::precise_time_ns; use test::{BenchHarness, BenchSamples}; use stats::Stats; - - use core::num; + use core::prelude::*; use core::rand::RngUtil; - use core::rand; - use core::u64; - use core::vec; pub impl BenchHarness { diff --git a/src/libstd/timer.rs b/src/libstd/timer.rs index f0daf407073af..1e48ce5aa6f2e 100644 --- a/src/libstd/timer.rs +++ b/src/libstd/timer.rs @@ -175,11 +175,7 @@ mod test { use timer::*; use uv; - - use core::iter; use core::rand::RngUtil; - use core::rand; - use core::task; use core::pipes::{stream, SharedChan}; #[test] diff --git a/src/libstd/treemap.rs b/src/libstd/treemap.rs index dbb01b6ce397b..020f4daefd9d6 100644 --- a/src/libstd/treemap.rs +++ b/src/libstd/treemap.rs @@ -698,7 +698,6 @@ mod test_treemap { use core::iterator::*; use super::*; use core::rand::RngUtil; - use core::rand; #[test] fn find_empty() { @@ -839,8 +838,8 @@ mod test_treemap { for 3.times { for 90.times { - let k = rng.gen_int(); - let v = rng.gen_int(); + let k = rng.gen(); + let v = rng.gen(); if !ctrl.contains(&(k, v)) { assert!(map.insert(k, v)); ctrl.push((k, v)); diff --git a/src/test/bench/core-map.rs b/src/test/bench/core-map.rs index 0c53ccd46e8b7..e216215ace7f9 100644 --- a/src/test/bench/core-map.rs +++ b/src/test/bench/core-map.rs @@ -15,6 +15,7 @@ use std::time; use std::treemap::TreeMap; use core::hashmap::{HashMap, HashSet}; use core::trie::TrieMap; +use core::rand::Rng; fn timed(label: &str, f: &fn()) { let start = time::precise_time_s(); diff --git a/src/test/bench/core-set.rs b/src/test/bench/core-set.rs index 2ed3f668684d8..b3e3d295c0fad 100644 --- a/src/test/bench/core-set.rs +++ b/src/test/bench/core-set.rs @@ -12,7 +12,6 @@ extern mod std; use core::hashmap::HashSet; use std::bitv::BitvSet; use std::treemap::TreeSet; -use core::io::WriterUtil; struct Results { sequential_ints: float, @@ -32,7 +31,7 @@ fn timed(result: &mut float, op: &fn()) { } pub impl Results { - fn bench_int>(&mut self, rng: &rand::Rng, num_keys: uint, + fn bench_int, R: rand::Rng>(&mut self, rng: &R, num_keys: uint, rand_cap: uint, f: &fn() -> T) { { let mut set = f(); @@ -70,8 +69,8 @@ pub impl Results { } } - fn bench_str>(&mut self, rng: &rand::Rng, num_keys: uint, - f: &fn() -> T) { + fn bench_str, R: rand::Rng>(&mut self, rng: &R, num_keys: uint, + f: &fn() -> T) { { let mut set = f(); do timed(&mut self.sequential_strings) { @@ -166,15 +165,15 @@ fn main() { { let rng = rand::IsaacRng::new_seeded(seed); let mut results = empty_results(); - results.bench_int(rng, num_keys, max, || TreeSet::new::()); - results.bench_str(rng, num_keys, || TreeSet::new::<~str>()); + results.bench_int(&rng, num_keys, max, || TreeSet::new::()); + results.bench_str(&rng, num_keys, || TreeSet::new::<~str>()); write_results("std::treemap::TreeSet", &results); } { let rng = rand::IsaacRng::new_seeded(seed); let mut results = empty_results(); - results.bench_int(rng, num_keys, max, || BitvSet::new()); + results.bench_int(&rng, num_keys, max, || BitvSet::new()); write_results("std::bitv::BitvSet", &results); } } diff --git a/src/test/bench/core-std.rs b/src/test/bench/core-std.rs index 8438759b5c8d3..1af3538a0219d 100644 --- a/src/test/bench/core-std.rs +++ b/src/test/bench/core-std.rs @@ -13,8 +13,6 @@ extern mod std; use std::time::precise_time_s; - -use core::io::{Reader, ReaderUtil}; use core::rand::RngUtil; macro_rules! bench ( @@ -77,7 +75,7 @@ fn vec_plus() { let mut i = 0; while i < 1500 { let rv = vec::from_elem(r.gen_uint_range(0, i + 1), i); - if r.gen_bool() { + if r.gen() { v += rv; } else { @@ -94,7 +92,7 @@ fn vec_append() { let mut i = 0; while i < 1500 { let rv = vec::from_elem(r.gen_uint_range(0, i + 1), i); - if r.gen_bool() { + if r.gen() { v = vec::append(v, rv); } else { @@ -110,7 +108,7 @@ fn vec_push_all() { let mut v = ~[]; for uint::range(0, 1500) |i| { let mut rv = vec::from_elem(r.gen_uint_range(0, i + 1), i); - if r.gen_bool() { + if r.gen() { v.push_all(rv); } else { diff --git a/src/test/bench/graph500-bfs.rs b/src/test/bench/graph500-bfs.rs index e84d8abf9790c..bd3de4a1b8aba 100644 --- a/src/test/bench/graph500-bfs.rs +++ b/src/test/bench/graph500-bfs.rs @@ -25,7 +25,6 @@ use std::time; use std::deque::Deque; use std::par; use core::hashmap::{HashMap, HashSet}; -use core::io::WriterUtil; use core::int::abs; use core::rand::RngUtil; @@ -51,7 +50,7 @@ fn make_edges(scale: uint, edgefactor: uint) -> ~[(node_id, node_id)] { let j = j * 2i64; let scale = scale - 1u; - let x = r.gen_float(); + let x = r.gen::(); if x < A { choose_edge(i, j, scale, r) diff --git a/src/test/bench/noise.rs b/src/test/bench/noise.rs index e032274482a02..0da3a2e5d68d0 100644 --- a/src/test/bench/noise.rs +++ b/src/test/bench/noise.rs @@ -13,8 +13,8 @@ fn lerp(a: f32, b: f32, v: f32) -> f32 { a * (1.0 - v) + b * v } #[inline(always)] fn smooth(v: f32) -> f32 { v * v * (3.0 - 2.0 * v) } -fn random_gradient(r: &Rng) -> Vec2 { - let v = r.gen_float() * float::consts::pi * 2.0; +fn random_gradient(r: &R) -> Vec2 { + let v = 2.0 * float::consts::pi * r.gen(); Vec2 { x: float::cos(v) as f32, y: float::sin(v) as f32, diff --git a/src/test/bench/shootout-fasta.rs b/src/test/bench/shootout-fasta.rs index 83e1a958d3ca8..0fcf8341ac852 100644 --- a/src/test/bench/shootout-fasta.rs +++ b/src/test/bench/shootout-fasta.rs @@ -16,7 +16,7 @@ * http://shootout.alioth.debian.org/ */ extern mod std; -use core::io::WriterUtil; +use core::rand::Rng; fn LINE_LENGTH() -> uint { return 60u; }