]>
Commit | Line | Data |
---|---|---|
1a4d82fc JJ |
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 | ||
1a4d82fc | 13 | use core::char; |
54a0048b | 14 | use core::mem; |
1a4d82fc | 15 | |
b039eaaf | 16 | use {Rand, Rng}; |
1a4d82fc | 17 | |
c34b1796 | 18 | impl Rand for isize { |
1a4d82fc | 19 | #[inline] |
c34b1796 | 20 | fn rand<R: Rng>(rng: &mut R) -> isize { |
54a0048b | 21 | if mem::size_of::<isize>() == 4 { |
c34b1796 | 22 | rng.gen::<i32>() as isize |
1a4d82fc | 23 | } else { |
c34b1796 | 24 | rng.gen::<i64>() as isize |
1a4d82fc JJ |
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 | ||
c34b1796 | 57 | impl Rand for usize { |
1a4d82fc | 58 | #[inline] |
c34b1796 | 59 | fn rand<R: Rng>(rng: &mut R) -> usize { |
54a0048b | 60 | if mem::size_of::<usize>() == 4 { |
c34b1796 | 61 | rng.gen::<u32>() as usize |
1a4d82fc | 62 | } else { |
c34b1796 | 63 | rng.gen::<u64>() as usize |
1a4d82fc JJ |
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 | |
c34b1796 | 142 | const CHAR_MASK: u32 = 0x001f_ffff; |
1a4d82fc JJ |
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] | |
b039eaaf SL |
187 | fn rand<R: Rng>(_: &mut R) -> () { |
188 | () | |
189 | } | |
1a4d82fc JJ |
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 | ||
92a42be0 | 204 | impl<T: Rand> Rand for Option<T> { |
1a4d82fc JJ |
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 | } |