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 {Rng}; 15 use 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 {Rng, RngCore, Standard}; 180 use 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 RngCore = &mut ::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 = ::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 = ::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