// Copyright 2013 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 or the MIT license // , 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. use char; use int; use option::{Option, Some, None}; use rand::{Rand,Rng}; use uint; impl Rand for int { #[inline] fn rand(rng: &mut R) -> int { if int::bits == 32 { rng.gen::() as int } else { rng.gen::() as int } } } impl Rand for i8 { #[inline] fn rand(rng: &mut R) -> i8 { rng.next_u32() as i8 } } impl Rand for i16 { #[inline] fn rand(rng: &mut R) -> i16 { rng.next_u32() as i16 } } impl Rand for i32 { #[inline] fn rand(rng: &mut R) -> i32 { rng.next_u32() as i32 } } impl Rand for i64 { #[inline] fn rand(rng: &mut R) -> i64 { rng.next_u64() as i64 } } impl Rand for uint { #[inline] fn rand(rng: &mut R) -> uint { if uint::bits == 32 { rng.gen::() as uint } else { rng.gen::() as uint } } } impl Rand for u8 { #[inline] fn rand(rng: &mut R) -> u8 { rng.next_u32() as u8 } } impl Rand for u16 { #[inline] fn rand(rng: &mut R) -> u16 { rng.next_u32() as u16 } } impl Rand for u32 { #[inline] fn rand(rng: &mut R) -> u32 { rng.next_u32() } } impl Rand for u64 { #[inline] fn rand(rng: &mut R) -> u64 { rng.next_u64() } } impl Rand for f32 { /// A random `f32` in the range `[0, 1)`, using 24 bits of /// precision. #[inline] fn rand(rng: &mut R) -> f32 { // using any more than 24 bits will cause (e.g.) 0xffff_ffff // to correspond to 1 exactly, so we need to drop 8 to // guarantee the open end. static SCALE: f32 = (1u32 << 24) as f32; (rng.next_u32() >> 8) as f32 / SCALE } } impl Rand for f64 { /// A random `f64` in the range `[0, 1)`, using 53 bits of /// precision. #[inline] fn rand(rng: &mut R) -> f64 { // as for f32, but using more bits. static SCALE: f64 = (1u64 << 53) as f64; (rng.next_u64() >> 11) as f64 / SCALE } } impl Rand for char { #[inline] fn rand(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(rng: &mut R) -> bool { rng.gen::() & 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(_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(_: &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 Rand for Option { #[inline] fn rand(rng: &mut R) -> Option { if rng.gen() { Some(rng.gen()) } else { None } } } impl Rand for ~T { #[inline] fn rand(rng: &mut R) -> ~T { ~rng.gen() } } impl Rand for @T { #[inline] fn rand(rng: &mut R) -> @T { @rng.gen() } } #[cfg(test)] mod tests { use rand::Rng; struct ConstantRng(u64); impl Rng for ConstantRng { fn next_u32(&mut self) -> u32 { (**self) as u32 } fn next_u64(&mut self) -> u64 { **self } } fn floating_point_edge_cases() { // the test for exact equality is correct here. assert!(ConstantRng(0xffff_ffff).gen::() != 1.0) assert!(ConstantRng(0xffff_ffff_ffff_ffff).gen::() != 1.0) } }