1 // Copyright 2018 Developers of the Rand project.
2 //
3 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4 // https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5 // <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
6 // option. This file may not be copied, modified, or distributed
7 // except according to those terms.
8 
9 //! The implementations of the `Standard` distribution for other built-in types.
10 
11 use core::char;
12 use core::num::Wrapping;
13 
14 use crate::{Rng};
15 use crate::distributions::{Distribution, Standard, Uniform};
16 
17 // ----- Sampling distributions -----
18 
19 /// Sample a `char`, uniformly distributed over ASCII letters and numbers:
20 /// a-z, A-Z and 0-9.
21 ///
22 /// # Example
23 ///
24 /// ```
25 /// use std::iter;
26 /// use rand::{Rng, thread_rng};
27 /// use rand::distributions::Alphanumeric;
28 ///
29 /// let mut rng = thread_rng();
30 /// let chars: String = iter::repeat(())
31 ///         .map(|()| rng.sample(Alphanumeric))
32 ///         .take(7)
33 ///         .collect();
34 /// println!("Random chars: {}", chars);
35 /// ```
36 #[derive(Debug)]
37 pub struct Alphanumeric;
38 
39 
40 // ----- Implementations of distributions -----
41 
42 impl Distribution<char> for Standard {
43     #[inline]
sample<R: Rng + ?Sized>(&self, rng: &mut R) -> char44     fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> char {
45         // A valid `char` is either in the interval `[0, 0xD800)` or
46         // `(0xDFFF, 0x11_0000)`. All `char`s must therefore be in
47         // `[0, 0x11_0000)` but not in the "gap" `[0xD800, 0xDFFF]` which is
48         // reserved for surrogates. This is the size of that gap.
49         const GAP_SIZE: u32 = 0xDFFF - 0xD800 + 1;
50 
51         // Uniform::new(0, 0x11_0000 - GAP_SIZE) can also be used but it
52         // seemed slower.
53         let range = Uniform::new(GAP_SIZE, 0x11_0000);
54 
55         let mut n = range.sample(rng);
56         if n <= 0xDFFF {
57             n -= GAP_SIZE;
58         }
59         unsafe { char::from_u32_unchecked(n) }
60     }
61 }
62 
63 impl Distribution<char> for Alphanumeric {
sample<R: Rng + ?Sized>(&self, rng: &mut R) -> char64     fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> char {
65         const RANGE: u32 = 26 + 26 + 10;
66         const GEN_ASCII_STR_CHARSET: &[u8] =
67             b"ABCDEFGHIJKLMNOPQRSTUVWXYZ\
68                 abcdefghijklmnopqrstuvwxyz\
69                 0123456789";
70         // We can pick from 62 characters. This is so close to a power of 2, 64,
71         // that we can do better than `Uniform`. Use a simple bitshift and
72         // rejection sampling. We do not use a bitmask, because for small RNGs
73         // the most significant bits are usually of higher quality.
74         loop {
75             let var = rng.next_u32() >> (32 - 6);
76             if var < RANGE {
77                 return GEN_ASCII_STR_CHARSET[var as usize] as char
78             }
79         }
80     }
81 }
82 
83 impl Distribution<bool> for Standard {
84     #[inline]
sample<R: Rng + ?Sized>(&self, rng: &mut R) -> bool85     fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> bool {
86         // We can compare against an arbitrary bit of an u32 to get a bool.
87         // Because the least significant bits of a lower quality RNG can have
88         // simple patterns, we compare against the most significant bit. This is
89         // easiest done using a sign test.
90         (rng.next_u32() as i32) < 0
91     }
92 }
93 
94 macro_rules! tuple_impl {
95     // use variables to indicate the arity of the tuple
96     ($($tyvar:ident),* ) => {
97         // the trailing commas are for the 1 tuple
98         impl< $( $tyvar ),* >
99             Distribution<( $( $tyvar ),* , )>
100             for Standard
101             where $( Standard: Distribution<$tyvar> ),*
102         {
103             #[inline]
104             fn sample<R: Rng + ?Sized>(&self, _rng: &mut R) -> ( $( $tyvar ),* , ) {
105                 (
106                     // use the $tyvar's to get the appropriate number of
107                     // repeats (they're not actually needed)
108                     $(
109                         _rng.gen::<$tyvar>()
110                     ),*
111                     ,
112                 )
113             }
114         }
115     }
116 }
117 
118 impl Distribution<()> for Standard {
119     #[inline]
sample<R: Rng + ?Sized>(&self, _: &mut R) -> ()120     fn sample<R: Rng + ?Sized>(&self, _: &mut R) -> () { () }
121 }
122 tuple_impl!{A}
123 tuple_impl!{A, B}
124 tuple_impl!{A, B, C}
125 tuple_impl!{A, B, C, D}
126 tuple_impl!{A, B, C, D, E}
127 tuple_impl!{A, B, C, D, E, F}
128 tuple_impl!{A, B, C, D, E, F, G}
129 tuple_impl!{A, B, C, D, E, F, G, H}
130 tuple_impl!{A, B, C, D, E, F, G, H, I}
131 tuple_impl!{A, B, C, D, E, F, G, H, I, J}
132 tuple_impl!{A, B, C, D, E, F, G, H, I, J, K}
133 tuple_impl!{A, B, C, D, E, F, G, H, I, J, K, L}
134 
135 macro_rules! array_impl {
136     // recursive, given at least one type parameter:
137     {$n:expr, $t:ident, $($ts:ident,)*} => {
138         array_impl!{($n - 1), $($ts,)*}
139 
140         impl<T> Distribution<[T; $n]> for Standard where Standard: Distribution<T> {
141             #[inline]
142             fn sample<R: Rng + ?Sized>(&self, _rng: &mut R) -> [T; $n] {
143                 [_rng.gen::<$t>(), $(_rng.gen::<$ts>()),*]
144             }
145         }
146     };
147     // empty case:
148     {$n:expr,} => {
149         impl<T> Distribution<[T; $n]> for Standard {
150             fn sample<R: Rng + ?Sized>(&self, _rng: &mut R) -> [T; $n] { [] }
151         }
152     };
153 }
154 
155 array_impl!{32, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,}
156 
157 impl<T> Distribution<Option<T>> for Standard where Standard: Distribution<T> {
158     #[inline]
sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Option<T>159     fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Option<T> {
160         // UFCS is needed here: https://github.com/rust-lang/rust/issues/24066
161         if rng.gen::<bool>() {
162             Some(rng.gen())
163         } else {
164             None
165         }
166     }
167 }
168 
169 impl<T> Distribution<Wrapping<T>> for Standard where Standard: Distribution<T> {
170     #[inline]
sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Wrapping<T>171     fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Wrapping<T> {
172         Wrapping(rng.gen())
173     }
174 }
175 
176 
177 #[cfg(test)]
178 mod tests {
179     use crate::{Rng, RngCore, Standard};
180     use crate::distributions::Alphanumeric;
181     #[cfg(all(not(feature="std"), feature="alloc"))] use alloc::string::String;
182 
183     #[test]
test_misc()184     fn test_misc() {
185         let rng: &mut dyn RngCore = &mut crate::test::rng(820);
186 
187         rng.sample::<char, _>(Standard);
188         rng.sample::<bool, _>(Standard);
189     }
190 
191     #[cfg(feature="alloc")]
192     #[test]
test_chars()193     fn test_chars() {
194         use core::iter;
195         let mut rng = crate::test::rng(805);
196 
197         // Test by generating a relatively large number of chars, so we also
198         // take the rejection sampling path.
199         let word: String = iter::repeat(())
200                 .map(|()| rng.gen::<char>()).take(1000).collect();
201         assert!(word.len() != 0);
202     }
203 
204     #[test]
test_alphanumeric()205     fn test_alphanumeric() {
206         let mut rng = crate::test::rng(806);
207 
208         // Test by generating a relatively large number of chars, so we also
209         // take the rejection sampling path.
210         let mut incorrect = false;
211         for _ in 0..100 {
212             let c = rng.sample(Alphanumeric);
213             incorrect |= !((c >= '0' && c <= '9') ||
214                            (c >= 'A' && c <= 'Z') ||
215                            (c >= 'a' && c <= 'z') );
216         }
217         assert!(incorrect == false);
218     }
219 }
220