]> git.lizzy.rs Git - rust.git/blob - src/librand/rand_impls.rs
458a9ba378d98d31a1c805de64c2849c1c0b1c17
[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::int;
16 use core::uint;
17
18 use {Rand,Rng};
19
20 impl Rand for int {
21     #[inline]
22     fn rand<R: Rng>(rng: &mut R) -> int {
23         if int::BITS == 32 {
24             rng.gen::<i32>() as int
25         } else {
26             rng.gen::<i64>() as int
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 uint {
60     #[inline]
61     fn rand<R: Rng>(rng: &mut R) -> uint {
62         if uint::BITS == 32 {
63             rng.gen::<u32>() as uint
64         } else {
65             rng.gen::<u64>() as uint
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, $ignored_bits:expr) => {
100         mod $mod_name {
101             use {Rand, Rng, Open01, Closed01};
102
103             static 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                     // using any more than `mantissa_bits` bits will
114                     // cause (e.g.) 0xffff_ffff to correspond to 1
115                     // exactly, so we need to drop some (8 for f32, 11
116                     // for f64) to guarantee the open end.
117                     (rng.$method_name() >> $ignored_bits) as $ty / SCALE
118                 }
119             }
120             impl Rand for Open01<$ty> {
121                 #[inline]
122                 fn rand<R: Rng>(rng: &mut R) -> Open01<$ty> {
123                     // add a small amount (specifically 2 bits below
124                     // the precision of f64/f32 at 1.0), so that small
125                     // numbers are larger than 0, but large numbers
126                     // aren't pushed to/above 1.
127                     Open01(((rng.$method_name() >> $ignored_bits) as $ty + 0.25) / SCALE)
128                 }
129             }
130             impl Rand for Closed01<$ty> {
131                 #[inline]
132                 fn rand<R: Rng>(rng: &mut R) -> Closed01<$ty> {
133                     // divide by the maximum value of the numerator to
134                     // get a non-zero probability of getting exactly
135                     // 1.0.
136                     Closed01((rng.$method_name() >> $ignored_bits) as $ty / (SCALE - 1.0))
137                 }
138             }
139         }
140     }
141 }
142 float_impls! { f64_rand_impls, f64, 53, next_u64, 11 }
143 float_impls! { f32_rand_impls, f32, 24, next_u32, 8 }
144
145 impl Rand for char {
146     #[inline]
147     fn rand<R: Rng>(rng: &mut R) -> char {
148         // a char is 21 bits
149         static CHAR_MASK: u32 = 0x001f_ffff;
150         loop {
151             // Rejection sampling. About 0.2% of numbers with at most
152             // 21-bits are invalid codepoints (surrogates), so this
153             // will succeed first go almost every time.
154             match char::from_u32(rng.next_u32() & CHAR_MASK) {
155                 Some(c) => return c,
156                 None => {}
157             }
158         }
159     }
160 }
161
162 impl Rand for bool {
163     #[inline]
164     fn rand<R: Rng>(rng: &mut R) -> bool {
165         rng.gen::<u8>() & 1 == 1
166     }
167 }
168
169 macro_rules! tuple_impl {
170     // use variables to indicate the arity of the tuple
171     ($($tyvar:ident),* ) => {
172         // the trailing commas are for the 1 tuple
173         impl<
174             $( $tyvar : Rand ),*
175             > Rand for ( $( $tyvar ),* , ) {
176
177             #[inline]
178             fn rand<R: Rng>(_rng: &mut R) -> ( $( $tyvar ),* , ) {
179                 (
180                     // use the $tyvar's to get the appropriate number of
181                     // repeats (they're not actually needed)
182                     $(
183                         _rng.gen::<$tyvar>()
184                     ),*
185                     ,
186                 )
187             }
188         }
189     }
190 }
191
192 impl Rand for () {
193     #[inline]
194     fn rand<R: Rng>(_: &mut R) -> () { () }
195 }
196 tuple_impl!{A}
197 tuple_impl!{A, B}
198 tuple_impl!{A, B, C}
199 tuple_impl!{A, B, C, D}
200 tuple_impl!{A, B, C, D, E}
201 tuple_impl!{A, B, C, D, E, F}
202 tuple_impl!{A, B, C, D, E, F, G}
203 tuple_impl!{A, B, C, D, E, F, G, H}
204 tuple_impl!{A, B, C, D, E, F, G, H, I}
205 tuple_impl!{A, B, C, D, E, F, G, H, I, J}
206
207 impl<T:Rand> Rand for Option<T> {
208     #[inline]
209     fn rand<R: Rng>(rng: &mut R) -> Option<T> {
210         if rng.gen() {
211             Some(rng.gen())
212         } else {
213             None
214         }
215     }
216 }
217
218 #[cfg(test)]
219 mod tests {
220     use std::prelude::*;
221     use std::rand::{Rng, task_rng, Open01, Closed01};
222
223     struct ConstantRng(u64);
224     impl Rng for ConstantRng {
225         fn next_u32(&mut self) -> u32 {
226             let ConstantRng(v) = *self;
227             v as u32
228         }
229         fn next_u64(&mut self) -> u64 {
230             let ConstantRng(v) = *self;
231             v
232         }
233     }
234
235     #[test]
236     fn floating_point_edge_cases() {
237         // the test for exact equality is correct here.
238         assert!(ConstantRng(0xffff_ffff).gen::<f32>() != 1.0)
239         assert!(ConstantRng(0xffff_ffff_ffff_ffff).gen::<f64>() != 1.0)
240     }
241
242     #[test]
243     fn rand_open() {
244         // this is unlikely to catch an incorrect implementation that
245         // generates exactly 0 or 1, but it keeps it sane.
246         let mut rng = task_rng();
247         for _ in range(0, 1_000) {
248             // strict inequalities
249             let Open01(f) = rng.gen::<Open01<f64>>();
250             assert!(0.0 < f && f < 1.0);
251
252             let Open01(f) = rng.gen::<Open01<f32>>();
253             assert!(0.0 < f && f < 1.0);
254         }
255     }
256
257     #[test]
258     fn rand_closed() {
259         let mut rng = task_rng();
260         for _ in range(0, 1_000) {
261             // strict inequalities
262             let Closed01(f) = rng.gen::<Closed01<f64>>();
263             assert!(0.0 <= f && f <= 1.0);
264
265             let Closed01(f) = rng.gen::<Closed01<f32>>();
266             assert!(0.0 <= f && f <= 1.0);
267         }
268     }
269 }