1 // Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT 2 // file at the top-level directory of this distribution and at 3 // http://rust-lang.org/COPYRIGHT. 4 // 5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or 6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license 7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your 8 // option. This file may not be copied, modified, or distributed 9 // except according to those terms. 10 11 //! The implementations of `Rand` for the built-in types. 12 13 use core::{char, mem}; 14 15 use {Rand,Rng}; 16 17 impl Rand for isize { 18 #[inline] rand<R: Rng>(rng: &mut R) -> isize19 fn rand<R: Rng>(rng: &mut R) -> isize { 20 if mem::size_of::<isize>() == 4 { 21 rng.gen::<i32>() as isize 22 } else { 23 rng.gen::<i64>() as isize 24 } 25 } 26 } 27 28 impl Rand for i8 { 29 #[inline] rand<R: Rng>(rng: &mut R) -> i830 fn rand<R: Rng>(rng: &mut R) -> i8 { 31 rng.next_u32() as i8 32 } 33 } 34 35 impl Rand for i16 { 36 #[inline] rand<R: Rng>(rng: &mut R) -> i1637 fn rand<R: Rng>(rng: &mut R) -> i16 { 38 rng.next_u32() as i16 39 } 40 } 41 42 impl Rand for i32 { 43 #[inline] rand<R: Rng>(rng: &mut R) -> i3244 fn rand<R: Rng>(rng: &mut R) -> i32 { 45 rng.next_u32() as i32 46 } 47 } 48 49 impl Rand for i64 { 50 #[inline] rand<R: Rng>(rng: &mut R) -> i6451 fn rand<R: Rng>(rng: &mut R) -> i64 { 52 rng.next_u64() as i64 53 } 54 } 55 56 #[cfg(feature = "i128_support")] 57 impl Rand for i128 { 58 #[inline] rand<R: Rng>(rng: &mut R) -> i12859 fn rand<R: Rng>(rng: &mut R) -> i128 { 60 rng.gen::<u128>() as i128 61 } 62 } 63 64 impl Rand for usize { 65 #[inline] rand<R: Rng>(rng: &mut R) -> usize66 fn rand<R: Rng>(rng: &mut R) -> usize { 67 if mem::size_of::<usize>() == 4 { 68 rng.gen::<u32>() as usize 69 } else { 70 rng.gen::<u64>() as usize 71 } 72 } 73 } 74 75 impl Rand for u8 { 76 #[inline] rand<R: Rng>(rng: &mut R) -> u877 fn rand<R: Rng>(rng: &mut R) -> u8 { 78 rng.next_u32() as u8 79 } 80 } 81 82 impl Rand for u16 { 83 #[inline] rand<R: Rng>(rng: &mut R) -> u1684 fn rand<R: Rng>(rng: &mut R) -> u16 { 85 rng.next_u32() as u16 86 } 87 } 88 89 impl Rand for u32 { 90 #[inline] rand<R: Rng>(rng: &mut R) -> u3291 fn rand<R: Rng>(rng: &mut R) -> u32 { 92 rng.next_u32() 93 } 94 } 95 96 impl Rand for u64 { 97 #[inline] rand<R: Rng>(rng: &mut R) -> u6498 fn rand<R: Rng>(rng: &mut R) -> u64 { 99 rng.next_u64() 100 } 101 } 102 103 #[cfg(feature = "i128_support")] 104 impl Rand for u128 { 105 #[inline] rand<R: Rng>(rng: &mut R) -> u128106 fn rand<R: Rng>(rng: &mut R) -> u128 { 107 ((rng.next_u64() as u128) << 64) | (rng.next_u64() as u128) 108 } 109 } 110 111 112 macro_rules! float_impls { 113 ($mod_name:ident, $ty:ty, $mantissa_bits:expr, $method_name:ident) => { 114 mod $mod_name { 115 use {Rand, Rng, Open01, Closed01}; 116 117 const SCALE: $ty = (1u64 << $mantissa_bits) as $ty; 118 119 impl Rand for $ty { 120 /// Generate a floating point number in the half-open 121 /// interval `[0,1)`. 122 /// 123 /// See `Closed01` for the closed interval `[0,1]`, 124 /// and `Open01` for the open interval `(0,1)`. 125 #[inline] 126 fn rand<R: Rng>(rng: &mut R) -> $ty { 127 rng.$method_name() 128 } 129 } 130 impl Rand for Open01<$ty> { 131 #[inline] 132 fn rand<R: Rng>(rng: &mut R) -> Open01<$ty> { 133 // add a small amount (specifically 2 bits below 134 // the precision of f64/f32 at 1.0), so that small 135 // numbers are larger than 0, but large numbers 136 // aren't pushed to/above 1. 137 Open01(rng.$method_name() + 0.25 / SCALE) 138 } 139 } 140 impl Rand for Closed01<$ty> { 141 #[inline] 142 fn rand<R: Rng>(rng: &mut R) -> Closed01<$ty> { 143 // rescale so that 1.0 - epsilon becomes 1.0 144 // precisely. 145 Closed01(rng.$method_name() * SCALE / (SCALE - 1.0)) 146 } 147 } 148 } 149 } 150 } 151 float_impls! { f64_rand_impls, f64, 53, next_f64 } 152 float_impls! { f32_rand_impls, f32, 24, next_f32 } 153 154 impl Rand for char { 155 #[inline] rand<R: Rng>(rng: &mut R) -> char156 fn rand<R: Rng>(rng: &mut R) -> char { 157 // a char is 21 bits 158 const CHAR_MASK: u32 = 0x001f_ffff; 159 loop { 160 // Rejection sampling. About 0.2% of numbers with at most 161 // 21-bits are invalid codepoints (surrogates), so this 162 // will succeed first go almost every time. 163 match char::from_u32(rng.next_u32() & CHAR_MASK) { 164 Some(c) => return c, 165 None => {} 166 } 167 } 168 } 169 } 170 171 impl Rand for bool { 172 #[inline] rand<R: Rng>(rng: &mut R) -> bool173 fn rand<R: Rng>(rng: &mut R) -> bool { 174 rng.gen::<u8>() & 1 == 1 175 } 176 } 177 178 macro_rules! tuple_impl { 179 // use variables to indicate the arity of the tuple 180 ($($tyvar:ident),* ) => { 181 // the trailing commas are for the 1 tuple 182 impl< 183 $( $tyvar : Rand ),* 184 > Rand for ( $( $tyvar ),* , ) { 185 186 #[inline] 187 fn rand<R: Rng>(_rng: &mut R) -> ( $( $tyvar ),* , ) { 188 ( 189 // use the $tyvar's to get the appropriate number of 190 // repeats (they're not actually needed) 191 $( 192 _rng.gen::<$tyvar>() 193 ),* 194 , 195 ) 196 } 197 } 198 } 199 } 200 201 impl Rand for () { 202 #[inline] rand<R: Rng>(_: &mut R) -> ()203 fn rand<R: Rng>(_: &mut R) -> () { () } 204 } 205 tuple_impl!{A} 206 tuple_impl!{A, B} 207 tuple_impl!{A, B, C} 208 tuple_impl!{A, B, C, D} 209 tuple_impl!{A, B, C, D, E} 210 tuple_impl!{A, B, C, D, E, F} 211 tuple_impl!{A, B, C, D, E, F, G} 212 tuple_impl!{A, B, C, D, E, F, G, H} 213 tuple_impl!{A, B, C, D, E, F, G, H, I} 214 tuple_impl!{A, B, C, D, E, F, G, H, I, J} 215 tuple_impl!{A, B, C, D, E, F, G, H, I, J, K} 216 tuple_impl!{A, B, C, D, E, F, G, H, I, J, K, L} 217 218 macro_rules! array_impl { 219 {$n:expr, $t:ident, $($ts:ident,)*} => { 220 array_impl!{($n - 1), $($ts,)*} 221 222 impl<T> Rand for [T; $n] where T: Rand { 223 #[inline] 224 fn rand<R: Rng>(_rng: &mut R) -> [T; $n] { 225 [_rng.gen::<$t>(), $(_rng.gen::<$ts>()),*] 226 } 227 } 228 }; 229 {$n:expr,} => { 230 impl<T> Rand for [T; $n] { 231 fn rand<R: Rng>(_rng: &mut R) -> [T; $n] { [] } 232 } 233 }; 234 } 235 236 array_impl!{32, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,} 237 238 impl<T:Rand> Rand for Option<T> { 239 #[inline] rand<R: Rng>(rng: &mut R) -> Option<T>240 fn rand<R: Rng>(rng: &mut R) -> Option<T> { 241 if rng.gen() { 242 Some(rng.gen()) 243 } else { 244 None 245 } 246 } 247 } 248 249 #[cfg(test)] 250 mod tests { 251 use {Rng, thread_rng, Open01, Closed01}; 252 253 struct ConstantRng(u64); 254 impl Rng for ConstantRng { next_u32(&mut self) -> u32255 fn next_u32(&mut self) -> u32 { 256 let ConstantRng(v) = *self; 257 v as u32 258 } next_u64(&mut self) -> u64259 fn next_u64(&mut self) -> u64 { 260 let ConstantRng(v) = *self; 261 v 262 } 263 } 264 265 #[test] floating_point_edge_cases()266 fn floating_point_edge_cases() { 267 // the test for exact equality is correct here. 268 assert!(ConstantRng(0xffff_ffff).gen::<f32>() != 1.0); 269 assert!(ConstantRng(0xffff_ffff_ffff_ffff).gen::<f64>() != 1.0); 270 } 271 272 #[test] rand_open()273 fn rand_open() { 274 // this is unlikely to catch an incorrect implementation that 275 // generates exactly 0 or 1, but it keeps it sane. 276 let mut rng = thread_rng(); 277 for _ in 0..1_000 { 278 // strict inequalities 279 let Open01(f) = rng.gen::<Open01<f64>>(); 280 assert!(0.0 < f && f < 1.0); 281 282 let Open01(f) = rng.gen::<Open01<f32>>(); 283 assert!(0.0 < f && f < 1.0); 284 } 285 } 286 287 #[test] rand_closed()288 fn rand_closed() { 289 let mut rng = thread_rng(); 290 for _ in 0..1_000 { 291 // strict inequalities 292 let Closed01(f) = rng.gen::<Closed01<f64>>(); 293 assert!(0.0 <= f && f <= 1.0); 294 295 let Closed01(f) = rng.gen::<Closed01<f32>>(); 296 assert!(0.0 <= f && f <= 1.0); 297 } 298 } 299 } 300