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 = "nightly"))] use core::arch::x86::*; 14 #[cfg(all(target_arch = "x86_64", feature = "nightly"))] 15 use core::arch::x86_64::*; 16 #[cfg(not(target_os = "emscripten"))] use core::num::NonZeroU128; 17 use core::num::{NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize}; 18 #[cfg(feature = "simd_support")] use packed_simd::*; 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(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 = u128::from(rng.next_u64()); 54 let y = u128::from(rng.next_u64()); 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(not(target_os = "emscripten"))] 89 impl_int_from_uint! { i128, u128 } 90 impl_int_from_uint! { isize, usize } 91 92 macro_rules! impl_nzint { 93 ($ty:ty, $new:path) => { 94 impl Distribution<$ty> for Standard { 95 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> $ty { 96 loop { 97 if let Some(nz) = $new(rng.gen()) { 98 break nz; 99 } 100 } 101 } 102 } 103 }; 104 } 105 106 impl_nzint!(NonZeroU8, NonZeroU8::new); 107 impl_nzint!(NonZeroU16, NonZeroU16::new); 108 impl_nzint!(NonZeroU32, NonZeroU32::new); 109 impl_nzint!(NonZeroU64, NonZeroU64::new); 110 #[cfg(not(target_os = "emscripten"))] 111 impl_nzint!(NonZeroU128, NonZeroU128::new); 112 impl_nzint!(NonZeroUsize, NonZeroUsize::new); 113 114 #[cfg(feature = "simd_support")] 115 macro_rules! simd_impl { 116 ($(($intrinsic:ident, $vec:ty),)+) => {$( 117 impl Distribution<$intrinsic> for Standard { 118 #[inline] 119 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> $intrinsic { 120 $intrinsic::from_bits(rng.gen::<$vec>()) 121 } 122 } 123 )+}; 124 125 ($bits:expr,) => {}; 126 ($bits:expr, $ty:ty, $($ty_more:ty,)*) => { 127 simd_impl!($bits, $($ty_more,)*); 128 129 impl Distribution<$ty> for Standard { 130 #[inline] 131 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> $ty { 132 let mut vec: $ty = Default::default(); 133 unsafe { 134 let ptr = &mut vec; 135 let b_ptr = &mut *(ptr as *mut $ty as *mut [u8; $bits/8]); 136 rng.fill_bytes(b_ptr); 137 } 138 vec.to_le() 139 } 140 } 141 }; 142 } 143 144 #[cfg(feature = "simd_support")] 145 simd_impl!(16, u8x2, i8x2,); 146 #[cfg(feature = "simd_support")] 147 simd_impl!(32, u8x4, i8x4, u16x2, i16x2,); 148 #[cfg(feature = "simd_support")] 149 simd_impl!(64, u8x8, i8x8, u16x4, i16x4, u32x2, i32x2,); 150 #[cfg(feature = "simd_support")] 151 simd_impl!(128, u8x16, i8x16, u16x8, i16x8, u32x4, i32x4, u64x2, i64x2,); 152 #[cfg(feature = "simd_support")] 153 simd_impl!(256, u8x32, i8x32, u16x16, i16x16, u32x8, i32x8, u64x4, i64x4,); 154 #[cfg(feature = "simd_support")] 155 simd_impl!(512, u8x64, i8x64, u16x32, i16x32, u32x16, i32x16, u64x8, i64x8,); 156 #[cfg(all( 157 feature = "simd_support", 158 feature = "nightly", 159 any(target_arch = "x86", target_arch = "x86_64") 160 ))] 161 simd_impl!((__m64, u8x8), (__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