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