auto merge of #9362 : huonw/rust/rand, r=alexcrichton
First steps on toward a shiny new `std::rand`, this does a variety of relatively clean-up tasks, like: - moving `std/rand.rs` to `std/rand/mod.rs` in preparation for (e.g.) splitting the large chunk that is the `Isaac` implementation into a separate file later. - removing the now unused RNG code in the old rt (500 lines gone just like that!) - merging Rng and RngUtil via default methods - examples in the documentation for almost all methods. And other things mentioned in the commit messages.
This commit is contained in:
commit
5f6a8ae966
1
mk/rt.mk
1
mk/rt.mk
|
@ -74,7 +74,6 @@ RUNTIME_CXXS_$(1)_$(2) := \
|
||||||
rt/rust_rng.cpp \
|
rt/rust_rng.cpp \
|
||||||
rt/rust_upcall.cpp \
|
rt/rust_upcall.cpp \
|
||||||
rt/rust_uv.cpp \
|
rt/rust_uv.cpp \
|
||||||
rt/isaac/randport.cpp \
|
|
||||||
rt/miniz.cpp \
|
rt/miniz.cpp \
|
||||||
rt/memory_region.cpp \
|
rt/memory_region.cpp \
|
||||||
rt/boxed_region.cpp \
|
rt/boxed_region.cpp \
|
||||||
|
|
|
@ -311,11 +311,11 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_base64_random() {
|
fn test_base64_random() {
|
||||||
use std::rand::{task_rng, random, RngUtil};
|
use std::rand::{task_rng, random, Rng};
|
||||||
use std::vec;
|
use std::vec;
|
||||||
|
|
||||||
do 1000.times {
|
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>());
|
let v = vec::from_fn(times, |_| random::<u8>());
|
||||||
assert_eq!(v.to_base64(STANDARD).from_base64().unwrap(), v);
|
assert_eq!(v.to_base64(STANDARD).from_base64().unwrap(), v);
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,7 +43,7 @@ pub trait Deque<T> : Mutable {
|
||||||
mod bench {
|
mod bench {
|
||||||
use std::container::MutableMap;
|
use std::container::MutableMap;
|
||||||
use std::{vec, rand};
|
use std::{vec, rand};
|
||||||
use std::rand::RngUtil;
|
use std::rand::Rng;
|
||||||
use test::BenchHarness;
|
use test::BenchHarness;
|
||||||
|
|
||||||
pub fn insert_rand_n<M:MutableMap<uint,uint>>(n: uint,
|
pub fn insert_rand_n<M:MutableMap<uint,uint>>(n: uint,
|
||||||
|
|
|
@ -347,8 +347,7 @@ impl <T: FixedBuffer> StandardPadding for T {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use std::rand::IsaacRng;
|
use std::rand::{IsaacRng, Rng};
|
||||||
use std::rand::RngUtil;
|
|
||||||
use std::vec;
|
use std::vec;
|
||||||
|
|
||||||
use cryptoutil::{add_bytes_to_bits, add_bytes_to_bits_tuple};
|
use cryptoutil::{add_bytes_to_bits, add_bytes_to_bits_tuple};
|
||||||
|
@ -365,7 +364,7 @@ mod test {
|
||||||
digest.reset();
|
digest.reset();
|
||||||
|
|
||||||
while count < total_size {
|
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 remaining = total_size - count;
|
||||||
let size = if next > remaining { remaining } else { next };
|
let size = if next > remaining { remaining } else { next };
|
||||||
digest.input(buffer.slice_to(size));
|
digest.input(buffer.slice_to(size));
|
||||||
|
|
|
@ -106,15 +106,15 @@ pub fn inflate_bytes_zlib(bytes: &[u8]) -> ~[u8] {
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use std::rand;
|
use std::rand;
|
||||||
use std::rand::RngUtil;
|
use std::rand::Rng;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_flate_round_trip() {
|
fn test_flate_round_trip() {
|
||||||
let mut r = rand::rng();
|
let mut r = rand::rng();
|
||||||
let mut words = ~[];
|
let mut words = ~[];
|
||||||
do 20.times {
|
do 20.times {
|
||||||
let range = r.gen_uint_range(1, 10);
|
let range = r.gen_integer_range(1u, 10);
|
||||||
words.push(r.gen_bytes(range));
|
words.push(r.gen_vec::<u8>(range));
|
||||||
}
|
}
|
||||||
do 20.times {
|
do 20.times {
|
||||||
let mut input = ~[];
|
let mut input = ~[];
|
||||||
|
|
|
@ -23,7 +23,7 @@ use std::cmp::{Eq, Ord, TotalEq, TotalOrd, Ordering, Less, Equal, Greater};
|
||||||
use std::int;
|
use std::int;
|
||||||
use std::num;
|
use std::num;
|
||||||
use std::num::{IntConvertible, Zero, One, ToStrRadix, FromStrRadix, Orderable};
|
use std::num::{IntConvertible, Zero, One, ToStrRadix, FromStrRadix, Orderable};
|
||||||
use std::rand::{Rng, RngUtil};
|
use std::rand::Rng;
|
||||||
use std::str;
|
use std::str;
|
||||||
use std::uint;
|
use std::uint;
|
||||||
use std::vec;
|
use std::vec;
|
||||||
|
|
|
@ -909,7 +909,7 @@ mod tests {
|
||||||
mod test_tim_sort {
|
mod test_tim_sort {
|
||||||
|
|
||||||
use sort::tim_sort;
|
use sort::tim_sort;
|
||||||
use std::rand::RngUtil;
|
use std::rand::Rng;
|
||||||
use std::rand;
|
use std::rand;
|
||||||
use std::vec;
|
use std::vec;
|
||||||
|
|
||||||
|
@ -1008,7 +1008,7 @@ mod big_tests {
|
||||||
|
|
||||||
use sort::*;
|
use sort::*;
|
||||||
|
|
||||||
use std::rand::RngUtil;
|
use std::rand::Rng;
|
||||||
use std::rand;
|
use std::rand;
|
||||||
use std::vec;
|
use std::vec;
|
||||||
|
|
||||||
|
@ -1069,8 +1069,8 @@ mod big_tests {
|
||||||
isSorted(arr);
|
isSorted(arr);
|
||||||
|
|
||||||
do 3.times {
|
do 3.times {
|
||||||
let i1 = rng.gen_uint_range(0, n);
|
let i1 = rng.gen_integer_range(0u, n);
|
||||||
let i2 = rng.gen_uint_range(0, n);
|
let i2 = rng.gen_integer_range(0u, n);
|
||||||
arr.swap(i1, i2);
|
arr.swap(i1, i2);
|
||||||
}
|
}
|
||||||
tim_sort(arr); // 3sort
|
tim_sort(arr); // 3sort
|
||||||
|
@ -1088,7 +1088,7 @@ mod big_tests {
|
||||||
isSorted(arr);
|
isSorted(arr);
|
||||||
|
|
||||||
do (n/100).times {
|
do (n/100).times {
|
||||||
let idx = rng.gen_uint_range(0, n);
|
let idx = rng.gen_integer_range(0u, n);
|
||||||
arr[idx] = rng.gen();
|
arr[idx] = rng.gen();
|
||||||
}
|
}
|
||||||
tim_sort(arr);
|
tim_sort(arr);
|
||||||
|
@ -1141,8 +1141,8 @@ mod big_tests {
|
||||||
isSorted(arr);
|
isSorted(arr);
|
||||||
|
|
||||||
do 3.times {
|
do 3.times {
|
||||||
let i1 = rng.gen_uint_range(0, n);
|
let i1 = rng.gen_integer_range(0u, n);
|
||||||
let i2 = rng.gen_uint_range(0, n);
|
let i2 = rng.gen_integer_range(0u, n);
|
||||||
arr.swap(i1, i2);
|
arr.swap(i1, i2);
|
||||||
}
|
}
|
||||||
tim_sort(arr); // 3sort
|
tim_sort(arr); // 3sort
|
||||||
|
@ -1160,7 +1160,7 @@ mod big_tests {
|
||||||
isSorted(arr);
|
isSorted(arr);
|
||||||
|
|
||||||
do (n/100).times {
|
do (n/100).times {
|
||||||
let idx = rng.gen_uint_range(0, n);
|
let idx = rng.gen_integer_range(0u, n);
|
||||||
arr[idx] = @rng.gen();
|
arr[idx] = @rng.gen();
|
||||||
}
|
}
|
||||||
tim_sort(arr);
|
tim_sort(arr);
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
|
|
||||||
|
|
||||||
use std::os;
|
use std::os;
|
||||||
use std::rand::RngUtil;
|
use std::rand::Rng;
|
||||||
use std::rand;
|
use std::rand;
|
||||||
|
|
||||||
/// Attempts to make a temporary directory inside of `tmpdir` whose name will
|
/// 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> {
|
pub fn mkdtemp(tmpdir: &Path, suffix: &str) -> Option<Path> {
|
||||||
let mut r = rand::rng();
|
let mut r = rand::rng();
|
||||||
for _ in range(0u, 1000) {
|
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
|
if os::make_dir(&p, 0x1c0) { // 700
|
||||||
return Some(p);
|
return Some(p);
|
||||||
}
|
}
|
||||||
|
|
|
@ -874,7 +874,7 @@ mod test_treemap {
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
use std::rand::RngUtil;
|
use std::rand::Rng;
|
||||||
use std::rand;
|
use std::rand;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -1028,7 +1028,7 @@ mod test_treemap {
|
||||||
}
|
}
|
||||||
|
|
||||||
do 30.times {
|
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);
|
let (key, _) = ctrl.remove(r);
|
||||||
assert!(map.remove(&key));
|
assert!(map.remove(&key));
|
||||||
check_structure(&map);
|
check_structure(&map);
|
||||||
|
|
|
@ -62,7 +62,7 @@ use std::char::Char;
|
||||||
use std::container::Container;
|
use std::container::Container;
|
||||||
use std::to_str::ToStr;
|
use std::to_str::ToStr;
|
||||||
use std::rand;
|
use std::rand;
|
||||||
use std::rand::RngUtil;
|
use std::rand::Rng;
|
||||||
use std::cmp::Eq;
|
use std::cmp::Eq;
|
||||||
use std::cast::{transmute,transmute_copy};
|
use std::cast::{transmute,transmute_copy};
|
||||||
|
|
||||||
|
@ -170,7 +170,7 @@ impl Uuid {
|
||||||
/// of random numbers. Use the rand::Rand trait to supply
|
/// of random numbers. Use the rand::Rand trait to supply
|
||||||
/// a custom generator if required.
|
/// a custom generator if required.
|
||||||
pub fn new_v4() -> Uuid {
|
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] };
|
let mut uuid = Uuid{ bytes: [0, .. 16] };
|
||||||
vec::bytes::copy_memory(uuid.bytes, ub, 16);
|
vec::bytes::copy_memory(uuid.bytes, ub, 16);
|
||||||
uuid.set_variant(VariantRFC4122);
|
uuid.set_variant(VariantRFC4122);
|
||||||
|
@ -488,7 +488,7 @@ impl TotalEq for Uuid {
|
||||||
impl rand::Rand for Uuid {
|
impl rand::Rand for Uuid {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn rand<R: rand::Rng>(rng: &mut R) -> Uuid {
|
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] };
|
let mut uuid = Uuid{ bytes: [0, .. 16] };
|
||||||
vec::bytes::copy_memory(uuid.bytes, ub, 16);
|
vec::bytes::copy_memory(uuid.bytes, ub, 16);
|
||||||
uuid.set_variant(VariantRFC4122);
|
uuid.set_variant(VariantRFC4122);
|
||||||
|
|
|
@ -24,7 +24,7 @@ use iter::{Iterator, FromIterator, Extendable};
|
||||||
use iter::{FilterMap, Chain, Repeat, Zip};
|
use iter::{FilterMap, Chain, Repeat, Zip};
|
||||||
use num;
|
use num;
|
||||||
use option::{None, Option, Some};
|
use option::{None, Option, Some};
|
||||||
use rand::RngUtil;
|
use rand::Rng;
|
||||||
use rand;
|
use rand;
|
||||||
use uint;
|
use uint;
|
||||||
use util::replace;
|
use util::replace;
|
||||||
|
|
|
@ -734,7 +734,7 @@ mod test {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod bench {
|
mod bench {
|
||||||
use extra::test::BenchHarness;
|
use extra::test::BenchHarness;
|
||||||
use rand::{XorShiftRng,RngUtil};
|
use rand::{XorShiftRng, Rng};
|
||||||
use float;
|
use float;
|
||||||
use to_str::ToStr;
|
use to_str::ToStr;
|
||||||
|
|
||||||
|
|
|
@ -1718,7 +1718,7 @@ mod tests {
|
||||||
use os::{remove_file, setenv, unsetenv};
|
use os::{remove_file, setenv, unsetenv};
|
||||||
use os;
|
use os;
|
||||||
use path::Path;
|
use path::Path;
|
||||||
use rand::RngUtil;
|
use rand::Rng;
|
||||||
use rand;
|
use rand;
|
||||||
use run;
|
use run;
|
||||||
use str::StrSlice;
|
use str::StrSlice;
|
||||||
|
@ -1738,7 +1738,7 @@ mod tests {
|
||||||
|
|
||||||
fn make_rand_name() -> ~str {
|
fn make_rand_name() -> ~str {
|
||||||
let mut rng = rand::rng();
|
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());
|
assert!(getenv(n).is_none());
|
||||||
n
|
n
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
/*!
|
/*!
|
||||||
Random number generation.
|
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
|
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
|
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>()`.
|
suffice, but sometimes an annotation is required, e.g. `rand::random::<float>()`.
|
||||||
|
@ -23,7 +23,7 @@ distributions like normal and exponential.
|
||||||
|
|
||||||
~~~ {.rust}
|
~~~ {.rust}
|
||||||
use std::rand;
|
use std::rand;
|
||||||
use std::rand::RngUtil;
|
use std::rand::Rng;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut rng = rand::rng();
|
let mut rng = rand::rng();
|
||||||
|
@ -44,22 +44,20 @@ fn main () {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use cast;
|
use cast;
|
||||||
use clone::Clone;
|
|
||||||
use cmp;
|
use cmp;
|
||||||
use container::Container;
|
use container::Container;
|
||||||
use int;
|
use int;
|
||||||
use iter::{Iterator, range, range_step};
|
use iter::{Iterator, range, range_step};
|
||||||
use local_data;
|
use local_data;
|
||||||
use num;
|
|
||||||
use prelude::*;
|
use prelude::*;
|
||||||
use str;
|
use str;
|
||||||
use sys;
|
use sys;
|
||||||
use u32;
|
use u32;
|
||||||
|
use u64;
|
||||||
use uint;
|
use uint;
|
||||||
use vec;
|
use vec;
|
||||||
use libc::size_t;
|
use libc::size_t;
|
||||||
|
|
||||||
#[path="rand/distributions.rs"]
|
|
||||||
pub mod distributions;
|
pub mod distributions;
|
||||||
|
|
||||||
/// A type that can be randomly generated using an Rng
|
/// A type that can be randomly generated using an Rng
|
||||||
|
@ -244,17 +242,10 @@ pub mod rustrt {
|
||||||
use libc::size_t;
|
use libc::size_t;
|
||||||
|
|
||||||
extern {
|
extern {
|
||||||
pub fn rand_seed_size() -> size_t;
|
|
||||||
pub fn rand_gen_seed(buf: *mut u8, sz: 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
|
/// A value with a particular weight compared to other values
|
||||||
pub struct Weighted<T> {
|
pub struct Weighted<T> {
|
||||||
/// The numerical weight of this item
|
/// The numerical weight of this item
|
||||||
|
@ -263,311 +254,187 @@ pub struct Weighted<T> {
|
||||||
item: T,
|
item: T,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Helper functions attached to the Rng type
|
/// A random number generator
|
||||||
pub trait RngUtil {
|
pub trait Rng {
|
||||||
/// Return a random value of a Rand type
|
/// Return the next random integer
|
||||||
fn gen<T:Rand>(&mut self) -> T;
|
fn next(&mut self) -> u32;
|
||||||
/**
|
|
||||||
* 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]);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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
|
/// Return a random value of a Rand type.
|
||||||
impl<R: Rng> RngUtil for R {
|
///
|
||||||
/// Return a random value for a Rand type
|
/// # Example
|
||||||
#[inline]
|
///
|
||||||
|
/// ~~~ {.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 {
|
fn gen<T: Rand>(&mut self) -> T {
|
||||||
Rand::rand(self)
|
Rand::rand(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// Return a random vector of the specified length.
|
||||||
* Return an int randomly chosen from the range [start, end),
|
///
|
||||||
* failing if start >= end
|
/// # Example
|
||||||
*/
|
///
|
||||||
fn gen_int_range(&mut self, start: int, end: int) -> int {
|
/// ~~~ {.rust}
|
||||||
assert!(start < end);
|
/// use std::rand;
|
||||||
start + num::abs(self.gen::<int>() % (end - start))
|
///
|
||||||
|
/// 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())
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// Generate a random primitive integer in the range [`low`,
|
||||||
* Return a uint randomly chosen from the range [start, end),
|
/// `high`). Fails if `low >= high`.
|
||||||
* failing if start >= end
|
///
|
||||||
*/
|
/// This gives a uniform distribution (assuming this RNG is itself
|
||||||
fn gen_uint_range(&mut self, start: uint, end: uint) -> uint {
|
/// uniform), even for edge cases like `gen_integer_range(0u8,
|
||||||
assert!(start < end);
|
/// 170)`, which a naive modulo operation would return numbers
|
||||||
start + (self.gen::<uint>() % (end - start))
|
/// less than 85 with double the probability to those greater than
|
||||||
}
|
/// 85.
|
||||||
|
///
|
||||||
/**
|
/// # Example
|
||||||
* Return a char randomly chosen from chars, failing if chars is empty
|
///
|
||||||
*/
|
/// ~~~ {.rust}
|
||||||
fn gen_char_from(&mut self, chars: &str) -> char {
|
/// use std::rand;
|
||||||
assert!(!chars.is_empty());
|
///
|
||||||
let mut cs = ~[];
|
/// fn main() {
|
||||||
for c in chars.iter() { cs.push(c) }
|
/// let rng = rand::task_rng();
|
||||||
self.choose(cs)
|
/// let n: uint = rng.gen_integer_range(0u, 10);
|
||||||
}
|
/// printfln!(n);
|
||||||
|
/// let m: i16 = rng.gen_integer_range(-40, 400);
|
||||||
/// Return a bool with a 1-in-n chance of true
|
/// printfln!(m);
|
||||||
fn gen_weighted_bool(&mut self, n: uint) -> bool {
|
/// }
|
||||||
if n == 0u {
|
/// ~~~
|
||||||
true
|
fn gen_integer_range<T: Rand + Int>(&mut self, low: T, high: T) -> T {
|
||||||
} else {
|
assert!(low < high, "RNG.gen_integer_range called with low >= high");
|
||||||
self.gen_uint_range(1u, n + 1u) == 1u
|
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 bool with a 1 in n chance of true
|
||||||
* Return a random string of the specified length composed of A-Z,a-z,0-9
|
///
|
||||||
*/
|
/// # Example
|
||||||
fn gen_str(&mut self, len: uint) -> ~str {
|
///
|
||||||
let charset = ~"ABCDEFGHIJKLMNOPQRSTUVWXYZ\
|
/// ~~~ {.rust}
|
||||||
abcdefghijklmnopqrstuvwxyz\
|
/// use std::rand;
|
||||||
0123456789";
|
/// use std::rand::Rng;
|
||||||
let mut s = ~"";
|
///
|
||||||
let mut i = 0u;
|
/// fn main() {
|
||||||
while (i < len) {
|
/// let mut rng = rand::rng();
|
||||||
s = s + str::from_char(self.gen_char_from(charset));
|
/// printfln!("%b", rng.gen_weighted_bool(3));
|
||||||
i += 1u;
|
/// }
|
||||||
|
/// ~~~
|
||||||
|
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
|
s
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return a random byte string of the specified length
|
/// Choose an item randomly, failing if `values` is empty.
|
||||||
fn gen_bytes(&mut self, len: uint) -> ~[u8] {
|
fn choose<T: Clone>(&mut self, values: &[T]) -> T {
|
||||||
do vec::from_fn(len) |_i| {
|
self.choose_option(values).expect("Rng.choose: `values` is empty").clone()
|
||||||
self.gen()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Choose an item randomly, failing if values is empty
|
/// Choose `Some(&item)` randomly, returning `None` if values is
|
||||||
fn choose<T:Clone>(&mut self, values: &[T]) -> T {
|
/// empty.
|
||||||
self.choose_option(values).unwrap()
|
///
|
||||||
}
|
/// # Example
|
||||||
|
///
|
||||||
/// Choose Some(item) randomly, returning None if values is empty
|
/// ~~~ {.rust}
|
||||||
fn choose_option<T:Clone>(&mut self, values: &[T]) -> Option<T> {
|
/// 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() {
|
if values.is_empty() {
|
||||||
None
|
None
|
||||||
} else {
|
} 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
|
/// Choose an item respecting the relative weights, failing if the sum of
|
||||||
* the weights is 0
|
/// 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 {
|
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
|
||||||
* Choose Some(item) respecting the relative weights, returning none if
|
/// the sum of the weights is 0
|
||||||
* 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>])
|
fn choose_weighted_option<T:Clone>(&mut self, v: &[Weighted<T>])
|
||||||
-> Option<T> {
|
-> Option<T> {
|
||||||
let mut total = 0u;
|
let mut total = 0u;
|
||||||
|
@ -577,7 +444,7 @@ impl<R: Rng> RngUtil for R {
|
||||||
if total == 0u {
|
if total == 0u {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let chosen = self.gen_uint_range(0u, total);
|
let chosen = self.gen_integer_range(0u, total);
|
||||||
let mut so_far = 0u;
|
let mut so_far = 0u;
|
||||||
for item in v.iter() {
|
for item in v.iter() {
|
||||||
so_far += item.weight;
|
so_far += item.weight;
|
||||||
|
@ -588,10 +455,23 @@ impl<R: Rng> RngUtil for R {
|
||||||
unreachable!();
|
unreachable!();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// Return a vec containing copies of the items, in order, where
|
||||||
* Return a vec containing copies of the items, in order, where
|
/// the weight of the item determines how many copies there are
|
||||||
* 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] {
|
fn weighted_vec<T:Clone>(&mut self, v: &[Weighted<T>]) -> ~[T] {
|
||||||
let mut r = ~[];
|
let mut r = ~[];
|
||||||
for item in v.iter() {
|
for item in v.iter() {
|
||||||
|
@ -603,24 +483,61 @@ impl<R: Rng> RngUtil for R {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Shuffle a vec
|
/// Shuffle a vec
|
||||||
fn shuffle<T:Clone>(&mut self, values: &[T]) -> ~[T] {
|
///
|
||||||
let mut m = values.to_owned();
|
/// # Example
|
||||||
self.shuffle_mut(m);
|
///
|
||||||
m
|
/// ~~~ {.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]) {
|
fn shuffle_mut<T>(&mut self, values: &mut [T]) {
|
||||||
let mut i = values.len();
|
let mut i = values.len();
|
||||||
while i >= 2u {
|
while i >= 2u {
|
||||||
// invariant: elements with index >= i have been locked in place.
|
// invariant: elements with index >= i have been locked in place.
|
||||||
i -= 1u;
|
i -= 1u;
|
||||||
// lock element i in place.
|
// 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] {
|
fn sample<A, T: Iterator<A>>(&mut self, iter: T, n: uint) -> ~[A] {
|
||||||
let mut reservoir : ~[A] = vec::with_capacity(n);
|
let mut reservoir : ~[A] = vec::with_capacity(n);
|
||||||
for (i, elem) in iter.enumerate() {
|
for (i, elem) in iter.enumerate() {
|
||||||
|
@ -629,7 +546,7 @@ impl<R: Rng> RngUtil for R {
|
||||||
loop
|
loop
|
||||||
}
|
}
|
||||||
|
|
||||||
let k = self.gen_uint_range(0, i + 1);
|
let k = self.gen_integer_range(0, i + 1);
|
||||||
if k < reservoir.len() {
|
if k < reservoir.len() {
|
||||||
reservoir[k] = elem
|
reservoir[k] = elem
|
||||||
}
|
}
|
||||||
|
@ -904,8 +821,8 @@ pub fn seed() -> ~[u8] {
|
||||||
#[fixed_stack_segment]; #[inline(never)];
|
#[fixed_stack_segment]; #[inline(never)];
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let n = rustrt::rand_seed_size() as uint;
|
let n = RAND_SIZE * 4;
|
||||||
let mut s = vec::from_elem(n, 0_u8);
|
let mut s = vec::from_elem(n as uint, 0_u8);
|
||||||
do s.as_mut_buf |p, sz| {
|
do s.as_mut_buf |p, sz| {
|
||||||
rustrt::rand_gen_seed(p, sz as size_t)
|
rustrt::rand_gen_seed(p, sz as size_t)
|
||||||
}
|
}
|
||||||
|
@ -962,7 +879,7 @@ mod test {
|
||||||
let seed = seed();
|
let seed = seed();
|
||||||
let mut ra = IsaacRng::new_seeded(seed);
|
let mut ra = IsaacRng::new_seeded(seed);
|
||||||
let mut rb = 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]
|
#[test]
|
||||||
|
@ -971,7 +888,7 @@ mod test {
|
||||||
let seed = [2u8, 32u8, 4u8, 32u8, 51u8];
|
let seed = [2u8, 32u8, 4u8, 32u8, 51u8];
|
||||||
let mut ra = IsaacRng::new_seeded(seed);
|
let mut ra = IsaacRng::new_seeded(seed);
|
||||||
let mut rb = 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]
|
#[test]
|
||||||
|
@ -986,35 +903,36 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_gen_int_range() {
|
fn test_gen_integer_range() {
|
||||||
let mut r = rng();
|
let mut r = rng();
|
||||||
let a = r.gen_int_range(-3, 42);
|
for _ in range(0, 1000) {
|
||||||
assert!(a >= -3 && a < 42);
|
let a = r.gen_integer_range(-3i, 42);
|
||||||
assert_eq!(r.gen_int_range(0, 1), 0);
|
assert!(a >= -3 && a < 42);
|
||||||
assert_eq!(r.gen_int_range(-12, -11), -12);
|
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]
|
#[test]
|
||||||
#[should_fail]
|
#[should_fail]
|
||||||
fn test_gen_int_from_fail() {
|
fn test_gen_integer_range_fail_int() {
|
||||||
let mut r = rng();
|
let mut r = rng();
|
||||||
r.gen_int_range(5, -2);
|
r.gen_integer_range(5i, -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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[should_fail]
|
#[should_fail]
|
||||||
fn test_gen_uint_range_fail() {
|
fn test_gen_integer_range_fail_uint() {
|
||||||
let mut r = rng();
|
let mut r = rng();
|
||||||
r.gen_uint_range(5u, 2u);
|
r.gen_integer_range(5u, 2u);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -1033,22 +951,22 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_gen_str() {
|
fn test_gen_ascii_str() {
|
||||||
let mut r = rng();
|
let mut r = rng();
|
||||||
debug!(r.gen_str(10u));
|
debug!(r.gen_ascii_str(10u));
|
||||||
debug!(r.gen_str(10u));
|
debug!(r.gen_ascii_str(10u));
|
||||||
debug!(r.gen_str(10u));
|
debug!(r.gen_ascii_str(10u));
|
||||||
assert_eq!(r.gen_str(0u).len(), 0u);
|
assert_eq!(r.gen_ascii_str(0u).len(), 0u);
|
||||||
assert_eq!(r.gen_str(10u).len(), 10u);
|
assert_eq!(r.gen_ascii_str(10u).len(), 10u);
|
||||||
assert_eq!(r.gen_str(16u).len(), 16u);
|
assert_eq!(r.gen_ascii_str(16u).len(), 16u);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_gen_bytes() {
|
fn test_gen_vec() {
|
||||||
let mut r = rng();
|
let mut r = rng();
|
||||||
assert_eq!(r.gen_bytes(0u).len(), 0u);
|
assert_eq!(r.gen_vec::<u8>(0u).len(), 0u);
|
||||||
assert_eq!(r.gen_bytes(10u).len(), 10u);
|
assert_eq!(r.gen_vec::<u8>(10u).len(), 10u);
|
||||||
assert_eq!(r.gen_bytes(16u).len(), 16u);
|
assert_eq!(r.gen_vec::<f64>(16u).len(), 16u);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -1060,9 +978,12 @@ mod test {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_choose_option() {
|
fn test_choose_option() {
|
||||||
let mut r = rng();
|
let mut r = rng();
|
||||||
let x: Option<int> = r.choose_option([]);
|
let v: &[int] = &[];
|
||||||
assert!(x.is_none());
|
assert!(r.choose_option(v).is_none());
|
||||||
assert_eq!(r.choose_option([1, 1, 1]), Some(1));
|
|
||||||
|
let i = 1;
|
||||||
|
let v = [1,1,1];
|
||||||
|
assert_eq!(r.choose_option(v), Some(&i));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -1107,16 +1028,16 @@ mod test {
|
||||||
fn test_shuffle() {
|
fn test_shuffle() {
|
||||||
let mut r = rng();
|
let mut r = rng();
|
||||||
let empty: ~[int] = ~[];
|
let empty: ~[int] = ~[];
|
||||||
assert_eq!(r.shuffle([]), empty);
|
assert_eq!(r.shuffle(~[]), empty);
|
||||||
assert_eq!(r.shuffle([1, 1, 1]), ~[1, 1, 1]);
|
assert_eq!(r.shuffle(~[1, 1, 1]), ~[1, 1, 1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_task_rng() {
|
fn test_task_rng() {
|
||||||
let mut r = task_rng();
|
let mut r = task_rng();
|
||||||
r.gen::<int>();
|
r.gen::<int>();
|
||||||
assert_eq!(r.shuffle([1, 1, 1]), ~[1, 1, 1]);
|
assert_eq!(r.shuffle(~[1, 1, 1]), ~[1, 1, 1]);
|
||||||
assert_eq!(r.gen_uint_range(0u, 1u), 0u);
|
assert_eq!(r.gen_integer_range(0u, 1u), 0u);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -1131,46 +1052,6 @@ mod test {
|
||||||
(f32, (f64, (float,)))) = random();
|
(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]
|
#[test]
|
||||||
fn test_sample() {
|
fn test_sample() {
|
||||||
let MIN_VAL = 1;
|
let MIN_VAL = 1;
|
|
@ -1095,7 +1095,7 @@ mod test {
|
||||||
#[test]
|
#[test]
|
||||||
fn megapipe_stress() {
|
fn megapipe_stress() {
|
||||||
use rand;
|
use rand;
|
||||||
use rand::RngUtil;
|
use rand::Rng;
|
||||||
|
|
||||||
if util::limit_thread_creation_due_to_osx_and_valgrind() { return; }
|
if util::limit_thread_creation_due_to_osx_and_valgrind() { return; }
|
||||||
|
|
||||||
|
@ -1106,7 +1106,7 @@ mod test {
|
||||||
let total = stress_factor() + 10;
|
let total = stress_factor() + 10;
|
||||||
let mut rng = rand::rng();
|
let mut rng = rand::rng();
|
||||||
do total.times {
|
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 pipe_clone = pipe.clone();
|
||||||
let end_chan_clone = end_chan.clone();
|
let end_chan_clone = end_chan.clone();
|
||||||
do spawntask_random {
|
do spawntask_random {
|
||||||
|
|
|
@ -26,7 +26,7 @@ use rt::local::Local;
|
||||||
use rt::rtio::{RemoteCallback, PausibleIdleCallback};
|
use rt::rtio::{RemoteCallback, PausibleIdleCallback};
|
||||||
use borrow::{to_uint};
|
use borrow::{to_uint};
|
||||||
use cell::Cell;
|
use cell::Cell;
|
||||||
use rand::{XorShiftRng, RngUtil};
|
use rand::{XorShiftRng, Rng};
|
||||||
use iter::range;
|
use iter::range;
|
||||||
use vec::{OwnedVector};
|
use vec::{OwnedVector};
|
||||||
|
|
||||||
|
@ -391,7 +391,7 @@ impl Scheduler {
|
||||||
fn try_steals(&mut self) -> Option<~Task> {
|
fn try_steals(&mut self) -> Option<~Task> {
|
||||||
let work_queues = &mut self.work_queues;
|
let work_queues = &mut self.work_queues;
|
||||||
let len = work_queues.len();
|
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) {
|
for index in range(0, len).map(|i| (i + start_index) % len) {
|
||||||
match work_queues[index].steal() {
|
match work_queues[index].steal() {
|
||||||
Some(task) => {
|
Some(task) => {
|
||||||
|
|
|
@ -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<<RANDSIZL)
|
|
||||||
|
|
||||||
/* context of random number generator */
|
|
||||||
struct randctx
|
|
||||||
{
|
|
||||||
ub4 randcnt;
|
|
||||||
ub4 randrsl[RANDSIZ];
|
|
||||||
ub4 randmem[RANDSIZ];
|
|
||||||
ub4 randa;
|
|
||||||
ub4 randb;
|
|
||||||
ub4 randc;
|
|
||||||
};
|
|
||||||
typedef struct randctx randctx;
|
|
||||||
|
|
||||||
/*
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
If (flag==TRUE), then use the contents of randrsl[0..RANDSIZ-1] as the seed.
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
*/
|
|
||||||
void randinit(randctx *r, word flag);
|
|
||||||
|
|
||||||
void isaac(randctx *r);
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Call isaac_rand(/o_ randctx *r _o/) to retrieve a single 32-bit random value
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
*/
|
|
||||||
#define isaac_rand(r) \
|
|
||||||
(!(r)->randcnt-- ? \
|
|
||||||
(isaac(r), (r)->randcnt=RANDSIZ-1, (r)->randrsl[(r)->randcnt]) : \
|
|
||||||
(r)->randrsl[(r)->randcnt])
|
|
||||||
|
|
||||||
#endif /* RAND */
|
|
|
@ -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<mend; )
|
|
||||||
{
|
|
||||||
rngstep( a<<13, a, b, mm, m, m2, r, x);
|
|
||||||
rngstep( (a & 0xffffffff) >>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<mend; )
|
|
||||||
{
|
|
||||||
rngstep( a<<13, a, b, mm, m, m2, r, x);
|
|
||||||
rngstep( (a & 0xffffffff) >>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; i<RANDSIZ; i+=8)
|
|
||||||
{
|
|
||||||
a+=r[i ]; b+=r[i+1];
|
|
||||||
c+=r[i+2]; d+=r[i+3];
|
|
||||||
e+=r[i+4]; f+=r[i+5];
|
|
||||||
g+=r[i+6]; h+=r[i+7];
|
|
||||||
mix(a,b,c,d,e,f,g,h);
|
|
||||||
m[i ]=a; m[i+1]=b; m[i+2]=c; m[i+3]=d;
|
|
||||||
m[i+4]=e; m[i+5]=f; m[i+6]=g; m[i+7]=h;
|
|
||||||
}
|
|
||||||
/* do a second pass to make all of the seed affect all of m */
|
|
||||||
for (i=0; i<RANDSIZ; i+=8)
|
|
||||||
{
|
|
||||||
a+=m[i ]; b+=m[i+1];
|
|
||||||
c+=m[i+2]; d+=m[i+3];
|
|
||||||
e+=m[i+4]; f+=m[i+5];
|
|
||||||
g+=m[i+6]; h+=m[i+7];
|
|
||||||
mix(a,b,c,d,e,f,g,h);
|
|
||||||
m[i ]=a; m[i+1]=b; m[i+2]=c; m[i+3]=d;
|
|
||||||
m[i+4]=e; m[i+5]=f; m[i+6]=g; m[i+7]=h;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (i=0; i<RANDSIZ; i+=8)
|
|
||||||
{
|
|
||||||
/* fill in mm[] with messy stuff */
|
|
||||||
mix(a,b,c,d,e,f,g,h);
|
|
||||||
m[i ]=a; m[i+1]=b; m[i+2]=c; m[i+3]=d;
|
|
||||||
m[i+4]=e; m[i+5]=f; m[i+6]=g; m[i+7]=h;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
isaac(ctx); /* fill in the first set of results */
|
|
||||||
ctx->randcnt=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
|
|
|
@ -1,50 +0,0 @@
|
||||||
/*
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Standard definitions and types, Bob Jenkins
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
*/
|
|
||||||
#ifndef STANDARD
|
|
||||||
# define STANDARD
|
|
||||||
# ifndef STDIO
|
|
||||||
# include <stdio.h>
|
|
||||||
# define STDIO
|
|
||||||
# endif
|
|
||||||
# ifndef STDDEF
|
|
||||||
# include <stddef.h>
|
|
||||||
# define STDDEF
|
|
||||||
# endif
|
|
||||||
# ifndef STDINT
|
|
||||||
# include <stdint.h>
|
|
||||||
# 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 */
|
|
|
@ -69,35 +69,11 @@ rust_env_pairs() {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern "C" CDECL size_t
|
|
||||||
rand_seed_size() {
|
|
||||||
return rng_seed_size();
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" CDECL void
|
extern "C" CDECL void
|
||||||
rand_gen_seed(uint8_t* dest, size_t size) {
|
rand_gen_seed(uint8_t* dest, size_t size) {
|
||||||
rng_gen_seed(dest, 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*
|
extern "C" CDECL char*
|
||||||
#if defined(__WIN32__)
|
#if defined(__WIN32__)
|
||||||
rust_list_dir_val(WIN32_FIND_DATA* entry_ptr) {
|
rust_list_dir_val(WIN32_FIND_DATA* entry_ptr) {
|
||||||
|
|
|
@ -32,14 +32,6 @@ win32_require(LPCTSTR fn, BOOL ok) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
size_t
|
|
||||||
rng_seed_size() {
|
|
||||||
randctx rctx;
|
|
||||||
return sizeof(rctx.randrsl);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialization helpers for ISAAC RNG
|
|
||||||
|
|
||||||
void
|
void
|
||||||
rng_gen_seed(uint8_t* dest, size_t size) {
|
rng_gen_seed(uint8_t* dest, size_t size) {
|
||||||
#ifdef __WIN32__
|
#ifdef __WIN32__
|
||||||
|
@ -80,59 +72,6 @@ rng_gen_seed(uint8_t* dest, size_t size) {
|
||||||
#endif
|
#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:
|
// Local Variables:
|
||||||
// mode: C++
|
// mode: C++
|
||||||
|
|
|
@ -11,22 +11,7 @@
|
||||||
#ifndef RUST_RNG_H
|
#ifndef RUST_RNG_H
|
||||||
#define 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_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:
|
// Local Variables:
|
||||||
|
|
|
@ -9,11 +9,7 @@ rust_localtime
|
||||||
rust_timegm
|
rust_timegm
|
||||||
rust_mktime
|
rust_mktime
|
||||||
precise_time_ns
|
precise_time_ns
|
||||||
rand_free
|
|
||||||
rand_new_seeded
|
|
||||||
rand_seed_size
|
|
||||||
rand_gen_seed
|
rand_gen_seed
|
||||||
rand_next
|
|
||||||
rust_path_is_dir
|
rust_path_is_dir
|
||||||
rust_path_exists
|
rust_path_exists
|
||||||
rust_get_stdin
|
rust_get_stdin
|
||||||
|
|
|
@ -15,7 +15,7 @@ extern mod extra;
|
||||||
use extra::time::precise_time_s;
|
use extra::time::precise_time_s;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::os;
|
use std::os;
|
||||||
use std::rand::RngUtil;
|
use std::rand::Rng;
|
||||||
use std::rand;
|
use std::rand;
|
||||||
use std::str;
|
use std::str;
|
||||||
use std::util;
|
use std::util;
|
||||||
|
@ -85,7 +85,7 @@ fn vec_plus() {
|
||||||
let mut v = ~[];
|
let mut v = ~[];
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
while i < 1500 {
|
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() {
|
if r.gen() {
|
||||||
v.push_all_move(rv);
|
v.push_all_move(rv);
|
||||||
} else {
|
} else {
|
||||||
|
@ -101,7 +101,7 @@ fn vec_append() {
|
||||||
let mut v = ~[];
|
let mut v = ~[];
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
while i < 1500 {
|
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() {
|
if r.gen() {
|
||||||
v = vec::append(v, rv);
|
v = vec::append(v, rv);
|
||||||
}
|
}
|
||||||
|
@ -117,7 +117,7 @@ fn vec_push_all() {
|
||||||
|
|
||||||
let mut v = ~[];
|
let mut v = ~[];
|
||||||
for i in range(0u, 1500) {
|
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() {
|
if r.gen() {
|
||||||
v.push_all(rv);
|
v.push_all(rv);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// Perlin noise benchmark from https://gist.github.com/1170424
|
// Perlin noise benchmark from https://gist.github.com/1170424
|
||||||
|
|
||||||
use std::float;
|
use std::float;
|
||||||
use std::rand::{Rng, RngUtil};
|
use std::rand::Rng;
|
||||||
use std::rand;
|
use std::rand;
|
||||||
|
|
||||||
struct Vec2 {
|
struct Vec2 {
|
||||||
|
|
Loading…
Reference in New Issue