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