]> git.lizzy.rs Git - rust.git/blob - src/librand/rand_impls.rs
std: Clean out deprecated APIs
[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::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 impl Rand for usize {
58     #[inline]
59     fn rand<R: Rng>(rng: &mut R) -> usize {
60         if mem::size_of::<usize>() == 4 {
61             rng.gen::<u32>() as usize
62         } else {
63             rng.gen::<u64>() as usize
64         }
65     }
66 }
67
68 impl Rand for u8 {
69     #[inline]
70     fn rand<R: Rng>(rng: &mut R) -> u8 {
71         rng.next_u32() as u8
72     }
73 }
74
75 impl Rand for u16 {
76     #[inline]
77     fn rand<R: Rng>(rng: &mut R) -> u16 {
78         rng.next_u32() as u16
79     }
80 }
81
82 impl Rand for u32 {
83     #[inline]
84     fn rand<R: Rng>(rng: &mut R) -> u32 {
85         rng.next_u32()
86     }
87 }
88
89 impl Rand for u64 {
90     #[inline]
91     fn rand<R: Rng>(rng: &mut R) -> u64 {
92         rng.next_u64()
93     }
94 }
95
96 macro_rules! float_impls {
97     ($mod_name:ident, $ty:ty, $mantissa_bits:expr, $method_name:ident) => {
98         mod $mod_name {
99             use {Rand, Rng, Open01, Closed01};
100
101             const SCALE: $ty = (1u64 << $mantissa_bits) as $ty;
102
103             impl Rand for $ty {
104                 /// Generate a floating point number in the half-open
105                 /// interval `[0,1)`.
106                 ///
107                 /// See `Closed01` for the closed interval `[0,1]`,
108                 /// and `Open01` for the open interval `(0,1)`.
109                 #[inline]
110                 fn rand<R: Rng>(rng: &mut R) -> $ty {
111                     rng.$method_name()
112                 }
113             }
114             impl Rand for Open01<$ty> {
115                 #[inline]
116                 fn rand<R: Rng>(rng: &mut R) -> Open01<$ty> {
117                     // add a small amount (specifically 2 bits below
118                     // the precision of f64/f32 at 1.0), so that small
119                     // numbers are larger than 0, but large numbers
120                     // aren't pushed to/above 1.
121                     Open01(rng.$method_name() + 0.25 / SCALE)
122                 }
123             }
124             impl Rand for Closed01<$ty> {
125                 #[inline]
126                 fn rand<R: Rng>(rng: &mut R) -> Closed01<$ty> {
127                     // rescale so that 1.0 - epsilon becomes 1.0
128                     // precisely.
129                     Closed01(rng.$method_name() * SCALE / (SCALE - 1.0))
130                 }
131             }
132         }
133     }
134 }
135 float_impls! { f64_rand_impls, f64, 53, next_f64 }
136 float_impls! { f32_rand_impls, f32, 24, next_f32 }
137
138 impl Rand for char {
139     #[inline]
140     fn rand<R: Rng>(rng: &mut R) -> char {
141         // a char is 21 bits
142         const CHAR_MASK: u32 = 0x001f_ffff;
143         loop {
144             // Rejection sampling. About 0.2% of numbers with at most
145             // 21-bits are invalid codepoints (surrogates), so this
146             // will succeed first go almost every time.
147             match char::from_u32(rng.next_u32() & CHAR_MASK) {
148                 Some(c) => return c,
149                 None => {}
150             }
151         }
152     }
153 }
154
155 impl Rand for bool {
156     #[inline]
157     fn rand<R: Rng>(rng: &mut R) -> bool {
158         rng.gen::<u8>() & 1 == 1
159     }
160 }
161
162 macro_rules! tuple_impl {
163     // use variables to indicate the arity of the tuple
164     ($($tyvar:ident),* ) => {
165         // the trailing commas are for the 1 tuple
166         impl<
167             $( $tyvar : Rand ),*
168             > Rand for ( $( $tyvar ),* , ) {
169
170             #[inline]
171             fn rand<R: Rng>(_rng: &mut R) -> ( $( $tyvar ),* , ) {
172                 (
173                     // use the $tyvar's to get the appropriate number of
174                     // repeats (they're not actually needed)
175                     $(
176                         _rng.gen::<$tyvar>()
177                     ),*
178                     ,
179                 )
180             }
181         }
182     }
183 }
184
185 impl Rand for () {
186     #[inline]
187     fn rand<R: Rng>(_: &mut R) -> () {
188         ()
189     }
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 }