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