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 {Rng};
12 use distributions::{Distribution, Standard};
13 #[cfg(feature="simd_support")]
14 use packed_simd::*;
15 #[cfg(all(target_arch = "x86", feature="nightly"))]
16 use core::arch::x86::*;
17 #[cfg(all(target_arch = "x86_64", feature="nightly"))]
18 use core::arch::x86_64::*;
19 
20 impl Distribution<u8> for Standard {
21     #[inline]
sample<R: Rng + ?Sized>(&self, rng: &mut R) -> u822     fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> u8 {
23         rng.next_u32() as u8
24     }
25 }
26 
27 impl Distribution<u16> for Standard {
28     #[inline]
sample<R: Rng + ?Sized>(&self, rng: &mut R) -> u1629     fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> u16 {
30         rng.next_u32() as u16
31     }
32 }
33 
34 impl Distribution<u32> for Standard {
35     #[inline]
sample<R: Rng + ?Sized>(&self, rng: &mut R) -> u3236     fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> u32 {
37         rng.next_u32()
38     }
39 }
40 
41 impl Distribution<u64> for Standard {
42     #[inline]
sample<R: Rng + ?Sized>(&self, rng: &mut R) -> u6443     fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> u64 {
44         rng.next_u64()
45     }
46 }
47 
48 #[cfg(all(rustc_1_26, not(target_os = "emscripten")))]
49 impl Distribution<u128> for Standard {
50     #[inline]
sample<R: Rng + ?Sized>(&self, rng: &mut R) -> u12851     fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> u128 {
52         // Use LE; we explicitly generate one value before the next.
53         let x = rng.next_u64() as u128;
54         let y = rng.next_u64() as u128;
55         (y << 64) | x
56     }
57 }
58 
59 impl Distribution<usize> for Standard {
60     #[inline]
61     #[cfg(any(target_pointer_width = "32", target_pointer_width = "16"))]
sample<R: Rng + ?Sized>(&self, rng: &mut R) -> usize62     fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> usize {
63         rng.next_u32() as usize
64     }
65 
66     #[inline]
67     #[cfg(target_pointer_width = "64")]
sample<R: Rng + ?Sized>(&self, rng: &mut R) -> usize68     fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> usize {
69         rng.next_u64() as usize
70     }
71 }
72 
73 macro_rules! impl_int_from_uint {
74     ($ty:ty, $uty:ty) => {
75         impl Distribution<$ty> for Standard {
76             #[inline]
77             fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> $ty {
78                 rng.gen::<$uty>() as $ty
79             }
80         }
81     }
82 }
83 
84 impl_int_from_uint! { i8, u8 }
85 impl_int_from_uint! { i16, u16 }
86 impl_int_from_uint! { i32, u32 }
87 impl_int_from_uint! { i64, u64 }
88 #[cfg(all(rustc_1_26, not(target_os = "emscripten")))] impl_int_from_uint! { i128, u128 }
89 impl_int_from_uint! { isize, usize }
90 
91 #[cfg(feature="simd_support")]
92 macro_rules! simd_impl {
93     ($(($intrinsic:ident, $vec:ty),)+) => {$(
94         impl Distribution<$intrinsic> for Standard {
95             #[inline]
96             fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> $intrinsic {
97                 $intrinsic::from_bits(rng.gen::<$vec>())
98             }
99         }
100     )+};
101 
102     ($bits:expr,) => {};
103     ($bits:expr, $ty:ty, $($ty_more:ty,)*) => {
104         simd_impl!($bits, $($ty_more,)*);
105 
106         impl Distribution<$ty> for Standard {
107             #[inline]
108             fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> $ty {
109                 let mut vec: $ty = Default::default();
110                 unsafe {
111                     let ptr = &mut vec;
112                     let b_ptr = &mut *(ptr as *mut $ty as *mut [u8; $bits/8]);
113                     rng.fill_bytes(b_ptr);
114                 }
115                 vec.to_le()
116             }
117         }
118     };
119 }
120 
121 #[cfg(feature="simd_support")]
122 simd_impl!(16, u8x2, i8x2,);
123 #[cfg(feature="simd_support")]
124 simd_impl!(32, u8x4, i8x4, u16x2, i16x2,);
125 #[cfg(feature="simd_support")]
126 simd_impl!(64, u8x8, i8x8, u16x4, i16x4, u32x2, i32x2,);
127 #[cfg(feature="simd_support")]
128 simd_impl!(128, u8x16, i8x16, u16x8, i16x8, u32x4, i32x4, u64x2, i64x2,);
129 #[cfg(feature="simd_support")]
130 simd_impl!(256, u8x32, i8x32, u16x16, i16x16, u32x8, i32x8, u64x4, i64x4,);
131 #[cfg(feature="simd_support")]
132 simd_impl!(512, u8x64, i8x64, u16x32, i16x32, u32x16, i32x16, u64x8, i64x8,);
133 #[cfg(all(feature="simd_support", feature="nightly", any(target_arch="x86", target_arch="x86_64")))]
134 simd_impl!((__m64, u8x8), (__m128i, u8x16), (__m256i, u8x32),);
135 
136 #[cfg(test)]
137 mod tests {
138     use Rng;
139     use distributions::{Standard};
140 
141     #[test]
test_integers()142     fn test_integers() {
143         let mut rng = ::test::rng(806);
144 
145         rng.sample::<isize, _>(Standard);
146         rng.sample::<i8, _>(Standard);
147         rng.sample::<i16, _>(Standard);
148         rng.sample::<i32, _>(Standard);
149         rng.sample::<i64, _>(Standard);
150         #[cfg(all(rustc_1_26, not(target_os = "emscripten")))]
151         rng.sample::<i128, _>(Standard);
152 
153         rng.sample::<usize, _>(Standard);
154         rng.sample::<u8, _>(Standard);
155         rng.sample::<u16, _>(Standard);
156         rng.sample::<u32, _>(Standard);
157         rng.sample::<u64, _>(Standard);
158         #[cfg(all(rustc_1_26, not(target_os = "emscripten")))]
159         rng.sample::<u128, _>(Standard);
160     }
161 }
162