2014-01-25 01:37:51 -06:00
|
|
|
// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
|
2013-10-01 12:16:22 -05:00
|
|
|
// 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.
|
|
|
|
|
|
|
|
//! The implementations of `Rand` for the built-in types.
|
|
|
|
|
2014-03-01 18:23:04 -06:00
|
|
|
use std::char;
|
|
|
|
use std::int;
|
|
|
|
use std::uint;
|
|
|
|
|
|
|
|
use {Rand,Rng};
|
2013-10-01 12:16:22 -05:00
|
|
|
|
|
|
|
impl Rand for int {
|
|
|
|
#[inline]
|
|
|
|
fn rand<R: Rng>(rng: &mut R) -> int {
|
2014-01-25 01:37:51 -06:00
|
|
|
if int::BITS == 32 {
|
2013-10-01 12:16:22 -05:00
|
|
|
rng.gen::<i32>() as int
|
|
|
|
} else {
|
|
|
|
rng.gen::<i64>() as int
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Rand for i8 {
|
|
|
|
#[inline]
|
|
|
|
fn rand<R: Rng>(rng: &mut R) -> i8 {
|
|
|
|
rng.next_u32() as i8
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Rand for i16 {
|
|
|
|
#[inline]
|
|
|
|
fn rand<R: Rng>(rng: &mut R) -> i16 {
|
|
|
|
rng.next_u32() as i16
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Rand for i32 {
|
|
|
|
#[inline]
|
|
|
|
fn rand<R: Rng>(rng: &mut R) -> i32 {
|
|
|
|
rng.next_u32() as i32
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Rand for i64 {
|
|
|
|
#[inline]
|
|
|
|
fn rand<R: Rng>(rng: &mut R) -> i64 {
|
|
|
|
rng.next_u64() as i64
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Rand for uint {
|
|
|
|
#[inline]
|
|
|
|
fn rand<R: Rng>(rng: &mut R) -> uint {
|
2014-01-25 01:37:51 -06:00
|
|
|
if uint::BITS == 32 {
|
2013-10-01 12:16:22 -05:00
|
|
|
rng.gen::<u32>() as uint
|
|
|
|
} else {
|
|
|
|
rng.gen::<u64>() as uint
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Rand for u8 {
|
|
|
|
#[inline]
|
|
|
|
fn rand<R: Rng>(rng: &mut R) -> u8 {
|
|
|
|
rng.next_u32() as u8
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Rand for u16 {
|
|
|
|
#[inline]
|
|
|
|
fn rand<R: Rng>(rng: &mut R) -> u16 {
|
|
|
|
rng.next_u32() as u16
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Rand for u32 {
|
|
|
|
#[inline]
|
|
|
|
fn rand<R: Rng>(rng: &mut R) -> u32 {
|
|
|
|
rng.next_u32()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Rand for u64 {
|
|
|
|
#[inline]
|
|
|
|
fn rand<R: Rng>(rng: &mut R) -> u64 {
|
|
|
|
rng.next_u64()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-11-18 05:27:48 -06:00
|
|
|
macro_rules! float_impls {
|
|
|
|
($mod_name:ident, $ty:ty, $mantissa_bits:expr, $method_name:ident, $ignored_bits:expr) => {
|
|
|
|
mod $mod_name {
|
2014-03-01 18:23:04 -06:00
|
|
|
use {Rand, Rng, Open01, Closed01};
|
2013-10-08 10:09:33 -05:00
|
|
|
|
2013-11-18 05:27:48 -06:00
|
|
|
static SCALE: $ty = (1u64 << $mantissa_bits) as $ty;
|
2013-10-01 12:16:22 -05:00
|
|
|
|
2013-11-18 05:27:48 -06:00
|
|
|
impl Rand for $ty {
|
|
|
|
/// Generate a floating point number in the half-open
|
|
|
|
/// interval `[0,1)`.
|
|
|
|
///
|
|
|
|
/// See `Closed01` for the closed interval `[0,1]`,
|
|
|
|
/// and `Open01` for the open interval `(0,1)`.
|
|
|
|
#[inline]
|
|
|
|
fn rand<R: Rng>(rng: &mut R) -> $ty {
|
|
|
|
// using any more than `mantissa_bits` bits will
|
|
|
|
// cause (e.g.) 0xffff_ffff to correspond to 1
|
|
|
|
// exactly, so we need to drop some (8 for f32, 11
|
|
|
|
// for f64) to guarantee the open end.
|
|
|
|
(rng.$method_name() >> $ignored_bits) as $ty / SCALE
|
|
|
|
}
|
|
|
|
}
|
|
|
|
impl Rand for Open01<$ty> {
|
|
|
|
#[inline]
|
|
|
|
fn rand<R: Rng>(rng: &mut R) -> Open01<$ty> {
|
|
|
|
// add a small amount (specifically 2 bits below
|
|
|
|
// the precision of f64/f32 at 1.0), so that small
|
|
|
|
// numbers are larger than 0, but large numbers
|
|
|
|
// aren't pushed to/above 1.
|
|
|
|
Open01(((rng.$method_name() >> $ignored_bits) as $ty + 0.25) / SCALE)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
impl Rand for Closed01<$ty> {
|
|
|
|
#[inline]
|
|
|
|
fn rand<R: Rng>(rng: &mut R) -> Closed01<$ty> {
|
|
|
|
// divide by the maximum value of the numerator to
|
|
|
|
// get a non-zero probability of getting exactly
|
|
|
|
// 1.0.
|
|
|
|
Closed01((rng.$method_name() >> $ignored_bits) as $ty / (SCALE - 1.0))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2013-10-01 12:16:22 -05:00
|
|
|
}
|
|
|
|
}
|
2013-11-18 05:27:48 -06:00
|
|
|
float_impls! { f64_rand_impls, f64, 53, next_u64, 11 }
|
|
|
|
float_impls! { f32_rand_impls, f32, 24, next_u32, 8 }
|
2013-10-01 12:16:22 -05:00
|
|
|
|
|
|
|
impl Rand for char {
|
|
|
|
#[inline]
|
|
|
|
fn rand<R: Rng>(rng: &mut R) -> char {
|
|
|
|
// a char is 21 bits
|
|
|
|
static CHAR_MASK: u32 = 0x001f_ffff;
|
|
|
|
loop {
|
|
|
|
// Rejection sampling. About 0.2% of numbers with at most
|
|
|
|
// 21-bits are invalid codepoints (surrogates), so this
|
|
|
|
// will succeed first go almost every time.
|
|
|
|
match char::from_u32(rng.next_u32() & CHAR_MASK) {
|
|
|
|
Some(c) => return c,
|
|
|
|
None => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Rand for bool {
|
|
|
|
#[inline]
|
|
|
|
fn rand<R: Rng>(rng: &mut R) -> bool {
|
|
|
|
rng.gen::<u8>() & 1 == 1
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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 ),* , ) {
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn rand<R: Rng>(_rng: &mut R) -> ( $( $tyvar ),* , ) {
|
|
|
|
(
|
|
|
|
// use the $tyvar's to get the appropriate number of
|
|
|
|
// repeats (they're not actually needed)
|
|
|
|
$(
|
|
|
|
_rng.gen::<$tyvar>()
|
|
|
|
),*
|
|
|
|
,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Rand for () {
|
|
|
|
#[inline]
|
|
|
|
fn rand<R: Rng>(_: &mut R) -> () { () }
|
|
|
|
}
|
|
|
|
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}
|
|
|
|
|
|
|
|
impl<T:Rand> Rand for Option<T> {
|
|
|
|
#[inline]
|
|
|
|
fn rand<R: Rng>(rng: &mut R) -> Option<T> {
|
|
|
|
if rng.gen() {
|
|
|
|
Some(rng.gen())
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-05 20:56:44 -05:00
|
|
|
impl<T: Rand> Rand for Box<T> {
|
2013-10-01 12:16:22 -05:00
|
|
|
#[inline]
|
2014-05-05 20:56:44 -05:00
|
|
|
fn rand<R: Rng>(rng: &mut R) -> Box<T> { box rng.gen() }
|
2013-10-01 12:16:22 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<T: Rand + 'static> Rand for @T {
|
|
|
|
#[inline]
|
|
|
|
fn rand<R: Rng>(rng: &mut R) -> @T { @rng.gen() }
|
|
|
|
}
|
2013-10-08 10:09:33 -05:00
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
2014-03-01 18:23:04 -06:00
|
|
|
use {Rng, task_rng, Open01, Closed01};
|
2013-11-18 05:27:48 -06:00
|
|
|
|
2013-10-08 10:09:33 -05:00
|
|
|
struct ConstantRng(u64);
|
|
|
|
impl Rng for ConstantRng {
|
2013-10-08 17:56:57 -05:00
|
|
|
fn next_u32(&mut self) -> u32 {
|
2013-11-01 20:06:31 -05:00
|
|
|
let ConstantRng(v) = *self;
|
|
|
|
v as u32
|
2013-10-08 17:56:57 -05:00
|
|
|
}
|
2013-10-08 10:09:33 -05:00
|
|
|
fn next_u64(&mut self) -> u64 {
|
2013-11-01 20:06:31 -05:00
|
|
|
let ConstantRng(v) = *self;
|
|
|
|
v
|
2013-10-08 10:09:33 -05:00
|
|
|
}
|
|
|
|
}
|
2013-11-18 05:27:48 -06:00
|
|
|
|
2013-12-19 08:12:56 -06:00
|
|
|
#[test]
|
2013-10-08 10:09:33 -05:00
|
|
|
fn floating_point_edge_cases() {
|
|
|
|
// the test for exact equality is correct here.
|
|
|
|
assert!(ConstantRng(0xffff_ffff).gen::<f32>() != 1.0)
|
|
|
|
assert!(ConstantRng(0xffff_ffff_ffff_ffff).gen::<f64>() != 1.0)
|
|
|
|
}
|
2013-11-18 05:27:48 -06:00
|
|
|
|
2013-12-19 08:12:56 -06:00
|
|
|
#[test]
|
2013-11-18 05:27:48 -06:00
|
|
|
fn rand_open() {
|
|
|
|
// this is unlikely to catch an incorrect implementation that
|
|
|
|
// generates exactly 0 or 1, but it keeps it sane.
|
|
|
|
let mut rng = task_rng();
|
|
|
|
for _ in range(0, 1_000) {
|
|
|
|
// strict inequalities
|
2013-11-01 20:06:31 -05:00
|
|
|
let Open01(f) = rng.gen::<Open01<f64>>();
|
2013-11-18 05:27:48 -06:00
|
|
|
assert!(0.0 < f && f < 1.0);
|
|
|
|
|
2013-11-01 20:06:31 -05:00
|
|
|
let Open01(f) = rng.gen::<Open01<f32>>();
|
2013-11-18 05:27:48 -06:00
|
|
|
assert!(0.0 < f && f < 1.0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-12-19 08:12:56 -06:00
|
|
|
#[test]
|
2013-11-18 05:27:48 -06:00
|
|
|
fn rand_closed() {
|
|
|
|
let mut rng = task_rng();
|
|
|
|
for _ in range(0, 1_000) {
|
|
|
|
// strict inequalities
|
2013-11-01 20:06:31 -05:00
|
|
|
let Closed01(f) = rng.gen::<Closed01<f64>>();
|
2013-11-18 05:27:48 -06:00
|
|
|
assert!(0.0 <= f && f <= 1.0);
|
|
|
|
|
2013-11-01 20:06:31 -05:00
|
|
|
let Closed01(f) = rng.gen::<Closed01<f32>>();
|
2013-11-18 05:27:48 -06:00
|
|
|
assert!(0.0 <= f && f <= 1.0);
|
|
|
|
}
|
|
|
|
}
|
2013-10-08 10:09:33 -05:00
|
|
|
}
|