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