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 integer types.
10 
11 use crate::distributions::{Distribution, Standard};
12 use crate::Rng;
13 #[cfg(all(target_arch = "x86", feature = "simd_support"))]
14 use core::arch::x86::{__m128i, __m256i};
15 #[cfg(all(target_arch = "x86_64", feature = "simd_support"))]
16 use core::arch::x86_64::{__m128i, __m256i};
17 #[cfg(not(target_os = "emscripten"))] use core::num::NonZeroU128;
18 use core::num::{NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize};
19 #[cfg(feature = "simd_support")] use packed_simd::*;
20 
21 impl Distribution<u8> for Standard {
22     #[inline]
sample<R: Rng + ?Sized>(&self, rng: &mut R) -> u823     fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> u8 {
24         rng.next_u32() as u8
25     }
26 }
27 
28 impl Distribution<u16> for Standard {
29     #[inline]
sample<R: Rng + ?Sized>(&self, rng: &mut R) -> u1630     fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> u16 {
31         rng.next_u32() as u16
32     }
33 }
34 
35 impl Distribution<u32> for Standard {
36     #[inline]
sample<R: Rng + ?Sized>(&self, rng: &mut R) -> u3237     fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> u32 {
38         rng.next_u32()
39     }
40 }
41 
42 impl Distribution<u64> for Standard {
43     #[inline]
sample<R: Rng + ?Sized>(&self, rng: &mut R) -> u6444     fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> u64 {
45         rng.next_u64()
46     }
47 }
48 
49 #[cfg(not(target_os = "emscripten"))]
50 impl Distribution<u128> for Standard {
51     #[inline]
sample<R: Rng + ?Sized>(&self, rng: &mut R) -> u12852     fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> u128 {
53         // Use LE; we explicitly generate one value before the next.
54         let x = u128::from(rng.next_u64());
55         let y = u128::from(rng.next_u64());
56         (y << 64) | x
57     }
58 }
59 
60 impl Distribution<usize> for Standard {
61     #[inline]
62     #[cfg(any(target_pointer_width = "32", target_pointer_width = "16"))]
sample<R: Rng + ?Sized>(&self, rng: &mut R) -> usize63     fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> usize {
64         rng.next_u32() as usize
65     }
66 
67     #[inline]
68     #[cfg(target_pointer_width = "64")]
sample<R: Rng + ?Sized>(&self, rng: &mut R) -> usize69     fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> usize {
70         rng.next_u64() as usize
71     }
72 }
73 
74 macro_rules! impl_int_from_uint {
75     ($ty:ty, $uty:ty) => {
76         impl Distribution<$ty> for Standard {
77             #[inline]
78             fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> $ty {
79                 rng.gen::<$uty>() as $ty
80             }
81         }
82     };
83 }
84 
85 impl_int_from_uint! { i8, u8 }
86 impl_int_from_uint! { i16, u16 }
87 impl_int_from_uint! { i32, u32 }
88 impl_int_from_uint! { i64, u64 }
89 #[cfg(not(target_os = "emscripten"))]
90 impl_int_from_uint! { i128, u128 }
91 impl_int_from_uint! { isize, usize }
92 
93 macro_rules! impl_nzint {
94     ($ty:ty, $new:path) => {
95         impl Distribution<$ty> for Standard {
96             fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> $ty {
97                 loop {
98                     if let Some(nz) = $new(rng.gen()) {
99                         break nz;
100                     }
101                 }
102             }
103         }
104     };
105 }
106 
107 impl_nzint!(NonZeroU8, NonZeroU8::new);
108 impl_nzint!(NonZeroU16, NonZeroU16::new);
109 impl_nzint!(NonZeroU32, NonZeroU32::new);
110 impl_nzint!(NonZeroU64, NonZeroU64::new);
111 #[cfg(not(target_os = "emscripten"))]
112 impl_nzint!(NonZeroU128, NonZeroU128::new);
113 impl_nzint!(NonZeroUsize, NonZeroUsize::new);
114 
115 #[cfg(feature = "simd_support")]
116 macro_rules! simd_impl {
117     ($(($intrinsic:ident, $vec:ty),)+) => {$(
118         impl Distribution<$intrinsic> for Standard {
119             #[inline]
120             fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> $intrinsic {
121                 $intrinsic::from_bits(rng.gen::<$vec>())
122             }
123         }
124     )+};
125 
126     ($bits:expr,) => {};
127     ($bits:expr, $ty:ty, $($ty_more:ty,)*) => {
128         simd_impl!($bits, $($ty_more,)*);
129 
130         impl Distribution<$ty> for Standard {
131             #[inline]
132             fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> $ty {
133                 let mut vec: $ty = Default::default();
134                 unsafe {
135                     let ptr = &mut vec;
136                     let b_ptr = &mut *(ptr as *mut $ty as *mut [u8; $bits/8]);
137                     rng.fill_bytes(b_ptr);
138                 }
139                 vec.to_le()
140             }
141         }
142     };
143 }
144 
145 #[cfg(feature = "simd_support")]
146 simd_impl!(16, u8x2, i8x2,);
147 #[cfg(feature = "simd_support")]
148 simd_impl!(32, u8x4, i8x4, u16x2, i16x2,);
149 #[cfg(feature = "simd_support")]
150 simd_impl!(64, u8x8, i8x8, u16x4, i16x4, u32x2, i32x2,);
151 #[cfg(feature = "simd_support")]
152 simd_impl!(128, u8x16, i8x16, u16x8, i16x8, u32x4, i32x4, u64x2, i64x2,);
153 #[cfg(feature = "simd_support")]
154 simd_impl!(256, u8x32, i8x32, u16x16, i16x16, u32x8, i32x8, u64x4, i64x4,);
155 #[cfg(feature = "simd_support")]
156 simd_impl!(512, u8x64, i8x64, u16x32, i16x32, u32x16, i32x16, u64x8, i64x8,);
157 #[cfg(all(
158     feature = "simd_support",
159     any(target_arch = "x86", target_arch = "x86_64")
160 ))]
161 simd_impl!((__m128i, u8x16), (__m256i, u8x32),);
162 
163 #[cfg(test)]
164 mod tests {
165     use super::*;
166 
167     #[test]
test_integers()168     fn test_integers() {
169         let mut rng = crate::test::rng(806);
170 
171         rng.sample::<isize, _>(Standard);
172         rng.sample::<i8, _>(Standard);
173         rng.sample::<i16, _>(Standard);
174         rng.sample::<i32, _>(Standard);
175         rng.sample::<i64, _>(Standard);
176         #[cfg(not(target_os = "emscripten"))]
177         rng.sample::<i128, _>(Standard);
178 
179         rng.sample::<usize, _>(Standard);
180         rng.sample::<u8, _>(Standard);
181         rng.sample::<u16, _>(Standard);
182         rng.sample::<u32, _>(Standard);
183         rng.sample::<u64, _>(Standard);
184         #[cfg(not(target_os = "emscripten"))]
185         rng.sample::<u128, _>(Standard);
186     }
187 
188     #[test]
value_stability()189     fn value_stability() {
190         fn test_samples<T: Copy + core::fmt::Debug + PartialEq>(zero: T, expected: &[T])
191         where Standard: Distribution<T> {
192             let mut rng = crate::test::rng(807);
193             let mut buf = [zero; 3];
194             for x in &mut buf {
195                 *x = rng.sample(Standard);
196             }
197             assert_eq!(&buf, expected);
198         }
199 
200         test_samples(0u8, &[9, 247, 111]);
201         test_samples(0u16, &[32265, 42999, 38255]);
202         test_samples(0u32, &[2220326409, 2575017975, 2018088303]);
203         test_samples(0u64, &[
204             11059617991457472009,
205             16096616328739788143,
206             1487364411147516184,
207         ]);
208         test_samples(0u128, &[
209             296930161868957086625409848350820761097,
210             145644820879247630242265036535529306392,
211             111087889832015897993126088499035356354,
212         ]);
213         #[cfg(any(target_pointer_width = "32", target_pointer_width = "16"))]
214         test_samples(0usize, &[2220326409, 2575017975, 2018088303]);
215         #[cfg(target_pointer_width = "64")]
216         test_samples(0usize, &[
217             11059617991457472009,
218             16096616328739788143,
219             1487364411147516184,
220         ]);
221 
222         test_samples(0i8, &[9, -9, 111]);
223         // Skip further i* types: they are simple reinterpretation of u* samples
224 
225         #[cfg(feature = "simd_support")]
226         {
227             // We only test a sub-set of types here and make assumptions about the rest.
228 
229             test_samples(u8x2::default(), &[
230                 u8x2::new(9, 126),
231                 u8x2::new(247, 167),
232                 u8x2::new(111, 149),
233             ]);
234             test_samples(u8x4::default(), &[
235                 u8x4::new(9, 126, 87, 132),
236                 u8x4::new(247, 167, 123, 153),
237                 u8x4::new(111, 149, 73, 120),
238             ]);
239             test_samples(u8x8::default(), &[
240                 u8x8::new(9, 126, 87, 132, 247, 167, 123, 153),
241                 u8x8::new(111, 149, 73, 120, 68, 171, 98, 223),
242                 u8x8::new(24, 121, 1, 50, 13, 46, 164, 20),
243             ]);
244 
245             test_samples(i64x8::default(), &[
246                 i64x8::new(
247                     -7387126082252079607,
248                     -2350127744969763473,
249                     1487364411147516184,
250                     7895421560427121838,
251                     602190064936008898,
252                     6022086574635100741,
253                     -5080089175222015595,
254                     -4066367846667249123,
255                 ),
256                 i64x8::new(
257                     9180885022207963908,
258                     3095981199532211089,
259                     6586075293021332726,
260                     419343203796414657,
261                     3186951873057035255,
262                     5287129228749947252,
263                     444726432079249540,
264                     -1587028029513790706,
265                 ),
266                 i64x8::new(
267                     6075236523189346388,
268                     1351763722368165432,
269                     -6192309979959753740,
270                     -7697775502176768592,
271                     -4482022114172078123,
272                     7522501477800909500,
273                     -1837258847956201231,
274                     -586926753024886735,
275                 ),
276             ]);
277         }
278     }
279 }
280