2012-12-03 18:48:01 -06:00
|
|
|
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
|
|
|
|
// file at the top-level directory of this distribution and at
|
|
|
|
// http://rust-lang.org/COPYRIGHT.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
|
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
|
|
// option. This file may not be copied, modified, or distributed
|
|
|
|
// except according to those terms.
|
|
|
|
|
2013-04-24 07:29:19 -05:00
|
|
|
/*!
|
|
|
|
Random number generation.
|
|
|
|
|
|
|
|
The key functions are `random()` and `RngUtil::gen()`. These are polymorphic
|
|
|
|
and so can be used to generate any type that implements `Rand`. Type inference
|
|
|
|
means that often a simple call to `rand::random()` or `rng.gen()` will
|
|
|
|
suffice, but sometimes an annotation is required, e.g. `rand::random::<float>()`.
|
|
|
|
|
2013-04-28 09:18:53 -05:00
|
|
|
See the `distributions` submodule for sampling random numbers from
|
|
|
|
distributions like normal and exponential.
|
|
|
|
|
2013-04-24 07:29:19 -05:00
|
|
|
# Examples
|
2013-05-27 08:49:54 -05:00
|
|
|
|
|
|
|
~~~ {.rust}
|
2013-07-10 08:30:14 -05:00
|
|
|
use std::rand;
|
|
|
|
use std::rand::RngUtil;
|
2013-04-24 07:29:19 -05:00
|
|
|
|
|
|
|
fn main() {
|
2013-05-17 13:23:53 -05:00
|
|
|
let mut rng = rand::rng();
|
2013-04-24 07:29:19 -05:00
|
|
|
if rng.gen() { // bool
|
2013-07-22 11:03:39 -05:00
|
|
|
printfln!("int: %d, uint: %u", rng.gen(), rng.gen())
|
2013-04-24 07:29:19 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
~~~
|
|
|
|
|
2013-05-27 08:49:54 -05:00
|
|
|
~~~ {.rust}
|
2013-07-10 08:30:14 -05:00
|
|
|
use std::rand;
|
|
|
|
|
2013-04-24 07:29:19 -05:00
|
|
|
fn main () {
|
|
|
|
let tuple_ptr = rand::random::<~(f64, char)>();
|
2013-07-22 11:03:39 -05:00
|
|
|
printfln!(tuple_ptr)
|
2013-04-24 07:29:19 -05:00
|
|
|
}
|
|
|
|
~~~
|
|
|
|
*/
|
|
|
|
|
2013-05-24 21:35:29 -05:00
|
|
|
use cast;
|
2013-07-02 14:47:32 -05:00
|
|
|
use clone::Clone;
|
2013-05-24 21:35:29 -05:00
|
|
|
use cmp;
|
2013-06-18 11:39:16 -05:00
|
|
|
use container::Container;
|
2012-12-23 16:41:37 -06:00
|
|
|
use int;
|
2013-06-08 07:04:46 -05:00
|
|
|
use iterator::IteratorUtil;
|
2013-05-24 21:35:29 -05:00
|
|
|
use local_data;
|
Replaces the free-standing functions in f32, &c.
The free-standing functions in f32, f64, i8, i16, i32, i64, u8, u16,
u32, u64, float, int, and uint are replaced with generic functions in
num instead.
If you were previously using any of those functions, just replace them
with the corresponding function with the same name in num.
Note: If you were using a function that corresponds to an operator, use
the operator instead.
2013-07-08 11:05:17 -05:00
|
|
|
use num;
|
2013-01-08 21:37:25 -06:00
|
|
|
use prelude::*;
|
2012-12-23 16:41:37 -06:00
|
|
|
use str;
|
2013-05-24 21:35:29 -05:00
|
|
|
use sys;
|
2012-12-23 16:41:37 -06:00
|
|
|
use u32;
|
|
|
|
use uint;
|
|
|
|
use util;
|
|
|
|
use vec;
|
2013-02-19 09:06:20 -06:00
|
|
|
use libc::size_t;
|
2012-12-23 16:41:37 -06:00
|
|
|
|
2013-04-28 09:18:53 -05:00
|
|
|
#[path="rand/distributions.rs"]
|
|
|
|
pub mod distributions;
|
|
|
|
|
2013-04-24 07:29:19 -05:00
|
|
|
/// A type that can be randomly generated using an Rng
|
2013-02-05 06:56:40 -06:00
|
|
|
pub trait Rand {
|
2013-05-28 16:35:52 -05:00
|
|
|
/// Generates a random instance of this type using the specified source of
|
|
|
|
/// randomness
|
2013-05-03 01:09:50 -05:00
|
|
|
fn rand<R: Rng>(rng: &mut R) -> Self;
|
2013-02-05 06:56:40 -06:00
|
|
|
}
|
|
|
|
|
2013-02-14 13:47:00 -06:00
|
|
|
impl Rand for int {
|
2013-04-26 08:53:29 -05:00
|
|
|
#[inline]
|
2013-05-03 01:09:50 -05:00
|
|
|
fn rand<R: Rng>(rng: &mut R) -> int {
|
2013-04-24 07:29:19 -05:00
|
|
|
if int::bits == 32 {
|
|
|
|
rng.next() as int
|
|
|
|
} else {
|
|
|
|
rng.gen::<i64>() as int
|
|
|
|
}
|
2013-02-05 06:56:40 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-02-14 13:47:00 -06:00
|
|
|
impl Rand for i8 {
|
2013-04-26 08:53:29 -05:00
|
|
|
#[inline]
|
2013-05-03 01:09:50 -05:00
|
|
|
fn rand<R: Rng>(rng: &mut R) -> i8 {
|
2013-04-24 07:29:19 -05:00
|
|
|
rng.next() as i8
|
2013-02-05 06:56:40 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-02-14 13:47:00 -06:00
|
|
|
impl Rand for i16 {
|
2013-04-26 08:53:29 -05:00
|
|
|
#[inline]
|
2013-05-03 01:09:50 -05:00
|
|
|
fn rand<R: Rng>(rng: &mut R) -> i16 {
|
2013-04-24 07:29:19 -05:00
|
|
|
rng.next() as i16
|
2013-02-05 06:56:40 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-02-14 13:47:00 -06:00
|
|
|
impl Rand for i32 {
|
2013-04-26 08:53:29 -05:00
|
|
|
#[inline]
|
2013-05-03 01:09:50 -05:00
|
|
|
fn rand<R: Rng>(rng: &mut R) -> i32 {
|
2013-04-24 07:29:19 -05:00
|
|
|
rng.next() as i32
|
2013-02-05 06:56:40 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-02-14 13:47:00 -06:00
|
|
|
impl Rand for i64 {
|
2013-04-26 08:53:29 -05:00
|
|
|
#[inline]
|
2013-05-03 01:09:50 -05:00
|
|
|
fn rand<R: Rng>(rng: &mut R) -> i64 {
|
2013-04-24 07:29:19 -05:00
|
|
|
(rng.next() as i64 << 32) | rng.next() as i64
|
2013-02-05 06:56:40 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-04-21 07:09:33 -05:00
|
|
|
impl Rand for uint {
|
2013-04-26 08:53:29 -05:00
|
|
|
#[inline]
|
2013-05-03 01:09:50 -05:00
|
|
|
fn rand<R: Rng>(rng: &mut R) -> uint {
|
2013-04-24 07:29:19 -05:00
|
|
|
if uint::bits == 32 {
|
|
|
|
rng.next() as uint
|
|
|
|
} else {
|
|
|
|
rng.gen::<u64>() as uint
|
|
|
|
}
|
2013-04-21 07:09:33 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-02-14 13:47:00 -06:00
|
|
|
impl Rand for u8 {
|
2013-04-26 08:53:29 -05:00
|
|
|
#[inline]
|
2013-05-03 01:09:50 -05:00
|
|
|
fn rand<R: Rng>(rng: &mut R) -> u8 {
|
2013-04-24 07:29:19 -05:00
|
|
|
rng.next() as u8
|
2013-02-05 06:56:40 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-02-14 13:47:00 -06:00
|
|
|
impl Rand for u16 {
|
2013-04-26 08:53:29 -05:00
|
|
|
#[inline]
|
2013-05-03 01:09:50 -05:00
|
|
|
fn rand<R: Rng>(rng: &mut R) -> u16 {
|
2013-04-24 07:29:19 -05:00
|
|
|
rng.next() as u16
|
2013-02-05 06:56:40 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-02-14 13:47:00 -06:00
|
|
|
impl Rand for u32 {
|
2013-04-26 08:53:29 -05:00
|
|
|
#[inline]
|
2013-05-03 01:09:50 -05:00
|
|
|
fn rand<R: Rng>(rng: &mut R) -> u32 {
|
2013-04-24 07:29:19 -05:00
|
|
|
rng.next()
|
2013-02-05 06:56:40 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-02-14 13:47:00 -06:00
|
|
|
impl Rand for u64 {
|
2013-04-26 08:53:29 -05:00
|
|
|
#[inline]
|
2013-05-03 01:09:50 -05:00
|
|
|
fn rand<R: Rng>(rng: &mut R) -> u64 {
|
2013-04-24 07:29:19 -05:00
|
|
|
(rng.next() as u64 << 32) | rng.next() as u64
|
2013-02-05 06:56:40 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-02-14 13:47:00 -06:00
|
|
|
impl Rand for float {
|
2013-04-26 08:53:29 -05:00
|
|
|
#[inline]
|
2013-05-03 01:09:50 -05:00
|
|
|
fn rand<R: Rng>(rng: &mut R) -> float {
|
2013-04-24 07:29:19 -05:00
|
|
|
rng.gen::<f64>() as float
|
2013-02-05 06:56:40 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-02-14 13:47:00 -06:00
|
|
|
impl Rand for f32 {
|
2013-04-26 08:53:29 -05:00
|
|
|
#[inline]
|
2013-05-03 01:09:50 -05:00
|
|
|
fn rand<R: Rng>(rng: &mut R) -> f32 {
|
2013-04-24 07:29:19 -05:00
|
|
|
rng.gen::<f64>() as f32
|
2013-02-05 06:56:40 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-30 22:51:13 -05:00
|
|
|
static SCALE : f64 = (u32::max_value as f64) + 1.0f64;
|
2013-02-14 13:47:00 -06:00
|
|
|
impl Rand for f64 {
|
2013-04-26 08:53:29 -05:00
|
|
|
#[inline]
|
2013-05-03 01:09:50 -05:00
|
|
|
fn rand<R: Rng>(rng: &mut R) -> f64 {
|
2013-04-24 07:29:19 -05:00
|
|
|
let u1 = rng.next() as f64;
|
|
|
|
let u2 = rng.next() as f64;
|
|
|
|
let u3 = rng.next() as f64;
|
|
|
|
|
2013-06-30 22:51:13 -05:00
|
|
|
((u1 / SCALE + u2) / SCALE + u3) / SCALE
|
2013-02-05 06:56:40 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-02-14 13:47:00 -06:00
|
|
|
impl Rand for char {
|
2013-04-26 08:53:29 -05:00
|
|
|
#[inline]
|
2013-05-03 01:09:50 -05:00
|
|
|
fn rand<R: Rng>(rng: &mut R) -> char {
|
2013-04-24 07:29:19 -05:00
|
|
|
rng.next() as char
|
2013-02-05 06:56:40 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-02-14 13:47:00 -06:00
|
|
|
impl Rand for bool {
|
2013-04-26 08:53:29 -05:00
|
|
|
#[inline]
|
2013-05-03 01:09:50 -05:00
|
|
|
fn rand<R: Rng>(rng: &mut R) -> bool {
|
2013-04-24 07:29:19 -05:00
|
|
|
rng.next() & 1u32 == 1u32
|
2013-02-05 06:56:40 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-04-22 04:01:48 -05:00
|
|
|
macro_rules! tuple_impl {
|
|
|
|
// use variables to indicate the arity of the tuple
|
|
|
|
($($tyvar:ident),* ) => {
|
|
|
|
// the trailing commas are for the 1 tuple
|
|
|
|
impl<
|
|
|
|
$( $tyvar : Rand ),*
|
|
|
|
> Rand for ( $( $tyvar ),* , ) {
|
|
|
|
|
2013-04-26 08:53:29 -05:00
|
|
|
#[inline]
|
2013-05-03 01:09:50 -05:00
|
|
|
fn rand<R: Rng>(_rng: &mut R) -> ( $( $tyvar ),* , ) {
|
2013-04-22 04:01:48 -05:00
|
|
|
(
|
2013-04-23 09:00:43 -05:00
|
|
|
// use the $tyvar's to get the appropriate number of
|
|
|
|
// repeats (they're not actually needed)
|
2013-04-22 04:01:48 -05:00
|
|
|
$(
|
|
|
|
_rng.gen::<$tyvar>()
|
|
|
|
),*
|
|
|
|
,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-04-26 08:53:29 -05:00
|
|
|
impl Rand for () {
|
|
|
|
#[inline]
|
2013-05-03 01:09:50 -05:00
|
|
|
fn rand<R: Rng>(_: &mut R) -> () { () }
|
2013-04-26 08:53:29 -05:00
|
|
|
}
|
2013-04-22 04:01:48 -05:00
|
|
|
tuple_impl!{A}
|
|
|
|
tuple_impl!{A, B}
|
|
|
|
tuple_impl!{A, B, C}
|
|
|
|
tuple_impl!{A, B, C, D}
|
|
|
|
tuple_impl!{A, B, C, D, E}
|
|
|
|
tuple_impl!{A, B, C, D, E, F}
|
|
|
|
tuple_impl!{A, B, C, D, E, F, G}
|
|
|
|
tuple_impl!{A, B, C, D, E, F, G, H}
|
|
|
|
tuple_impl!{A, B, C, D, E, F, G, H, I}
|
|
|
|
tuple_impl!{A, B, C, D, E, F, G, H, I, J}
|
|
|
|
|
2013-02-20 19:07:17 -06:00
|
|
|
impl<T:Rand> Rand for Option<T> {
|
2013-04-26 08:53:29 -05:00
|
|
|
#[inline]
|
2013-05-03 01:09:50 -05:00
|
|
|
fn rand<R: Rng>(rng: &mut R) -> Option<T> {
|
2013-04-24 07:29:19 -05:00
|
|
|
if rng.gen() {
|
2013-04-23 09:00:43 -05:00
|
|
|
Some(rng.gen())
|
2013-03-12 15:00:50 -05:00
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
2013-02-05 06:56:40 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-04-22 04:01:48 -05:00
|
|
|
impl<T: Rand> Rand for ~T {
|
2013-04-26 08:53:29 -05:00
|
|
|
#[inline]
|
2013-05-03 01:09:50 -05:00
|
|
|
fn rand<R: Rng>(rng: &mut R) -> ~T { ~rng.gen() }
|
2013-04-22 04:01:48 -05:00
|
|
|
}
|
|
|
|
|
2013-07-18 19:12:46 -05:00
|
|
|
impl<T: Rand + 'static> Rand for @T {
|
2013-04-26 08:53:29 -05:00
|
|
|
#[inline]
|
2013-05-03 01:09:50 -05:00
|
|
|
fn rand<R: Rng>(rng: &mut R) -> @T { @rng.gen() }
|
2013-04-22 04:01:48 -05:00
|
|
|
}
|
|
|
|
|
2011-11-16 22:49:38 -06:00
|
|
|
#[abi = "cdecl"]
|
2013-03-05 13:57:50 -06:00
|
|
|
pub mod rustrt {
|
|
|
|
use libc::size_t;
|
|
|
|
|
2013-07-18 21:08:57 -05:00
|
|
|
extern {
|
|
|
|
pub unsafe fn rand_seed_size() -> size_t;
|
|
|
|
pub unsafe fn rand_gen_seed(buf: *mut u8, sz: size_t);
|
2013-03-05 13:57:50 -06:00
|
|
|
}
|
2010-07-25 23:45:09 -05:00
|
|
|
}
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/// A random number generator
|
2012-09-26 18:01:40 -05:00
|
|
|
pub trait Rng {
|
2012-07-04 16:53:12 -05:00
|
|
|
/// Return the next random integer
|
2013-05-03 01:09:50 -05:00
|
|
|
pub fn next(&mut self) -> u32;
|
2012-05-17 13:52:49 -05:00
|
|
|
}
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/// A value with a particular weight compared to other values
|
2013-01-22 10:12:52 -06:00
|
|
|
pub struct Weighted<T> {
|
2013-05-28 16:35:52 -05:00
|
|
|
/// The numerical weight of this item
|
2013-01-22 10:12:52 -06:00
|
|
|
weight: uint,
|
2013-05-28 16:35:52 -05:00
|
|
|
/// The actual item which is being weighted
|
2013-01-22 10:12:52 -06:00
|
|
|
item: T,
|
|
|
|
}
|
2013-04-24 07:29:19 -05:00
|
|
|
|
2013-05-28 16:35:52 -05:00
|
|
|
/// Helper functions attached to the Rng type
|
2013-03-12 15:00:50 -05:00
|
|
|
pub trait RngUtil {
|
2013-04-23 09:00:43 -05:00
|
|
|
/// Return a random value of a Rand type
|
2013-05-03 01:09:50 -05:00
|
|
|
fn gen<T:Rand>(&mut self) -> T;
|
2013-04-10 14:08:19 -05:00
|
|
|
/**
|
2013-04-24 07:29:19 -05:00
|
|
|
* Return a int randomly chosen from the range [start, end),
|
|
|
|
* failing if start >= end
|
2013-04-10 14:08:19 -05:00
|
|
|
*/
|
2013-05-03 01:09:50 -05:00
|
|
|
fn gen_int_range(&mut self, start: int, end: int) -> int;
|
2013-03-12 15:00:50 -05:00
|
|
|
/**
|
|
|
|
* Return a uint randomly chosen from the range [start, end),
|
|
|
|
* failing if start >= end
|
|
|
|
*/
|
2013-05-03 01:09:50 -05:00
|
|
|
fn gen_uint_range(&mut self, start: uint, end: uint) -> uint;
|
2013-03-12 15:00:50 -05:00
|
|
|
/**
|
|
|
|
* Return a char randomly chosen from chars, failing if chars is empty
|
|
|
|
*/
|
2013-05-03 01:09:50 -05:00
|
|
|
fn gen_char_from(&mut self, chars: &str) -> char;
|
2013-04-10 14:08:19 -05:00
|
|
|
/**
|
|
|
|
* Return a bool with a 1 in n chance of true
|
|
|
|
*
|
2013-05-27 08:49:54 -05:00
|
|
|
* # Example
|
2013-04-10 14:08:19 -05:00
|
|
|
*
|
2013-05-27 08:49:54 -05:00
|
|
|
* ~~~ {.rust}
|
2013-04-10 14:08:19 -05:00
|
|
|
*
|
2013-07-10 08:30:14 -05:00
|
|
|
* use std::rand;
|
|
|
|
* use std::rand::RngUtil;
|
2013-04-10 14:08:19 -05:00
|
|
|
*
|
|
|
|
* fn main() {
|
2013-07-10 08:30:14 -05:00
|
|
|
* let mut rng = rand::rng();
|
2013-07-22 11:03:39 -05:00
|
|
|
* printfln!("%b", rng.gen_weighted_bool(3));
|
2013-04-10 14:08:19 -05:00
|
|
|
* }
|
|
|
|
* ~~~
|
|
|
|
*/
|
2013-05-03 01:09:50 -05:00
|
|
|
fn gen_weighted_bool(&mut self, n: uint) -> bool;
|
2013-03-12 15:00:50 -05:00
|
|
|
/**
|
|
|
|
* Return a random string of the specified length composed of A-Z,a-z,0-9
|
2013-04-10 14:08:19 -05:00
|
|
|
*
|
2013-05-27 08:49:54 -05:00
|
|
|
* # Example
|
2013-04-10 14:08:19 -05:00
|
|
|
*
|
2013-05-27 08:49:54 -05:00
|
|
|
* ~~~ {.rust}
|
2013-04-10 14:08:19 -05:00
|
|
|
*
|
2013-07-10 08:30:14 -05:00
|
|
|
* use std::rand;
|
|
|
|
* use std::rand::RngUtil;
|
2013-04-10 14:08:19 -05:00
|
|
|
*
|
|
|
|
* fn main() {
|
2013-07-10 08:30:14 -05:00
|
|
|
* let mut rng = rand::rng();
|
2013-04-11 08:12:26 -05:00
|
|
|
* println(rng.gen_str(8));
|
2013-04-10 14:08:19 -05:00
|
|
|
* }
|
|
|
|
* ~~~
|
2013-03-12 15:00:50 -05:00
|
|
|
*/
|
2013-05-03 01:09:50 -05:00
|
|
|
fn gen_str(&mut self, len: uint) -> ~str;
|
2013-04-10 14:08:19 -05:00
|
|
|
/**
|
|
|
|
* Return a random byte string of the specified length
|
|
|
|
*
|
2013-05-27 08:49:54 -05:00
|
|
|
* # Example
|
2013-04-10 14:08:19 -05:00
|
|
|
*
|
2013-05-27 08:49:54 -05:00
|
|
|
* ~~~ {.rust}
|
2013-04-10 14:08:19 -05:00
|
|
|
*
|
2013-07-10 08:30:14 -05:00
|
|
|
* use std::rand;
|
|
|
|
* use std::rand::RngUtil;
|
2013-04-10 14:08:19 -05:00
|
|
|
*
|
|
|
|
* fn main() {
|
2013-07-10 08:30:14 -05:00
|
|
|
* let mut rng = rand::rng();
|
2013-07-22 11:03:39 -05:00
|
|
|
* printfln!(rng.gen_bytes(8));
|
2013-04-10 14:08:19 -05:00
|
|
|
* }
|
|
|
|
* ~~~
|
|
|
|
*/
|
2013-05-03 01:09:50 -05:00
|
|
|
fn gen_bytes(&mut self, len: uint) -> ~[u8];
|
2013-04-10 14:08:19 -05:00
|
|
|
/**
|
|
|
|
* Choose an item randomly, failing if values is empty
|
|
|
|
*
|
2013-05-27 08:49:54 -05:00
|
|
|
* # Example
|
2013-04-10 14:08:19 -05:00
|
|
|
*
|
2013-05-27 08:49:54 -05:00
|
|
|
* ~~~ {.rust}
|
2013-04-10 14:08:19 -05:00
|
|
|
*
|
2013-07-10 08:30:14 -05:00
|
|
|
* use std::rand;
|
|
|
|
* use std::rand::RngUtil;
|
2013-04-10 14:08:19 -05:00
|
|
|
*
|
|
|
|
* fn main() {
|
2013-07-10 08:30:14 -05:00
|
|
|
* let mut rng = rand::rng();
|
2013-07-22 11:03:39 -05:00
|
|
|
* printfln!("%d", rng.choose([1,2,4,8,16,32]));
|
2013-04-10 14:08:19 -05:00
|
|
|
* }
|
|
|
|
* ~~~
|
|
|
|
*/
|
2013-07-10 16:43:25 -05:00
|
|
|
fn choose<T:Clone>(&mut self, values: &[T]) -> T;
|
2013-03-12 15:00:50 -05:00
|
|
|
/// Choose Some(item) randomly, returning None if values is empty
|
2013-07-02 14:47:32 -05:00
|
|
|
fn choose_option<T:Clone>(&mut self, values: &[T]) -> Option<T>;
|
2013-03-12 15:00:50 -05:00
|
|
|
/**
|
|
|
|
* Choose an item respecting the relative weights, failing if the sum of
|
|
|
|
* the weights is 0
|
2013-04-10 14:08:19 -05:00
|
|
|
*
|
2013-05-27 08:49:54 -05:00
|
|
|
* # Example
|
2013-04-10 14:08:19 -05:00
|
|
|
*
|
2013-05-27 08:49:54 -05:00
|
|
|
* ~~~ {.rust}
|
2013-04-10 14:08:19 -05:00
|
|
|
*
|
2013-07-10 08:30:14 -05:00
|
|
|
* use std::rand;
|
|
|
|
* use std::rand::RngUtil;
|
2013-04-10 14:08:19 -05:00
|
|
|
*
|
|
|
|
* fn main() {
|
2013-07-10 08:30:14 -05:00
|
|
|
* let mut rng = rand::rng();
|
2013-04-11 08:12:26 -05:00
|
|
|
* let x = [rand::Weighted {weight: 4, item: 'a'},
|
|
|
|
* rand::Weighted {weight: 2, item: 'b'},
|
|
|
|
* rand::Weighted {weight: 2, item: 'c'}];
|
2013-07-22 11:03:39 -05:00
|
|
|
* printfln!("%c", rng.choose_weighted(x));
|
2013-04-10 14:08:19 -05:00
|
|
|
* }
|
|
|
|
* ~~~
|
2013-03-12 15:00:50 -05:00
|
|
|
*/
|
2013-07-10 16:43:25 -05:00
|
|
|
fn choose_weighted<T:Clone>(&mut self, v : &[Weighted<T>]) -> T;
|
2013-03-12 15:00:50 -05:00
|
|
|
/**
|
|
|
|
* Choose Some(item) respecting the relative weights, returning none if
|
|
|
|
* the sum of the weights is 0
|
2013-04-10 14:08:19 -05:00
|
|
|
*
|
2013-05-27 08:49:54 -05:00
|
|
|
* # Example
|
2013-04-10 14:08:19 -05:00
|
|
|
*
|
2013-05-27 08:49:54 -05:00
|
|
|
* ~~~ {.rust}
|
2013-04-10 14:08:19 -05:00
|
|
|
*
|
2013-07-10 08:30:14 -05:00
|
|
|
* use std::rand;
|
|
|
|
* use std::rand::RngUtil;
|
2013-04-10 14:08:19 -05:00
|
|
|
*
|
|
|
|
* fn main() {
|
2013-07-10 08:30:14 -05:00
|
|
|
* let mut rng = rand::rng();
|
2013-04-11 08:12:26 -05:00
|
|
|
* let x = [rand::Weighted {weight: 4, item: 'a'},
|
|
|
|
* rand::Weighted {weight: 2, item: 'b'},
|
|
|
|
* rand::Weighted {weight: 2, item: 'c'}];
|
2013-07-22 11:03:39 -05:00
|
|
|
* printfln!(rng.choose_weighted_option(x));
|
2013-04-10 14:08:19 -05:00
|
|
|
* }
|
|
|
|
* ~~~
|
2013-03-12 15:00:50 -05:00
|
|
|
*/
|
2013-07-02 14:47:32 -05:00
|
|
|
fn choose_weighted_option<T:Clone>(&mut self, v: &[Weighted<T>])
|
2013-05-03 01:09:50 -05:00
|
|
|
-> Option<T>;
|
2013-03-12 15:00:50 -05:00
|
|
|
/**
|
|
|
|
* Return a vec containing copies of the items, in order, where
|
|
|
|
* the weight of the item determines how many copies there are
|
2013-04-10 14:08:19 -05:00
|
|
|
*
|
2013-05-27 08:49:54 -05:00
|
|
|
* # Example
|
2013-04-10 14:08:19 -05:00
|
|
|
*
|
2013-05-27 08:49:54 -05:00
|
|
|
* ~~~ {.rust}
|
2013-04-10 14:08:19 -05:00
|
|
|
*
|
2013-07-10 08:30:14 -05:00
|
|
|
* use std::rand;
|
|
|
|
* use std::rand::RngUtil;
|
2013-04-10 14:08:19 -05:00
|
|
|
*
|
|
|
|
* fn main() {
|
2013-07-10 08:30:14 -05:00
|
|
|
* let mut rng = rand::rng();
|
2013-04-11 08:12:26 -05:00
|
|
|
* let x = [rand::Weighted {weight: 4, item: 'a'},
|
|
|
|
* rand::Weighted {weight: 2, item: 'b'},
|
|
|
|
* rand::Weighted {weight: 2, item: 'c'}];
|
2013-07-22 11:03:39 -05:00
|
|
|
* printfln!(rng.weighted_vec(x));
|
2013-04-10 14:08:19 -05:00
|
|
|
* }
|
|
|
|
* ~~~
|
2013-03-12 15:00:50 -05:00
|
|
|
*/
|
2013-07-02 14:47:32 -05:00
|
|
|
fn weighted_vec<T:Clone>(&mut self, v: &[Weighted<T>]) -> ~[T];
|
2013-04-10 14:08:19 -05:00
|
|
|
/**
|
|
|
|
* Shuffle a vec
|
|
|
|
*
|
2013-05-27 08:49:54 -05:00
|
|
|
* # Example
|
2013-04-10 14:08:19 -05:00
|
|
|
*
|
2013-05-27 08:49:54 -05:00
|
|
|
* ~~~ {.rust}
|
2013-04-10 14:08:19 -05:00
|
|
|
*
|
2013-07-10 08:30:14 -05:00
|
|
|
* use std::rand;
|
|
|
|
* use std::rand::RngUtil;
|
2013-04-10 14:08:19 -05:00
|
|
|
*
|
|
|
|
* fn main() {
|
2013-07-10 08:30:14 -05:00
|
|
|
* let mut rng = rand::rng();
|
2013-07-22 11:03:39 -05:00
|
|
|
* printfln!(rng.shuffle([1,2,3]));
|
2013-04-10 14:08:19 -05:00
|
|
|
* }
|
|
|
|
* ~~~
|
|
|
|
*/
|
2013-07-10 16:43:25 -05:00
|
|
|
fn shuffle<T:Clone>(&mut self, values: &[T]) -> ~[T];
|
2013-04-10 14:08:19 -05:00
|
|
|
/**
|
|
|
|
* Shuffle a mutable vec in place
|
|
|
|
*
|
2013-05-27 08:49:54 -05:00
|
|
|
* # Example
|
2013-04-10 14:08:19 -05:00
|
|
|
*
|
2013-05-27 08:49:54 -05:00
|
|
|
* ~~~ {.rust}
|
2013-04-10 14:08:19 -05:00
|
|
|
*
|
2013-07-10 08:30:14 -05:00
|
|
|
* use std::rand;
|
|
|
|
* use std::rand::RngUtil;
|
2013-04-10 14:08:19 -05:00
|
|
|
*
|
|
|
|
* fn main() {
|
2013-07-10 08:30:14 -05:00
|
|
|
* let mut rng = rand::rng();
|
2013-04-10 14:08:19 -05:00
|
|
|
* let mut y = [1,2,3];
|
|
|
|
* rng.shuffle_mut(y);
|
2013-07-22 11:03:39 -05:00
|
|
|
* printfln!(y);
|
2013-04-10 14:08:19 -05:00
|
|
|
* rng.shuffle_mut(y);
|
2013-07-22 11:03:39 -05:00
|
|
|
* printfln!(y);
|
2013-04-10 14:08:19 -05:00
|
|
|
* }
|
|
|
|
* ~~~
|
|
|
|
*/
|
2013-05-03 01:09:50 -05:00
|
|
|
fn shuffle_mut<T>(&mut self, values: &mut [T]);
|
2013-03-12 15:00:50 -05:00
|
|
|
}
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/// Extension methods for random number generators
|
2013-04-23 09:00:43 -05:00
|
|
|
impl<R: Rng> RngUtil for R {
|
2013-02-05 06:56:40 -06:00
|
|
|
/// Return a random value for a Rand type
|
2013-06-18 16:45:18 -05:00
|
|
|
#[inline]
|
2013-05-03 01:09:50 -05:00
|
|
|
fn gen<T: Rand>(&mut self) -> T {
|
2013-04-23 09:00:43 -05:00
|
|
|
Rand::rand(self)
|
2013-02-05 06:56:40 -06:00
|
|
|
}
|
2011-10-26 18:24:31 -05:00
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/**
|
|
|
|
* Return an int randomly chosen from the range [start, end),
|
|
|
|
* failing if start >= end
|
|
|
|
*/
|
2013-05-03 01:09:50 -05:00
|
|
|
fn gen_int_range(&mut self, start: int, end: int) -> int {
|
2013-03-28 20:39:09 -05:00
|
|
|
assert!(start < end);
|
Replaces the free-standing functions in f32, &c.
The free-standing functions in f32, f64, i8, i16, i32, i64, u8, u16,
u32, u64, float, int, and uint are replaced with generic functions in
num instead.
If you were previously using any of those functions, just replace them
with the corresponding function with the same name in num.
Note: If you were using a function that corresponds to an operator, use
the operator instead.
2013-07-08 11:05:17 -05:00
|
|
|
start + num::abs(self.gen::<int>() % (end - start))
|
2012-05-19 13:25:45 -05:00
|
|
|
}
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/**
|
|
|
|
* Return a uint randomly chosen from the range [start, end),
|
|
|
|
* failing if start >= end
|
|
|
|
*/
|
2013-05-03 01:09:50 -05:00
|
|
|
fn gen_uint_range(&mut self, start: uint, end: uint) -> uint {
|
2013-03-28 20:39:09 -05:00
|
|
|
assert!(start < end);
|
2013-04-24 07:29:19 -05:00
|
|
|
start + (self.gen::<uint>() % (end - start))
|
2012-05-19 13:25:45 -05:00
|
|
|
}
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/**
|
|
|
|
* Return a char randomly chosen from chars, failing if chars is empty
|
|
|
|
*/
|
2013-05-03 01:09:50 -05:00
|
|
|
fn gen_char_from(&mut self, chars: &str) -> char {
|
2013-03-28 20:39:09 -05:00
|
|
|
assert!(!chars.is_empty());
|
2013-03-24 01:51:18 -05:00
|
|
|
let mut cs = ~[];
|
2013-06-08 07:04:46 -05:00
|
|
|
for chars.iter().advance |c| { cs.push(c) }
|
2013-03-24 01:51:18 -05:00
|
|
|
self.choose(cs)
|
2012-05-19 13:25:45 -05:00
|
|
|
}
|
|
|
|
|
2013-04-10 14:54:28 -05:00
|
|
|
/// Return a bool with a 1-in-n chance of true
|
2013-05-03 01:09:50 -05:00
|
|
|
fn gen_weighted_bool(&mut self, n: uint) -> bool {
|
2012-05-19 13:25:45 -05:00
|
|
|
if n == 0u {
|
|
|
|
true
|
|
|
|
} else {
|
2012-05-21 20:57:28 -05:00
|
|
|
self.gen_uint_range(1u, n + 1u) == 1u
|
2012-05-19 13:25:45 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/**
|
|
|
|
* Return a random string of the specified length composed of A-Z,a-z,0-9
|
|
|
|
*/
|
2013-05-03 01:09:50 -05:00
|
|
|
fn gen_str(&mut self, len: uint) -> ~str {
|
2012-07-14 00:57:48 -05:00
|
|
|
let charset = ~"ABCDEFGHIJKLMNOPQRSTUVWXYZ\
|
2012-07-06 13:35:46 -05:00
|
|
|
abcdefghijklmnopqrstuvwxyz\
|
|
|
|
0123456789";
|
2012-07-14 00:57:48 -05:00
|
|
|
let mut s = ~"";
|
2012-05-17 13:52:49 -05:00
|
|
|
let mut i = 0u;
|
|
|
|
while (i < len) {
|
2012-05-19 13:25:45 -05:00
|
|
|
s = s + str::from_char(self.gen_char_from(charset));
|
2012-05-17 13:52:49 -05:00
|
|
|
i += 1u;
|
|
|
|
}
|
2013-02-15 02:51:28 -06:00
|
|
|
s
|
2012-05-17 13:52:49 -05:00
|
|
|
}
|
2011-12-26 21:31:25 -06:00
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/// Return a random byte string of the specified length
|
2013-05-03 01:09:50 -05:00
|
|
|
fn gen_bytes(&mut self, len: uint) -> ~[u8] {
|
2012-06-30 18:19:07 -05:00
|
|
|
do vec::from_fn(len) |_i| {
|
2013-04-24 07:29:19 -05:00
|
|
|
self.gen()
|
2012-05-19 13:25:45 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/// Choose an item randomly, failing if values is empty
|
2013-07-10 16:43:25 -05:00
|
|
|
fn choose<T:Clone>(&mut self, values: &[T]) -> T {
|
2012-05-19 13:25:45 -05:00
|
|
|
self.choose_option(values).get()
|
|
|
|
}
|
|
|
|
|
2012-08-20 14:23:37 -05:00
|
|
|
/// Choose Some(item) randomly, returning None if values is empty
|
2013-07-02 14:47:32 -05:00
|
|
|
fn choose_option<T:Clone>(&mut self, values: &[T]) -> Option<T> {
|
2012-05-19 13:25:45 -05:00
|
|
|
if values.is_empty() {
|
2012-08-20 14:23:37 -05:00
|
|
|
None
|
2012-05-19 13:25:45 -05:00
|
|
|
} else {
|
2013-07-02 14:47:32 -05:00
|
|
|
Some(values[self.gen_uint_range(0u, values.len())].clone())
|
2012-05-17 13:52:49 -05:00
|
|
|
}
|
|
|
|
}
|
2012-07-04 16:53:12 -05:00
|
|
|
/**
|
|
|
|
* Choose an item respecting the relative weights, failing if the sum of
|
|
|
|
* the weights is 0
|
|
|
|
*/
|
2013-07-10 16:43:25 -05:00
|
|
|
fn choose_weighted<T:Clone>(&mut self, v: &[Weighted<T>]) -> T {
|
2012-05-19 13:25:45 -05:00
|
|
|
self.choose_weighted_option(v).get()
|
|
|
|
}
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/**
|
2012-08-20 14:23:37 -05:00
|
|
|
* Choose Some(item) respecting the relative weights, returning none if
|
2012-07-04 16:53:12 -05:00
|
|
|
* the sum of the weights is 0
|
|
|
|
*/
|
2013-07-02 14:47:32 -05:00
|
|
|
fn choose_weighted_option<T:Clone>(&mut self, v: &[Weighted<T>])
|
|
|
|
-> Option<T> {
|
2012-05-19 13:25:45 -05:00
|
|
|
let mut total = 0u;
|
2013-06-21 07:29:53 -05:00
|
|
|
for v.iter().advance |item| {
|
2012-05-19 13:25:45 -05:00
|
|
|
total += item.weight;
|
|
|
|
}
|
|
|
|
if total == 0u {
|
2012-08-20 14:23:37 -05:00
|
|
|
return None;
|
2012-05-19 13:25:45 -05:00
|
|
|
}
|
2012-05-21 20:57:28 -05:00
|
|
|
let chosen = self.gen_uint_range(0u, total);
|
2012-05-19 13:25:45 -05:00
|
|
|
let mut so_far = 0u;
|
2013-06-21 07:29:53 -05:00
|
|
|
for v.iter().advance |item| {
|
2012-05-19 13:25:45 -05:00
|
|
|
so_far += item.weight;
|
|
|
|
if so_far > chosen {
|
2013-07-02 14:47:32 -05:00
|
|
|
return Some(item.item.clone());
|
2012-05-19 13:25:45 -05:00
|
|
|
}
|
|
|
|
}
|
2012-09-20 16:27:25 -05:00
|
|
|
util::unreachable();
|
2012-05-19 13:25:45 -05:00
|
|
|
}
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/**
|
|
|
|
* Return a vec containing copies of the items, in order, where
|
|
|
|
* the weight of the item determines how many copies there are
|
|
|
|
*/
|
2013-07-02 14:47:32 -05:00
|
|
|
fn weighted_vec<T:Clone>(&mut self, v: &[Weighted<T>]) -> ~[T] {
|
2012-06-29 18:26:56 -05:00
|
|
|
let mut r = ~[];
|
2013-06-21 07:29:53 -05:00
|
|
|
for v.iter().advance |item| {
|
2012-06-30 18:19:07 -05:00
|
|
|
for uint::range(0u, item.weight) |_i| {
|
2013-07-02 14:47:32 -05:00
|
|
|
r.push(item.item.clone());
|
2012-05-19 13:25:45 -05:00
|
|
|
}
|
|
|
|
}
|
2013-02-15 02:51:28 -06:00
|
|
|
r
|
2012-05-19 13:25:45 -05:00
|
|
|
}
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/// Shuffle a vec
|
2013-07-10 16:43:25 -05:00
|
|
|
fn shuffle<T:Clone>(&mut self, values: &[T]) -> ~[T] {
|
2013-07-12 02:53:03 -05:00
|
|
|
let mut m = values.to_owned();
|
2012-05-19 13:25:45 -05:00
|
|
|
self.shuffle_mut(m);
|
2013-02-15 02:51:28 -06:00
|
|
|
m
|
2012-05-19 13:25:45 -05:00
|
|
|
}
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/// Shuffle a mutable vec in place
|
2013-05-03 01:09:50 -05:00
|
|
|
fn shuffle_mut<T>(&mut self, values: &mut [T]) {
|
2012-05-19 13:25:45 -05:00
|
|
|
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.
|
2013-06-28 11:54:03 -05:00
|
|
|
values.swap(i, self.gen_uint_range(0u, i + 1u));
|
2012-05-19 13:25:45 -05:00
|
|
|
}
|
|
|
|
}
|
2013-04-23 09:00:43 -05:00
|
|
|
}
|
2012-05-19 13:25:45 -05:00
|
|
|
|
2013-04-23 09:00:43 -05:00
|
|
|
/// Create a random number generator with a default algorithm and seed.
|
|
|
|
pub fn rng() -> IsaacRng {
|
|
|
|
IsaacRng::new()
|
2012-01-11 05:54:39 -06:00
|
|
|
}
|
2011-07-29 06:31:44 -05:00
|
|
|
|
2013-04-26 08:23:49 -05:00
|
|
|
static RAND_SIZE_LEN: u32 = 8;
|
|
|
|
static RAND_SIZE: u32 = 1 << RAND_SIZE_LEN;
|
2013-02-27 18:13:53 -06:00
|
|
|
|
2013-04-26 08:23:49 -05:00
|
|
|
/// A random number generator that uses the [ISAAC
|
|
|
|
/// algorithm](http://en.wikipedia.org/wiki/ISAAC_%28cipher%29).
|
|
|
|
pub struct IsaacRng {
|
2013-05-03 01:09:50 -05:00
|
|
|
priv cnt: u32,
|
|
|
|
priv rsl: [u32, .. RAND_SIZE],
|
|
|
|
priv mem: [u32, .. RAND_SIZE],
|
|
|
|
priv a: u32,
|
|
|
|
priv b: u32,
|
|
|
|
priv c: u32
|
2012-06-21 23:46:43 -05:00
|
|
|
}
|
2012-05-17 13:52:49 -05:00
|
|
|
|
2013-05-31 17:17:22 -05:00
|
|
|
impl IsaacRng {
|
2013-04-26 08:23:49 -05:00
|
|
|
/// Create an ISAAC random number generator with a random seed.
|
2013-05-31 17:17:22 -05:00
|
|
|
pub fn new() -> IsaacRng {
|
2013-04-23 09:00:43 -05:00
|
|
|
IsaacRng::new_seeded(seed())
|
|
|
|
}
|
|
|
|
|
2013-04-26 08:23:49 -05:00
|
|
|
/// Create an ISAAC random number generator with a seed. This can be any
|
|
|
|
/// length, although the maximum number of bytes used is 1024 and any more
|
|
|
|
/// will be silently ignored. A generator constructed with a given seed
|
|
|
|
/// will generate the same sequence of values as all other generators
|
|
|
|
/// constructed with the same seed.
|
2013-05-31 17:17:22 -05:00
|
|
|
pub fn new_seeded(seed: &[u8]) -> IsaacRng {
|
2013-04-26 08:23:49 -05:00
|
|
|
let mut rng = IsaacRng {
|
|
|
|
cnt: 0,
|
|
|
|
rsl: [0, .. RAND_SIZE],
|
|
|
|
mem: [0, .. RAND_SIZE],
|
|
|
|
a: 0, b: 0, c: 0
|
|
|
|
};
|
|
|
|
|
|
|
|
let array_size = sys::size_of_val(&rng.rsl);
|
|
|
|
let copy_length = cmp::min(array_size, seed.len());
|
|
|
|
|
|
|
|
// manually create a &mut [u8] slice of randrsl to copy into.
|
|
|
|
let dest = unsafe { cast::transmute((&mut rng.rsl, array_size)) };
|
|
|
|
vec::bytes::copy_memory(dest, seed, copy_length);
|
|
|
|
rng.init(true);
|
|
|
|
rng
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Create an ISAAC random number generator using the default
|
|
|
|
/// fixed seed.
|
2013-05-31 17:17:22 -05:00
|
|
|
pub fn new_unseeded() -> IsaacRng {
|
2013-04-26 08:23:49 -05:00
|
|
|
let mut rng = IsaacRng {
|
|
|
|
cnt: 0,
|
|
|
|
rsl: [0, .. RAND_SIZE],
|
|
|
|
mem: [0, .. RAND_SIZE],
|
|
|
|
a: 0, b: 0, c: 0
|
|
|
|
};
|
|
|
|
rng.init(false);
|
|
|
|
rng
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Initialises `self`. If `use_rsl` is true, then use the current value
|
|
|
|
/// of `rsl` as a seed, otherwise construct one algorithmically (not
|
|
|
|
/// randomly).
|
2013-05-31 17:17:22 -05:00
|
|
|
fn init(&mut self, use_rsl: bool) {
|
2013-06-04 23:43:41 -05:00
|
|
|
let mut a = 0x9e3779b9;
|
|
|
|
let mut b = a;
|
|
|
|
let mut c = a;
|
|
|
|
let mut d = a;
|
|
|
|
let mut e = a;
|
|
|
|
let mut f = a;
|
|
|
|
let mut g = a;
|
|
|
|
let mut h = a;
|
2013-04-26 08:23:49 -05:00
|
|
|
|
|
|
|
macro_rules! mix(
|
|
|
|
() => {{
|
|
|
|
a^=b<<11; d+=a; b+=c;
|
|
|
|
b^=c>>2; e+=b; c+=d;
|
|
|
|
c^=d<<8; f+=c; d+=e;
|
|
|
|
d^=e>>16; g+=d; e+=f;
|
|
|
|
e^=f<<10; h+=e; f+=g;
|
|
|
|
f^=g>>4; a+=f; g+=h;
|
|
|
|
g^=h<<8; b+=g; h+=a;
|
|
|
|
h^=a>>9; c+=h; a+=b;
|
|
|
|
}}
|
|
|
|
);
|
|
|
|
|
|
|
|
for 4.times { mix!(); }
|
|
|
|
|
|
|
|
if use_rsl {
|
|
|
|
macro_rules! memloop (
|
|
|
|
($arr:expr) => {{
|
|
|
|
for u32::range_step(0, RAND_SIZE, 8) |i| {
|
|
|
|
a+=$arr[i ]; b+=$arr[i+1];
|
|
|
|
c+=$arr[i+2]; d+=$arr[i+3];
|
|
|
|
e+=$arr[i+4]; f+=$arr[i+5];
|
|
|
|
g+=$arr[i+6]; h+=$arr[i+7];
|
|
|
|
mix!();
|
|
|
|
self.mem[i ]=a; self.mem[i+1]=b;
|
|
|
|
self.mem[i+2]=c; self.mem[i+3]=d;
|
|
|
|
self.mem[i+4]=e; self.mem[i+5]=f;
|
|
|
|
self.mem[i+6]=g; self.mem[i+7]=h;
|
|
|
|
}
|
|
|
|
}}
|
|
|
|
);
|
|
|
|
|
|
|
|
memloop!(self.rsl);
|
|
|
|
memloop!(self.mem);
|
|
|
|
} else {
|
|
|
|
for u32::range_step(0, RAND_SIZE, 8) |i| {
|
|
|
|
mix!();
|
|
|
|
self.mem[i ]=a; self.mem[i+1]=b;
|
|
|
|
self.mem[i+2]=c; self.mem[i+3]=d;
|
|
|
|
self.mem[i+4]=e; self.mem[i+5]=f;
|
|
|
|
self.mem[i+6]=g; self.mem[i+7]=h;
|
2013-04-23 09:00:43 -05:00
|
|
|
}
|
|
|
|
}
|
2013-04-26 08:23:49 -05:00
|
|
|
|
|
|
|
self.isaac();
|
2012-09-04 17:23:28 -05:00
|
|
|
}
|
|
|
|
|
2013-04-26 08:23:49 -05:00
|
|
|
/// Refills the output buffer (`self.rsl`)
|
2013-04-26 08:53:29 -05:00
|
|
|
#[inline]
|
2013-05-31 17:17:22 -05:00
|
|
|
fn isaac(&mut self) {
|
2013-04-26 08:23:49 -05:00
|
|
|
self.c += 1;
|
|
|
|
// abbreviations
|
2013-06-06 20:54:14 -05:00
|
|
|
let mut a = self.a;
|
|
|
|
let mut b = self.b + self.c;
|
2013-04-26 08:23:49 -05:00
|
|
|
|
2013-06-30 22:51:13 -05:00
|
|
|
static MIDPOINT: uint = RAND_SIZE as uint / 2;
|
2013-04-26 08:23:49 -05:00
|
|
|
|
2013-05-03 01:09:50 -05:00
|
|
|
macro_rules! ind (($x:expr) => {
|
|
|
|
self.mem[($x >> 2) & (RAND_SIZE - 1)]
|
|
|
|
});
|
2013-04-26 08:23:49 -05:00
|
|
|
macro_rules! rngstep(
|
|
|
|
($j:expr, $shift:expr) => {{
|
|
|
|
let base = base + $j;
|
|
|
|
let mix = if $shift < 0 {
|
|
|
|
a >> -$shift as uint
|
|
|
|
} else {
|
|
|
|
a << $shift as uint
|
|
|
|
};
|
|
|
|
|
2013-05-03 01:09:50 -05:00
|
|
|
let x = self.mem[base + mr_offset];
|
|
|
|
a = (a ^ mix) + self.mem[base + m2_offset];
|
2013-04-26 08:23:49 -05:00
|
|
|
let y = ind!(x) + a + b;
|
2013-05-03 01:09:50 -05:00
|
|
|
self.mem[base + mr_offset] = y;
|
2013-04-26 08:23:49 -05:00
|
|
|
|
|
|
|
b = ind!(y >> RAND_SIZE_LEN) + x;
|
2013-05-03 01:09:50 -05:00
|
|
|
self.rsl[base + mr_offset] = b;
|
2013-04-26 08:23:49 -05:00
|
|
|
}}
|
|
|
|
);
|
|
|
|
|
2013-06-30 22:51:13 -05:00
|
|
|
let r = [(0, MIDPOINT), (MIDPOINT, 0)];
|
2013-06-21 07:29:53 -05:00
|
|
|
for r.iter().advance |&(mr_offset, m2_offset)| {
|
2013-06-30 22:51:13 -05:00
|
|
|
for uint::range_step(0, MIDPOINT, 4) |base| {
|
2013-04-26 08:23:49 -05:00
|
|
|
rngstep!(0, 13);
|
|
|
|
rngstep!(1, -6);
|
|
|
|
rngstep!(2, 2);
|
|
|
|
rngstep!(3, -16);
|
|
|
|
}
|
2013-01-10 23:23:07 -06:00
|
|
|
}
|
2013-04-26 08:23:49 -05:00
|
|
|
|
|
|
|
self.a = a;
|
|
|
|
self.b = b;
|
|
|
|
self.cnt = RAND_SIZE;
|
2013-01-10 23:23:07 -06:00
|
|
|
}
|
2012-05-20 08:06:54 -05:00
|
|
|
}
|
2012-05-17 13:52:49 -05:00
|
|
|
|
2013-04-26 08:23:49 -05:00
|
|
|
impl Rng for IsaacRng {
|
2013-06-18 16:45:18 -05:00
|
|
|
#[inline]
|
2013-05-03 01:09:50 -05:00
|
|
|
fn next(&mut self) -> u32 {
|
2013-04-26 08:23:49 -05:00
|
|
|
if self.cnt == 0 {
|
|
|
|
// make some more numbers
|
|
|
|
self.isaac();
|
2013-02-19 09:06:20 -06:00
|
|
|
}
|
2013-04-26 08:23:49 -05:00
|
|
|
self.cnt -= 1;
|
|
|
|
self.rsl[self.cnt]
|
2013-01-10 23:23:07 -06:00
|
|
|
}
|
2012-05-20 08:06:54 -05:00
|
|
|
}
|
|
|
|
|
2013-04-26 08:53:29 -05:00
|
|
|
/// An [Xorshift random number
|
|
|
|
/// generator](http://en.wikipedia.org/wiki/Xorshift). Not suitable for
|
|
|
|
/// cryptographic purposes.
|
2013-04-26 08:23:49 -05:00
|
|
|
pub struct XorShiftRng {
|
2013-05-03 01:09:50 -05:00
|
|
|
priv x: u32,
|
|
|
|
priv y: u32,
|
|
|
|
priv z: u32,
|
|
|
|
priv w: u32,
|
2013-01-22 10:12:52 -06:00
|
|
|
}
|
2012-05-30 18:31:16 -05:00
|
|
|
|
2013-04-23 09:00:43 -05:00
|
|
|
impl Rng for XorShiftRng {
|
2013-04-26 08:53:29 -05:00
|
|
|
#[inline]
|
2013-05-03 01:09:50 -05:00
|
|
|
pub fn next(&mut self) -> u32 {
|
2012-05-30 18:31:16 -05:00
|
|
|
let x = self.x;
|
2013-04-12 00:10:01 -05:00
|
|
|
let t = x ^ (x << 11);
|
2012-05-30 18:31:16 -05:00
|
|
|
self.x = self.y;
|
|
|
|
self.y = self.z;
|
|
|
|
self.z = self.w;
|
|
|
|
let w = self.w;
|
|
|
|
self.w = w ^ (w >> 19) ^ (t ^ (t >> 8));
|
|
|
|
self.w
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-05-31 17:17:22 -05:00
|
|
|
impl XorShiftRng {
|
2013-04-23 09:00:43 -05:00
|
|
|
/// Create an xor shift random number generator with a default seed.
|
2013-05-31 17:17:22 -05:00
|
|
|
pub fn new() -> XorShiftRng {
|
2013-04-23 09:00:43 -05:00
|
|
|
// constants taken from http://en.wikipedia.org/wiki/Xorshift
|
2013-05-03 01:09:50 -05:00
|
|
|
XorShiftRng::new_seeded(123456789u32,
|
|
|
|
362436069u32,
|
|
|
|
521288629u32,
|
|
|
|
88675123u32)
|
2013-04-23 09:00:43 -05:00
|
|
|
}
|
2012-05-30 18:31:16 -05:00
|
|
|
|
2013-04-23 09:00:43 -05:00
|
|
|
/**
|
|
|
|
* Create a random number generator using the specified seed. A generator
|
2013-05-31 17:17:22 -05:00
|
|
|
* constructed with a given seed will generate the same sequence of values
|
|
|
|
* as all other generators constructed with the same seed.
|
2013-04-23 09:00:43 -05:00
|
|
|
*/
|
2013-05-31 17:17:22 -05:00
|
|
|
pub fn new_seeded(x: u32, y: u32, z: u32, w: u32) -> XorShiftRng {
|
2013-05-03 01:09:50 -05:00
|
|
|
XorShiftRng {
|
|
|
|
x: x,
|
|
|
|
y: y,
|
|
|
|
z: z,
|
|
|
|
w: w,
|
|
|
|
}
|
2013-04-23 09:00:43 -05:00
|
|
|
}
|
2013-04-26 08:23:49 -05:00
|
|
|
}
|
2012-05-30 18:31:16 -05:00
|
|
|
|
2013-04-26 08:23:49 -05:00
|
|
|
/// Create a new random seed.
|
|
|
|
pub fn seed() -> ~[u8] {
|
|
|
|
unsafe {
|
|
|
|
let n = rustrt::rand_seed_size() as uint;
|
|
|
|
let mut s = vec::from_elem(n, 0_u8);
|
2013-07-03 01:34:17 -05:00
|
|
|
do s.as_mut_buf |p, sz| {
|
2013-04-26 08:23:49 -05:00
|
|
|
rustrt::rand_gen_seed(p, sz as size_t)
|
|
|
|
}
|
|
|
|
s
|
|
|
|
}
|
2013-04-23 09:00:43 -05:00
|
|
|
}
|
2012-10-01 22:29:34 -05:00
|
|
|
|
|
|
|
// used to make space in TLS for a random number generator
|
2013-07-14 03:43:31 -05:00
|
|
|
static tls_rng_state: local_data::Key<@@mut IsaacRng> = &local_data::Key;
|
2012-10-01 22:29:34 -05:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Gives back a lazily initialized task-local random number generator,
|
|
|
|
* seeded by the system. Intended to be used in method chaining style, ie
|
2013-04-24 07:29:19 -05:00
|
|
|
* `task_rng().gen::<int>()`.
|
2012-10-01 22:29:34 -05:00
|
|
|
*/
|
2013-04-26 08:53:29 -05:00
|
|
|
#[inline]
|
2013-06-18 13:54:00 -05:00
|
|
|
pub fn task_rng() -> @mut IsaacRng {
|
2013-07-12 03:38:44 -05:00
|
|
|
let r = local_data::get(tls_rng_state, |k| k.map(|&k| *k));
|
2012-10-01 22:29:34 -05:00
|
|
|
match r {
|
|
|
|
None => {
|
2013-07-12 03:38:44 -05:00
|
|
|
let rng = @@mut IsaacRng::new_seeded(seed());
|
|
|
|
local_data::set(tls_rng_state, rng);
|
|
|
|
*rng
|
2012-10-01 22:29:34 -05:00
|
|
|
}
|
2013-06-18 13:54:00 -05:00
|
|
|
Some(rng) => *rng
|
2012-10-01 22:29:34 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-04-24 07:29:19 -05:00
|
|
|
// Allow direct chaining with `task_rng`
|
2013-06-18 13:54:00 -05:00
|
|
|
impl<R: Rng> Rng for @mut R {
|
2013-06-18 16:45:18 -05:00
|
|
|
#[inline]
|
2013-05-03 01:09:50 -05:00
|
|
|
fn next(&mut self) -> u32 {
|
2013-06-18 13:54:00 -05:00
|
|
|
(**self).next()
|
2013-05-03 01:09:50 -05:00
|
|
|
}
|
2013-04-24 07:29:19 -05:00
|
|
|
}
|
|
|
|
|
2012-10-02 16:15:14 -05:00
|
|
|
/**
|
2013-04-21 07:09:33 -05:00
|
|
|
* Returns a random value of a Rand type, using the task's random number
|
|
|
|
* generator.
|
2012-10-02 16:15:14 -05:00
|
|
|
*/
|
2013-04-26 08:53:29 -05:00
|
|
|
#[inline]
|
2013-04-21 07:09:33 -05:00
|
|
|
pub fn random<T: Rand>() -> T {
|
2013-06-18 13:54:00 -05:00
|
|
|
task_rng().gen()
|
2012-10-02 16:15:14 -05:00
|
|
|
}
|
|
|
|
|
2012-01-17 21:05:07 -06:00
|
|
|
#[cfg(test)]
|
2013-07-22 13:43:12 -05:00
|
|
|
mod test {
|
2013-03-26 15:38:07 -05:00
|
|
|
use option::{Option, Some};
|
2013-04-23 09:00:43 -05:00
|
|
|
use super::*;
|
2012-12-27 19:53:04 -06:00
|
|
|
|
2012-05-20 08:06:54 -05:00
|
|
|
#[test]
|
2013-04-23 09:00:43 -05:00
|
|
|
fn test_rng_seeded() {
|
|
|
|
let seed = seed();
|
2013-05-07 19:57:58 -05:00
|
|
|
let mut ra = IsaacRng::new_seeded(seed);
|
|
|
|
let mut rb = IsaacRng::new_seeded(seed);
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(ra.gen_str(100u), rb.gen_str(100u));
|
2012-05-20 08:06:54 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2013-04-23 09:00:43 -05:00
|
|
|
fn test_rng_seeded_custom_seed() {
|
2012-05-20 08:06:54 -05:00
|
|
|
// much shorter than generated seeds which are 1024 bytes
|
2013-02-19 09:06:20 -06:00
|
|
|
let seed = [2u8, 32u8, 4u8, 32u8, 51u8];
|
2013-05-07 19:57:58 -05:00
|
|
|
let mut ra = IsaacRng::new_seeded(seed);
|
|
|
|
let mut rb = IsaacRng::new_seeded(seed);
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(ra.gen_str(100u), rb.gen_str(100u));
|
2012-05-20 08:06:54 -05:00
|
|
|
}
|
|
|
|
|
2012-06-05 01:26:06 -05:00
|
|
|
#[test]
|
2013-04-23 09:00:43 -05:00
|
|
|
fn test_rng_seeded_custom_seed2() {
|
2013-02-19 09:06:20 -06:00
|
|
|
let seed = [2u8, 32u8, 4u8, 32u8, 51u8];
|
2013-05-07 19:57:58 -05:00
|
|
|
let mut ra = IsaacRng::new_seeded(seed);
|
2012-06-05 01:26:06 -05:00
|
|
|
// Regression test that isaac is actually using the above vector
|
|
|
|
let r = ra.next();
|
2012-08-22 19:24:52 -05:00
|
|
|
error!("%?", r);
|
2013-03-28 20:39:09 -05:00
|
|
|
assert!(r == 890007737u32 // on x86_64
|
2013-03-06 15:58:02 -06:00
|
|
|
|| r == 2935188040u32); // on x86
|
2012-06-05 01:26:06 -05:00
|
|
|
}
|
|
|
|
|
2012-01-17 21:05:07 -06:00
|
|
|
#[test]
|
2013-04-23 09:00:43 -05:00
|
|
|
fn test_gen_int_range() {
|
2013-05-07 19:57:58 -05:00
|
|
|
let mut r = rng();
|
2012-05-21 20:57:28 -05:00
|
|
|
let a = r.gen_int_range(-3, 42);
|
2013-03-28 20:39:09 -05:00
|
|
|
assert!(a >= -3 && a < 42);
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(r.gen_int_range(0, 1), 0);
|
|
|
|
assert_eq!(r.gen_int_range(-12, -11), -12);
|
2012-05-19 13:25:45 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
#[should_fail]
|
2012-06-07 23:38:25 -05:00
|
|
|
#[ignore(cfg(windows))]
|
2013-04-23 09:00:43 -05:00
|
|
|
fn test_gen_int_from_fail() {
|
2013-05-07 19:57:58 -05:00
|
|
|
let mut r = rng();
|
|
|
|
r.gen_int_range(5, -2);
|
2012-05-19 13:25:45 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2013-04-23 09:00:43 -05:00
|
|
|
fn test_gen_uint_range() {
|
2013-05-07 19:57:58 -05:00
|
|
|
let mut r = rng();
|
2012-05-21 20:57:28 -05:00
|
|
|
let a = r.gen_uint_range(3u, 42u);
|
2013-03-28 20:39:09 -05:00
|
|
|
assert!(a >= 3u && a < 42u);
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(r.gen_uint_range(0u, 1u), 0u);
|
|
|
|
assert_eq!(r.gen_uint_range(12u, 13u), 12u);
|
2012-05-19 13:25:45 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
#[should_fail]
|
2012-06-07 23:38:25 -05:00
|
|
|
#[ignore(cfg(windows))]
|
2013-04-23 09:00:43 -05:00
|
|
|
fn test_gen_uint_range_fail() {
|
2013-05-07 19:57:58 -05:00
|
|
|
let mut r = rng();
|
|
|
|
r.gen_uint_range(5u, 2u);
|
2012-01-17 21:05:07 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2013-04-23 09:00:43 -05:00
|
|
|
fn test_gen_float() {
|
2013-05-07 19:57:58 -05:00
|
|
|
let mut r = rng();
|
2013-04-24 07:29:19 -05:00
|
|
|
let a = r.gen::<float>();
|
|
|
|
let b = r.gen::<float>();
|
2013-03-08 14:39:42 -06:00
|
|
|
debug!((a, b));
|
2012-05-17 13:52:49 -05:00
|
|
|
}
|
|
|
|
|
2012-05-19 13:25:45 -05:00
|
|
|
#[test]
|
2013-04-23 09:00:43 -05:00
|
|
|
fn test_gen_weighted_bool() {
|
2013-05-07 19:57:58 -05:00
|
|
|
let mut r = rng();
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(r.gen_weighted_bool(0u), true);
|
|
|
|
assert_eq!(r.gen_weighted_bool(1u), true);
|
2012-05-19 13:25:45 -05:00
|
|
|
}
|
|
|
|
|
2012-05-17 13:52:49 -05:00
|
|
|
#[test]
|
2013-04-23 09:00:43 -05:00
|
|
|
fn test_gen_str() {
|
2013-05-07 19:57:58 -05:00
|
|
|
let mut r = rng();
|
2013-03-08 14:39:42 -06:00
|
|
|
debug!(r.gen_str(10u));
|
|
|
|
debug!(r.gen_str(10u));
|
|
|
|
debug!(r.gen_str(10u));
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(r.gen_str(0u).len(), 0u);
|
|
|
|
assert_eq!(r.gen_str(10u).len(), 10u);
|
|
|
|
assert_eq!(r.gen_str(16u).len(), 16u);
|
2012-05-17 13:52:49 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2013-04-23 09:00:43 -05:00
|
|
|
fn test_gen_bytes() {
|
2013-05-07 19:57:58 -05:00
|
|
|
let mut r = rng();
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(r.gen_bytes(0u).len(), 0u);
|
|
|
|
assert_eq!(r.gen_bytes(10u).len(), 10u);
|
|
|
|
assert_eq!(r.gen_bytes(16u).len(), 16u);
|
2012-01-17 21:05:07 -06:00
|
|
|
}
|
2012-05-19 13:25:45 -05:00
|
|
|
|
|
|
|
#[test]
|
2013-04-23 09:00:43 -05:00
|
|
|
fn test_choose() {
|
2013-05-07 19:57:58 -05:00
|
|
|
let mut r = rng();
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(r.choose([1, 1, 1]), 1);
|
2012-05-19 13:25:45 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2013-04-23 09:00:43 -05:00
|
|
|
fn test_choose_option() {
|
2013-05-07 19:57:58 -05:00
|
|
|
let mut r = rng();
|
2012-08-27 18:26:35 -05:00
|
|
|
let x: Option<int> = r.choose_option([]);
|
2013-03-28 20:39:09 -05:00
|
|
|
assert!(x.is_none());
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(r.choose_option([1, 1, 1]), Some(1));
|
2012-05-19 13:25:45 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2013-04-23 09:00:43 -05:00
|
|
|
fn test_choose_weighted() {
|
2013-05-07 19:57:58 -05:00
|
|
|
let mut r = rng();
|
2013-05-23 11:39:17 -05:00
|
|
|
assert!(r.choose_weighted([
|
2013-04-23 09:00:43 -05:00
|
|
|
Weighted { weight: 1u, item: 42 },
|
2013-03-06 15:58:02 -06:00
|
|
|
]) == 42);
|
2013-05-23 11:39:17 -05:00
|
|
|
assert!(r.choose_weighted([
|
2013-04-23 09:00:43 -05:00
|
|
|
Weighted { weight: 0u, item: 42 },
|
|
|
|
Weighted { weight: 1u, item: 43 },
|
2013-03-06 15:58:02 -06:00
|
|
|
]) == 43);
|
2012-05-19 13:25:45 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2013-04-23 09:00:43 -05:00
|
|
|
fn test_choose_weighted_option() {
|
2013-05-07 19:57:58 -05:00
|
|
|
let mut r = rng();
|
2013-05-23 11:39:17 -05:00
|
|
|
assert!(r.choose_weighted_option([
|
2013-04-23 09:00:43 -05:00
|
|
|
Weighted { weight: 1u, item: 42 },
|
2013-03-06 15:58:02 -06:00
|
|
|
]) == Some(42));
|
2013-05-23 11:39:17 -05:00
|
|
|
assert!(r.choose_weighted_option([
|
2013-04-23 09:00:43 -05:00
|
|
|
Weighted { weight: 0u, item: 42 },
|
|
|
|
Weighted { weight: 1u, item: 43 },
|
2013-03-06 15:58:02 -06:00
|
|
|
]) == Some(43));
|
2012-08-27 18:26:35 -05:00
|
|
|
let v: Option<int> = r.choose_weighted_option([]);
|
2013-03-28 20:39:09 -05:00
|
|
|
assert!(v.is_none());
|
2012-05-19 13:25:45 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2013-04-23 09:00:43 -05:00
|
|
|
fn test_weighted_vec() {
|
2013-05-07 19:57:58 -05:00
|
|
|
let mut r = rng();
|
2012-06-29 18:26:56 -05:00
|
|
|
let empty: ~[int] = ~[];
|
2013-05-23 11:39:17 -05:00
|
|
|
assert_eq!(r.weighted_vec([]), empty);
|
|
|
|
assert!(r.weighted_vec([
|
2013-04-23 09:00:43 -05:00
|
|
|
Weighted { weight: 0u, item: 3u },
|
|
|
|
Weighted { weight: 1u, item: 2u },
|
|
|
|
Weighted { weight: 2u, item: 1u },
|
2013-03-06 15:58:02 -06:00
|
|
|
]) == ~[2u, 1u, 1u]);
|
2012-05-19 13:25:45 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2013-04-23 09:00:43 -05:00
|
|
|
fn test_shuffle() {
|
2013-05-07 19:57:58 -05:00
|
|
|
let mut r = rng();
|
2012-06-29 18:26:56 -05:00
|
|
|
let empty: ~[int] = ~[];
|
2013-05-23 11:39:17 -05:00
|
|
|
assert_eq!(r.shuffle([]), empty);
|
|
|
|
assert_eq!(r.shuffle([1, 1, 1]), ~[1, 1, 1]);
|
2012-05-19 13:25:45 -05:00
|
|
|
}
|
2012-10-01 22:48:33 -05:00
|
|
|
|
|
|
|
#[test]
|
2013-04-23 09:00:43 -05:00
|
|
|
fn test_task_rng() {
|
2013-05-07 19:57:58 -05:00
|
|
|
let mut r = task_rng();
|
2013-04-24 07:29:19 -05:00
|
|
|
r.gen::<int>();
|
2013-05-23 11:39:17 -05:00
|
|
|
assert_eq!(r.shuffle([1, 1, 1]), ~[1, 1, 1]);
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(r.gen_uint_range(0u, 1u), 0u);
|
2012-10-01 22:48:33 -05:00
|
|
|
}
|
2012-10-02 16:15:14 -05:00
|
|
|
|
|
|
|
#[test]
|
2013-04-23 09:00:43 -05:00
|
|
|
fn test_random() {
|
2013-04-21 07:09:33 -05:00
|
|
|
// not sure how to test this aside from just getting some values
|
2013-04-23 09:00:43 -05:00
|
|
|
let _n : uint = random();
|
|
|
|
let _f : f32 = random();
|
|
|
|
let _o : Option<Option<i8>> = random();
|
2013-04-22 04:01:48 -05:00
|
|
|
let _many : ((),
|
|
|
|
(~uint, @int, ~Option<~(@char, ~(@bool,))>),
|
|
|
|
(u8, i8, u16, i16, u32, i32, u64, i64),
|
2013-04-23 09:00:43 -05:00
|
|
|
(f32, (f64, (float,)))) = random();
|
2012-10-02 16:15:14 -05:00
|
|
|
}
|
2013-04-26 08:23:49 -05:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn compare_isaac_implementation() {
|
|
|
|
// 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 {}
|
|
|
|
|
2013-07-18 21:08:57 -05:00
|
|
|
extern {
|
|
|
|
pub unsafe fn rand_new_seeded(buf: *u8, sz: size_t)
|
|
|
|
-> *rust_rng;
|
|
|
|
pub unsafe fn rand_next(rng: *rust_rng) -> u32;
|
|
|
|
pub unsafe fn rand_free(rng: *rust_rng);
|
2013-04-26 08:23:49 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// run against several seeds
|
|
|
|
for 10.times {
|
|
|
|
unsafe {
|
|
|
|
let seed = super::seed();
|
2013-07-03 01:34:17 -05:00
|
|
|
let rt_rng = do seed.as_imm_buf |p, sz| {
|
2013-04-26 08:23:49 -05:00
|
|
|
rustrt::rand_new_seeded(p, sz as size_t)
|
|
|
|
};
|
2013-05-07 19:57:58 -05:00
|
|
|
let mut rng = IsaacRng::new_seeded(seed);
|
2013-04-26 08:23:49 -05:00
|
|
|
|
|
|
|
for 10000.times {
|
|
|
|
assert_eq!(rng.next(), rustrt::rand_next(rt_rng));
|
|
|
|
}
|
|
|
|
rustrt::rand_free(rt_rng);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-01-17 21:05:07 -06:00
|
|
|
}
|
2013-07-22 13:43:12 -05:00
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod bench {
|
|
|
|
use extra::test::BenchHarness;
|
|
|
|
use rand::*;
|
|
|
|
use sys::size_of;
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn rand_xorshift(bh: &mut BenchHarness) {
|
|
|
|
let mut rng = XorShiftRng::new();
|
|
|
|
do bh.iter {
|
|
|
|
rng.gen::<uint>();
|
|
|
|
}
|
|
|
|
bh.bytes = size_of::<uint>() as u64;
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn rand_isaac(bh: &mut BenchHarness) {
|
|
|
|
let mut rng = IsaacRng::new();
|
|
|
|
do bh.iter {
|
|
|
|
rng.gen::<uint>();
|
|
|
|
}
|
|
|
|
bh.bytes = size_of::<uint>() as u64;
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn rand_shuffle_100(bh: &mut BenchHarness) {
|
|
|
|
let mut rng = XorShiftRng::new();
|
|
|
|
let x : &mut[uint] = [1,..100];
|
|
|
|
do bh.iter {
|
|
|
|
rng.shuffle_mut(x);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|