diff --git a/mk/rt.mk b/mk/rt.mk index d1a4b2bc87a..1b818bfee41 100644 --- a/mk/rt.mk +++ b/mk/rt.mk @@ -74,7 +74,6 @@ RUNTIME_CXXS_$(1)_$(2) := \ rt/rust_rng.cpp \ rt/rust_upcall.cpp \ rt/rust_uv.cpp \ - rt/isaac/randport.cpp \ rt/miniz.cpp \ rt/memory_region.cpp \ rt/boxed_region.cpp \ 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 @@ 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::()); 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 @@ impl 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)); 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::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; 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 @@ 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); 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 @@ use std::rand; 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 @@ 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); 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 @@ 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(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::{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; 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 @@ mod test { #[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 @@ 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 } diff --git a/src/libstd/rand.rs b/src/libstd/rand/mod.rs similarity index 65% rename from src/libstd/rand.rs rename to src/libstd/rand/mod.rs index 71664569c87..7b753f821d7 100644 --- a/src/libstd/rand.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 @@ 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,22 +44,20 @@ 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; -#[path="rand/distributions.rs"] pub mod distributions; /// A type that can be randomly generated using an Rng @@ -244,17 +242,10 @@ pub mod rustrt { use libc::size_t; extern { - pub fn rand_seed_size() -> size_t; pub fn rand_gen_seed(buf: *mut u8, sz: size_t); } } -/// 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 @@ -263,311 +254,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 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()) } - /** - * 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 + /// 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).expect("Rng.choose: `values` is empty").clone() } - /// 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 `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(&mut self, v: &[Weighted]) -> 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(&mut self, v: &[Weighted]) -> Option { let mut total = 0u; @@ -577,7 +444,7 @@ impl 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; @@ -588,10 +455,23 @@ impl 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(&mut self, v: &[Weighted]) -> ~[T] { let mut r = ~[]; for item in v.iter() { @@ -603,24 +483,61 @@ impl RngUtil for R { } /// Shuffle a vec - fn shuffle(&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(&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(&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() { @@ -629,7 +546,7 @@ impl 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 } @@ -904,8 +821,8 @@ pub fn seed() -> ~[u8] { #[fixed_stack_segment]; #[inline(never)]; unsafe { - let n = rustrt::rand_seed_size() as uint; - let mut s = vec::from_elem(n, 0_u8); + let n = RAND_SIZE * 4; + let mut s = vec::from_elem(n as uint, 0_u8); do s.as_mut_buf |p, sz| { rustrt::rand_gen_seed(p, sz as size_t) } @@ -962,7 +879,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] @@ -971,7 +888,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] @@ -986,35 +903,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] @@ -1033,22 +951,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::(0u).len(), 0u); + assert_eq!(r.gen_vec::(10u).len(), 10u); + assert_eq!(r.gen_vec::(16u).len(), 16u); } #[test] @@ -1060,9 +978,12 @@ mod test { #[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] @@ -1107,16 +1028,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::(); - 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] @@ -1131,46 +1052,6 @@ mod test { (f32, (f64, (float,)))) = random(); } - #[test] - fn compare_isaac_implementation() { - #[fixed_stack_segment]; #[inline(never)]; - - // This is to verify that the implementation of the ISAAC rng is - // correct (i.e. matches the output of the upstream implementation, - // which is in the runtime) - use libc::size_t; - - #[abi = "cdecl"] - mod rustrt { - use libc::size_t; - - #[allow(non_camel_case_types)] // runtime type - pub enum rust_rng {} - - extern { - pub fn rand_new_seeded(buf: *u8, sz: size_t) -> *rust_rng; - pub fn rand_next(rng: *rust_rng) -> u32; - pub fn rand_free(rng: *rust_rng); - } - } - - // run against several seeds - do 10.times { - unsafe { - let seed = super::seed(); - let rt_rng = do seed.as_imm_buf |p, sz| { - rustrt::rand_new_seeded(p, sz as size_t) - }; - let mut rng = IsaacRng::new_seeded(seed); - - do 10000.times { - assert_eq!(rng.next(), rustrt::rand_next(rt_rng)); - } - rustrt::rand_free(rt_rng); - } - } - } - #[test] fn test_sample() { let MIN_VAL = 1; 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 @@ 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 { 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::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) => { diff --git a/src/rt/isaac/rand.h b/src/rt/isaac/rand.h deleted file mode 100644 index c28b35e688d..00000000000 --- a/src/rt/isaac/rand.h +++ /dev/null @@ -1,54 +0,0 @@ -/* ------------------------------------------------------------------------------- -rand.h: definitions for a random number generator -By Bob Jenkins, 1996, Public Domain -MODIFIED: - 960327: Creation (addition of randinit, really) - 970719: use context, not global variables, for internal state - 980324: renamed seed to flag - 980605: recommend RANDSIZL=4 for noncryptography. - 010626: note this is public domain ------------------------------------------------------------------------------- -*/ -#ifndef STANDARD -#include "standard.h" -#endif - -#ifndef RAND -#define RAND -#define RANDSIZL (8) /* I recommend 8 for crypto, 4 for simulations */ -#define RANDSIZ (1<randcnt-- ? \ - (isaac(r), (r)->randcnt=RANDSIZ-1, (r)->randrsl[(r)->randcnt]) : \ - (r)->randrsl[(r)->randcnt]) - -#endif /* RAND */ diff --git a/src/rt/isaac/randport.cpp b/src/rt/isaac/randport.cpp deleted file mode 100644 index a2928a9b5d0..00000000000 --- a/src/rt/isaac/randport.cpp +++ /dev/null @@ -1,139 +0,0 @@ -/* ------------------------------------------------------------------------------- -rand.c: By Bob Jenkins. My random number generator, ISAAC. Public Domain -MODIFIED: - 960327: Creation (addition of randinit, really) - 970719: use context, not global variables, for internal state - 980324: make a portable version - 010626: Note this is public domain - 100725: Mask on use of >32 bits, not on assignment: from Paul Eggert ------------------------------------------------------------------------------- -*/ -#ifndef STANDARD -#include "standard.h" -#endif -#ifndef RAND -#include "rand.h" -#endif - - -#define ind(mm,x) ((mm)[(x>>2)&(RANDSIZ-1)]) -#define rngstep(mix,a,b,mm,m,m2,r,x) \ -{ \ - x = *m; \ - a = ((a^(mix)) + *(m2++)) & 0xffffffff; \ - *(m++) = y = (ind(mm,x) + a + b) & 0xffffffff; \ - *(r++) = b = (ind(mm,y>>RANDSIZL) + x) & 0xffffffff; \ -} - -void isaac(randctx *ctx) -{ - ub4 a,b,x,y,*m,*mm,*m2,*r,*mend; - mm=ctx->randmem; r=ctx->randrsl; - a = ctx->randa; b = ctx->randb + (++ctx->randc); - for (m = mm, mend = m2 = m+(RANDSIZ/2); m>6 , a, b, mm, m, m2, r, x); - rngstep( a<<2 , a, b, mm, m, m2, r, x); - rngstep( (a & 0xffffffff) >>16, a, b, mm, m, m2, r, x); - } - for (m2 = mm; m2>6 , a, b, mm, m, m2, r, x); - rngstep( a<<2 , a, b, mm, m, m2, r, x); - rngstep( (a & 0xffffffff) >>16, a, b, mm, m, m2, r, x); - } - ctx->randb = b; ctx->randa = a; -} - - -#define mix(a,b,c,d,e,f,g,h) \ -{ \ - a^=b<<11; d+=a; b+=c; \ - b^=(c&0xffffffff)>>2; e+=b; c+=d; \ - c^=d<<8; f+=c; d+=e; \ - d^=(e&0xffffffff)>>16; g+=d; e+=f; \ - e^=f<<10; h+=e; f+=g; \ - f^=(g&0xffffffff)>>4; a+=f; g+=h; \ - g^=h<<8; b+=g; h+=a; \ - h^=(a&0xffffffff)>>9; c+=h; a+=b; \ -} - -/* if (flag==TRUE), then use the contents of randrsl[] to initialize mm[]. */ -void randinit(randctx *ctx, word flag) -{ - word i; - ub4 a,b,c,d,e,f,g,h; - ub4 *m,*r; - ctx->randa = ctx->randb = ctx->randc = 0; - m=ctx->randmem; - r=ctx->randrsl; - a=b=c=d=e=f=g=h=0x9e3779b9; /* the golden ratio */ - - for (i=0; i<4; ++i) /* scramble it */ - { - mix(a,b,c,d,e,f,g,h); - } - - if (flag) - { - /* initialize using the contents of r[] as the seed */ - for (i=0; irandcnt=RANDSIZ; /* prepare to use the first set of results */ -} - - -#ifdef NEVER -int main() -{ - ub4 i,j; - randctx ctx; - ctx.randa=ctx.randb=ctx.randc=(ub4)0; - for (i=0; i<256; ++i) ctx.randrsl[i]=(ub4)0; - randinit(&ctx, TRUE); - for (i=0; i<2; ++i) - { - isaac(&ctx); - for (j=0; j<256; ++j) - { - printf("%.8lx",ctx.randrsl[j]); - if ((j&7)==7) printf("\n"); - } - } -} -#endif diff --git a/src/rt/isaac/standard.h b/src/rt/isaac/standard.h deleted file mode 100644 index c196a37474b..00000000000 --- a/src/rt/isaac/standard.h +++ /dev/null @@ -1,50 +0,0 @@ -/* ------------------------------------------------------------------------------- -Standard definitions and types, Bob Jenkins ------------------------------------------------------------------------------- -*/ -#ifndef STANDARD -# define STANDARD -# ifndef STDIO -# include -# define STDIO -# endif -# ifndef STDDEF -# include -# define STDDEF -# endif -# ifndef STDINT -# include -# define STDINT -# endif - -typedef uint64_t ub8; -#define UB8MAXVAL 0xffffffffffffffffLL -#define UB8BITS 64 -typedef int64_t sb8; -#define SB8MAXVAL 0x7fffffffffffffffLL -typedef uint32_t ub4; /* unsigned 4-byte quantities */ -#define UB4MAXVAL 0xffffffff -typedef int32_t sb4; -#define UB4BITS 32 -#define SB4MAXVAL 0x7fffffff -typedef uint16_t ub2; -#define UB2MAXVAL 0xffff -#define UB2BITS 16 -typedef int16_t sb2; -#define SB2MAXVAL 0x7fff -typedef uint8_t ub1; -#define UB1MAXVAL 0xff -#define UB1BITS 8 -typedef int8_t sb1; /* signed 1-byte quantities */ -#define SB1MAXVAL 0x7f -typedef int word; /* fastest type available */ - -#define bis(target,mask) ((target) |= (mask)) -#define bic(target,mask) ((target) &= ~(mask)) -#define bit(target,mask) ((target) & (mask)) -#define TRUE 1 -#define FALSE 0 -#define SUCCESS 0 /* 1 on VAX */ - -#endif /* STANDARD */ diff --git a/src/rt/rust_builtin.cpp b/src/rt/rust_builtin.cpp index 8877b082588..eeb0c95337a 100644 --- a/src/rt/rust_builtin.cpp +++ b/src/rt/rust_builtin.cpp @@ -69,35 +69,11 @@ rust_env_pairs() { } #endif -extern "C" CDECL size_t -rand_seed_size() { - return rng_seed_size(); -} - extern "C" CDECL void rand_gen_seed(uint8_t* dest, size_t size) { rng_gen_seed(dest, size); } -extern "C" CDECL void * -rand_new_seeded(uint8_t* seed, size_t seed_size) { - assert(seed != NULL); - rust_rng *rng = (rust_rng *) malloc(sizeof(rust_rng)); - assert(rng != NULL && "rng alloc failed"); - rng_init(rng, NULL, seed, seed_size); - return rng; -} - -extern "C" CDECL uint32_t -rand_next(rust_rng *rng) { - return rng_gen_u32(rng); -} - -extern "C" CDECL void -rand_free(rust_rng *rng) { - free(rng); -} - extern "C" CDECL char* #if defined(__WIN32__) rust_list_dir_val(WIN32_FIND_DATA* entry_ptr) { diff --git a/src/rt/rust_rng.cpp b/src/rt/rust_rng.cpp index 27015891fee..89754f94b70 100644 --- a/src/rt/rust_rng.cpp +++ b/src/rt/rust_rng.cpp @@ -32,14 +32,6 @@ win32_require(LPCTSTR fn, BOOL ok) { } #endif -size_t -rng_seed_size() { - randctx rctx; - return sizeof(rctx.randrsl); -} - -// Initialization helpers for ISAAC RNG - void rng_gen_seed(uint8_t* dest, size_t size) { #ifdef __WIN32__ @@ -80,59 +72,6 @@ rng_gen_seed(uint8_t* dest, size_t size) { #endif } -static void -isaac_init(randctx *rctx, char *env_seed, - uint8_t* user_seed, size_t seed_len) { - memset(rctx, 0, sizeof(randctx)); - - if (user_seed != NULL) { - // ignore bytes after the required length - if (seed_len > sizeof(rctx->randrsl)) { - seed_len = sizeof(rctx->randrsl); - } - memcpy(&rctx->randrsl, user_seed, seed_len); - } else if (env_seed != NULL) { - ub4 seed = (ub4) atoi(env_seed); - for (size_t i = 0; i < RANDSIZ; i ++) { - memcpy(&rctx->randrsl[i], &seed, sizeof(ub4)); - seed = (seed + 0x7ed55d16) + (seed << 12); - } - } else { - rng_gen_seed((uint8_t*)&rctx->randrsl, - sizeof(rctx->randrsl)); - } - - randinit(rctx, 1); -} - -void -rng_init(rust_rng* rng, char* env_seed, - uint8_t *user_seed, size_t seed_len) { - isaac_init(&rng->rctx, env_seed, user_seed, seed_len); - rng->reseedable = !user_seed && !env_seed; -} - -static void -rng_maybe_reseed(rust_rng* rng) { - // If this RNG has generated more than 32KB of random data and was not - // seeded by the user or RUST_SEED, then we should reseed now. - const size_t RESEED_THRESHOLD = 32 * 1024; - size_t bytes_generated = rng->rctx.randc * sizeof(ub4); - if (bytes_generated < RESEED_THRESHOLD || !rng->reseedable) { - return; - } - rng_gen_seed((uint8_t*)rng->rctx.randrsl, - sizeof(rng->rctx.randrsl)); - randinit(&rng->rctx, 1); -} - -uint32_t -rng_gen_u32(rust_rng* rng) { - uint32_t x = isaac_rand(&rng->rctx); - rng_maybe_reseed(rng); - return x; -} - // // Local Variables: // mode: C++ diff --git a/src/rt/rust_rng.h b/src/rt/rust_rng.h index a13b5acd0ef..08335a6f73f 100644 --- a/src/rt/rust_rng.h +++ b/src/rt/rust_rng.h @@ -11,22 +11,7 @@ #ifndef RUST_RNG_H #define RUST_RNG_H -#include "rand.h" - -class rust_kernel; - -// Initialization helpers for ISAAC RNG - -struct rust_rng { - randctx rctx; - bool reseedable; -}; - -size_t rng_seed_size(); void rng_gen_seed(uint8_t* dest, size_t size); -void rng_init(rust_rng *rng, char *env_seed, - uint8_t *user_seed, size_t seed_len); -uint32_t rng_gen_u32(rust_rng *rng); // // Local Variables: diff --git a/src/rt/rustrt.def.in b/src/rt/rustrt.def.in index 7a9149187d8..186fb387eea 100644 --- a/src/rt/rustrt.def.in +++ b/src/rt/rustrt.def.in @@ -9,11 +9,7 @@ rust_localtime rust_timegm rust_mktime precise_time_ns -rand_free -rand_new_seeded -rand_seed_size rand_gen_seed -rand_next rust_path_is_dir rust_path_exists rust_get_stdin 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 @@ 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); } 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 {