]> git.lizzy.rs Git - rust.git/blob - src/librand/rand_impls.rs
Auto merge of #27296 - jroesch:type-macros, r=huonw
[rust.git] / src / librand / 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 #[cfg(stage0)]
14 use core::prelude::v1::*;
15
16 use core::char;
17 use core::isize;
18 use core::usize;
19
20 use {Rand,Rng};
21
22 impl Rand for isize {
23     #[inline]
24     fn rand<R: Rng>(rng: &mut R) -> isize {
25         if isize::BITS == 32 {
26             rng.gen::<i32>() as isize
27         } else {
28             rng.gen::<i64>() as isize
29         }
30     }
31 }
32
33 impl Rand for i8 {
34     #[inline]
35     fn rand<R: Rng>(rng: &mut R) -> i8 {
36         rng.next_u32() as i8
37     }
38 }
39
40 impl Rand for i16 {
41     #[inline]
42     fn rand<R: Rng>(rng: &mut R) -> i16 {
43         rng.next_u32() as i16
44     }
45 }
46
47 impl Rand for i32 {
48     #[inline]
49     fn rand<R: Rng>(rng: &mut R) -> i32 {
50         rng.next_u32() as i32
51     }
52 }
53
54 impl Rand for i64 {
55     #[inline]
56     fn rand<R: Rng>(rng: &mut R) -> i64 {
57         rng.next_u64() as i64
58     }
59 }
60
61 impl Rand for usize {
62     #[inline]
63     fn rand<R: Rng>(rng: &mut R) -> usize {
64         if usize::BITS == 32 {
65             rng.gen::<u32>() as usize
66         } else {
67             rng.gen::<u64>() as usize
68         }
69     }
70 }
71
72 impl Rand for u8 {
73     #[inline]
74     fn rand<R: Rng>(rng: &mut R) -> u8 {
75         rng.next_u32() as u8
76     }
77 }
78
79 impl Rand for u16 {
80     #[inline]
81     fn rand<R: Rng>(rng: &mut R) -> u16 {
82         rng.next_u32() as u16
83     }
84 }
85
86 impl Rand for u32 {
87     #[inline]
88     fn rand<R: Rng>(rng: &mut R) -> u32 {
89         rng.next_u32()
90     }
91 }
92
93 impl Rand for u64 {
94     #[inline]
95     fn rand<R: Rng>(rng: &mut R) -> u64 {
96         rng.next_u64()
97     }
98 }
99
100 macro_rules! float_impls {
101     ($mod_name:ident, $ty:ty, $mantissa_bits:expr, $method_name:ident) => {
102         mod $mod_name {
103             use {Rand, Rng, Open01, Closed01};
104
105             const SCALE: $ty = (1u64 << $mantissa_bits) as $ty;
106
107             impl Rand for $ty {
108                 /// Generate a floating point number in the half-open
109                 /// interval `[0,1)`.
110                 ///
111                 /// See `Closed01` for the closed interval `[0,1]`,
112                 /// and `Open01` for the open interval `(0,1)`.
113                 #[inline]
114                 fn rand<R: Rng>(rng: &mut R) -> $ty {
115                     rng.$method_name()
116                 }
117             }
118             impl Rand for Open01<$ty> {
119                 #[inline]
120                 fn rand<R: Rng>(rng: &mut R) -> Open01<$ty> {
121                     // add a small amount (specifically 2 bits below
122                     // the precision of f64/f32 at 1.0), so that small
123                     // numbers are larger than 0, but large numbers
124                     // aren't pushed to/above 1.
125                     Open01(rng.$method_name() + 0.25 / SCALE)
126                 }
127             }
128             impl Rand for Closed01<$ty> {
129                 #[inline]
130                 fn rand<R: Rng>(rng: &mut R) -> Closed01<$ty> {
131                     // rescale so that 1.0 - epsilon becomes 1.0
132                     // precisely.
133                     Closed01(rng.$method_name() * SCALE / (SCALE - 1.0))
134                 }
135             }
136         }
137     }
138 }
139 float_impls! { f64_rand_impls, f64, 53, next_f64 }
140 float_impls! { f32_rand_impls, f32, 24, next_f32 }
141
142 impl Rand for char {
143     #[inline]
144     fn rand<R: Rng>(rng: &mut R) -> char {
145         // a char is 21 bits
146         const CHAR_MASK: u32 = 0x001f_ffff;
147         loop {
148             // Rejection sampling. About 0.2% of numbers with at most
149             // 21-bits are invalid codepoints (surrogates), so this
150             // will succeed first go almost every time.
151             match char::from_u32(rng.next_u32() & CHAR_MASK) {
152                 Some(c) => return c,
153                 None => {}
154             }
155         }
156     }
157 }
158
159 impl Rand for bool {
160     #[inline]
161     fn rand<R: Rng>(rng: &mut R) -> bool {
162         rng.gen::<u8>() & 1 == 1
163     }
164 }
165
166 macro_rules! tuple_impl {
167     // use variables to indicate the arity of the tuple
168     ($($tyvar:ident),* ) => {
169         // the trailing commas are for the 1 tuple
170         impl<
171             $( $tyvar : Rand ),*
172             > Rand for ( $( $tyvar ),* , ) {
173
174             #[inline]
175             fn rand<R: Rng>(_rng: &mut R) -> ( $( $tyvar ),* , ) {
176                 (
177                     // use the $tyvar's to get the appropriate number of
178                     // repeats (they're not actually needed)
179                     $(
180                         _rng.gen::<$tyvar>()
181                     ),*
182                     ,
183                 )
184             }
185         }
186     }
187 }
188
189 impl Rand for () {
190     #[inline]
191     fn rand<R: Rng>(_: &mut R) -> () { () }
192 }
193 tuple_impl!{A}
194 tuple_impl!{A, B}
195 tuple_impl!{A, B, C}
196 tuple_impl!{A, B, C, D}
197 tuple_impl!{A, B, C, D, E}
198 tuple_impl!{A, B, C, D, E, F}
199 tuple_impl!{A, B, C, D, E, F, G}
200 tuple_impl!{A, B, C, D, E, F, G, H}
201 tuple_impl!{A, B, C, D, E, F, G, H, I}
202 tuple_impl!{A, B, C, D, E, F, G, H, I, J}
203 tuple_impl!{A, B, C, D, E, F, G, H, I, J, K}
204 tuple_impl!{A, B, C, D, E, F, G, H, I, J, K, L}
205
206 impl<T:Rand> Rand for Option<T> {
207     #[inline]
208     fn rand<R: Rng>(rng: &mut R) -> Option<T> {
209         if rng.gen() {
210             Some(rng.gen())
211         } else {
212             None
213         }
214     }
215 }