Coverage Report

Created: 2025-02-25 06:39

/rust/registry/src/index.crates.io-6f17d22bba15001f/rand-0.9.0/src/distr/integer.rs
Line
Count
Source (jump to first uncovered line)
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 `StandardUniform` distribution for integer types.
10
11
use crate::distr::{Distribution, StandardUniform};
12
use crate::Rng;
13
#[cfg(all(target_arch = "x86", feature = "simd_support"))]
14
use core::arch::x86::__m512i;
15
#[cfg(target_arch = "x86")]
16
use core::arch::x86::{__m128i, __m256i};
17
#[cfg(all(target_arch = "x86_64", feature = "simd_support"))]
18
use core::arch::x86_64::__m512i;
19
#[cfg(target_arch = "x86_64")]
20
use core::arch::x86_64::{__m128i, __m256i};
21
use core::num::{
22
    NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroU128, NonZeroU16,
23
    NonZeroU32, NonZeroU64, NonZeroU8,
24
};
25
#[cfg(feature = "simd_support")]
26
use core::simd::*;
27
28
impl Distribution<u8> for StandardUniform {
29
    #[inline]
30
0
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> u8 {
31
0
        rng.next_u32() as u8
32
0
    }
33
}
34
35
impl Distribution<u16> for StandardUniform {
36
    #[inline]
37
0
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> u16 {
38
0
        rng.next_u32() as u16
39
0
    }
Unexecuted instantiation: <rand::distr::StandardUniform as rand::distr::distribution::Distribution<u16>>::sample::<rand::rngs::thread::ThreadRng>
Unexecuted instantiation: <rand::distr::StandardUniform as rand::distr::distribution::Distribution<u16>>::sample::<_>
40
}
41
42
impl Distribution<u32> for StandardUniform {
43
    #[inline]
44
0
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> u32 {
45
0
        rng.next_u32()
46
0
    }
Unexecuted instantiation: <rand::distr::StandardUniform as rand::distr::distribution::Distribution<u32>>::sample::<rand::rngs::thread::ThreadRng>
Unexecuted instantiation: <rand::distr::StandardUniform as rand::distr::distribution::Distribution<u32>>::sample::<&mut rand::rngs::thread::ThreadRng>
Unexecuted instantiation: <rand::distr::StandardUniform as rand::distr::distribution::Distribution<u32>>::sample::<_>
47
}
48
49
impl Distribution<u64> for StandardUniform {
50
    #[inline]
51
0
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> u64 {
52
0
        rng.next_u64()
53
0
    }
Unexecuted instantiation: <rand::distr::StandardUniform as rand::distr::distribution::Distribution<u64>>::sample::<rand::rngs::thread::ThreadRng>
Unexecuted instantiation: <rand::distr::StandardUniform as rand::distr::distribution::Distribution<u64>>::sample::<_>
54
}
55
56
impl Distribution<u128> for StandardUniform {
57
    #[inline]
58
0
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> u128 {
59
0
        // Use LE; we explicitly generate one value before the next.
60
0
        let x = u128::from(rng.next_u64());
61
0
        let y = u128::from(rng.next_u64());
62
0
        (y << 64) | x
63
0
    }
Unexecuted instantiation: <rand::distr::StandardUniform as rand::distr::distribution::Distribution<u128>>::sample::<rand::rngs::thread::ThreadRng>
Unexecuted instantiation: <rand::distr::StandardUniform as rand::distr::distribution::Distribution<u128>>::sample::<_>
64
}
65
66
macro_rules! impl_int_from_uint {
67
    ($ty:ty, $uty:ty) => {
68
        impl Distribution<$ty> for StandardUniform {
69
            #[inline]
70
0
            fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> $ty {
71
0
                rng.random::<$uty>() as $ty
72
0
            }
Unexecuted instantiation: <rand::distr::StandardUniform as rand::distr::distribution::Distribution<i8>>::sample::<_>
Unexecuted instantiation: <rand::distr::StandardUniform as rand::distr::distribution::Distribution<i16>>::sample::<_>
Unexecuted instantiation: <rand::distr::StandardUniform as rand::distr::distribution::Distribution<i32>>::sample::<_>
Unexecuted instantiation: <rand::distr::StandardUniform as rand::distr::distribution::Distribution<i64>>::sample::<_>
Unexecuted instantiation: <rand::distr::StandardUniform as rand::distr::distribution::Distribution<i128>>::sample::<_>
73
        }
74
    };
75
}
76
77
impl_int_from_uint! { i8, u8 }
78
impl_int_from_uint! { i16, u16 }
79
impl_int_from_uint! { i32, u32 }
80
impl_int_from_uint! { i64, u64 }
81
impl_int_from_uint! { i128, u128 }
82
83
macro_rules! impl_nzint {
84
    ($ty:ty, $new:path) => {
85
        impl Distribution<$ty> for StandardUniform {
86
0
            fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> $ty {
87
                loop {
88
0
                    if let Some(nz) = $new(rng.random()) {
89
0
                        break nz;
90
0
                    }
91
                }
92
0
            }
Unexecuted instantiation: <rand::distr::StandardUniform as rand::distr::distribution::Distribution<core::num::nonzero::NonZero<u8>>>::sample::<_>
Unexecuted instantiation: <rand::distr::StandardUniform as rand::distr::distribution::Distribution<core::num::nonzero::NonZero<u16>>>::sample::<_>
Unexecuted instantiation: <rand::distr::StandardUniform as rand::distr::distribution::Distribution<core::num::nonzero::NonZero<u32>>>::sample::<_>
Unexecuted instantiation: <rand::distr::StandardUniform as rand::distr::distribution::Distribution<core::num::nonzero::NonZero<u64>>>::sample::<_>
Unexecuted instantiation: <rand::distr::StandardUniform as rand::distr::distribution::Distribution<core::num::nonzero::NonZero<u128>>>::sample::<_>
Unexecuted instantiation: <rand::distr::StandardUniform as rand::distr::distribution::Distribution<core::num::nonzero::NonZero<i8>>>::sample::<_>
Unexecuted instantiation: <rand::distr::StandardUniform as rand::distr::distribution::Distribution<core::num::nonzero::NonZero<i16>>>::sample::<_>
Unexecuted instantiation: <rand::distr::StandardUniform as rand::distr::distribution::Distribution<core::num::nonzero::NonZero<i32>>>::sample::<_>
Unexecuted instantiation: <rand::distr::StandardUniform as rand::distr::distribution::Distribution<core::num::nonzero::NonZero<i64>>>::sample::<_>
Unexecuted instantiation: <rand::distr::StandardUniform as rand::distr::distribution::Distribution<core::num::nonzero::NonZero<i128>>>::sample::<_>
93
        }
94
    };
95
}
96
97
impl_nzint!(NonZeroU8, NonZeroU8::new);
98
impl_nzint!(NonZeroU16, NonZeroU16::new);
99
impl_nzint!(NonZeroU32, NonZeroU32::new);
100
impl_nzint!(NonZeroU64, NonZeroU64::new);
101
impl_nzint!(NonZeroU128, NonZeroU128::new);
102
103
impl_nzint!(NonZeroI8, NonZeroI8::new);
104
impl_nzint!(NonZeroI16, NonZeroI16::new);
105
impl_nzint!(NonZeroI32, NonZeroI32::new);
106
impl_nzint!(NonZeroI64, NonZeroI64::new);
107
impl_nzint!(NonZeroI128, NonZeroI128::new);
108
109
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
110
macro_rules! x86_intrinsic_impl {
111
    ($meta:meta, $($intrinsic:ident),+) => {$(
112
        #[cfg($meta)]
113
        impl Distribution<$intrinsic> for StandardUniform {
114
            #[inline]
115
0
            fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> $intrinsic {
116
0
                // On proper hardware, this should compile to SIMD instructions
117
0
                // Verified on x86 Haswell with __m128i, __m256i
118
0
                let mut buf = [0_u8; core::mem::size_of::<$intrinsic>()];
119
0
                rng.fill_bytes(&mut buf);
120
0
                // x86 is little endian so no need for conversion
121
0
                zerocopy::transmute!(buf)
122
0
            }
Unexecuted instantiation: <rand::distr::StandardUniform as rand::distr::distribution::Distribution<core::core_arch::x86::__m128i>>::sample::<_>
Unexecuted instantiation: <rand::distr::StandardUniform as rand::distr::distribution::Distribution<core::core_arch::x86::__m256i>>::sample::<_>
123
        }
124
    )+};
125
}
126
127
#[cfg(feature = "simd_support")]
128
macro_rules! simd_impl {
129
    ($($ty:ty),+) => {$(
130
        /// Requires nightly Rust and the [`simd_support`] feature
131
        ///
132
        /// [`simd_support`]: https://github.com/rust-random/rand#crate-features
133
        #[cfg(feature = "simd_support")]
134
        impl<const LANES: usize> Distribution<Simd<$ty, LANES>> for StandardUniform
135
        where
136
            LaneCount<LANES>: SupportedLaneCount,
137
        {
138
            #[inline]
139
            fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Simd<$ty, LANES> {
140
                let mut vec = Simd::default();
141
                rng.fill(vec.as_mut_array().as_mut_slice());
142
                vec
143
            }
144
        }
145
    )+};
146
}
147
148
#[cfg(feature = "simd_support")]
149
simd_impl!(u8, i8, u16, i16, u32, i32, u64, i64);
150
151
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
152
x86_intrinsic_impl!(
153
    any(target_arch = "x86", target_arch = "x86_64"),
154
    __m128i,
155
    __m256i
156
);
157
#[cfg(all(
158
    any(target_arch = "x86", target_arch = "x86_64"),
159
    feature = "simd_support"
160
))]
161
x86_intrinsic_impl!(
162
    all(
163
        any(target_arch = "x86", target_arch = "x86_64"),
164
        feature = "simd_support"
165
    ),
166
    __m512i
167
);
168
169
#[cfg(test)]
170
mod tests {
171
    use super::*;
172
173
    #[test]
174
    fn test_integers() {
175
        let mut rng = crate::test::rng(806);
176
177
        rng.sample::<i8, _>(StandardUniform);
178
        rng.sample::<i16, _>(StandardUniform);
179
        rng.sample::<i32, _>(StandardUniform);
180
        rng.sample::<i64, _>(StandardUniform);
181
        rng.sample::<i128, _>(StandardUniform);
182
183
        rng.sample::<u8, _>(StandardUniform);
184
        rng.sample::<u16, _>(StandardUniform);
185
        rng.sample::<u32, _>(StandardUniform);
186
        rng.sample::<u64, _>(StandardUniform);
187
        rng.sample::<u128, _>(StandardUniform);
188
    }
189
190
    #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
191
    #[test]
192
    fn x86_integers() {
193
        let mut rng = crate::test::rng(807);
194
195
        rng.sample::<__m128i, _>(StandardUniform);
196
        rng.sample::<__m256i, _>(StandardUniform);
197
        #[cfg(feature = "simd_support")]
198
        rng.sample::<__m512i, _>(StandardUniform);
199
    }
200
201
    #[test]
202
    fn value_stability() {
203
        fn test_samples<T: Copy + core::fmt::Debug + PartialEq>(zero: T, expected: &[T])
204
        where
205
            StandardUniform: Distribution<T>,
206
        {
207
            let mut rng = crate::test::rng(807);
208
            let mut buf = [zero; 3];
209
            for x in &mut buf {
210
                *x = rng.sample(StandardUniform);
211
            }
212
            assert_eq!(&buf, expected);
213
        }
214
215
        test_samples(0u8, &[9, 247, 111]);
216
        test_samples(0u16, &[32265, 42999, 38255]);
217
        test_samples(0u32, &[2220326409, 2575017975, 2018088303]);
218
        test_samples(
219
            0u64,
220
            &[
221
                11059617991457472009,
222
                16096616328739788143,
223
                1487364411147516184,
224
            ],
225
        );
226
        test_samples(
227
            0u128,
228
            &[
229
                296930161868957086625409848350820761097,
230
                145644820879247630242265036535529306392,
231
                111087889832015897993126088499035356354,
232
            ],
233
        );
234
235
        test_samples(0i8, &[9, -9, 111]);
236
        // Skip further i* types: they are simple reinterpretation of u* samples
237
238
        #[cfg(feature = "simd_support")]
239
        {
240
            // We only test a sub-set of types here and make assumptions about the rest.
241
242
            test_samples(
243
                u8x4::default(),
244
                &[
245
                    u8x4::from([9, 126, 87, 132]),
246
                    u8x4::from([247, 167, 123, 153]),
247
                    u8x4::from([111, 149, 73, 120]),
248
                ],
249
            );
250
            test_samples(
251
                u8x8::default(),
252
                &[
253
                    u8x8::from([9, 126, 87, 132, 247, 167, 123, 153]),
254
                    u8x8::from([111, 149, 73, 120, 68, 171, 98, 223]),
255
                    u8x8::from([24, 121, 1, 50, 13, 46, 164, 20]),
256
                ],
257
            );
258
259
            test_samples(
260
                i64x8::default(),
261
                &[
262
                    i64x8::from([
263
                        -7387126082252079607,
264
                        -2350127744969763473,
265
                        1487364411147516184,
266
                        7895421560427121838,
267
                        602190064936008898,
268
                        6022086574635100741,
269
                        -5080089175222015595,
270
                        -4066367846667249123,
271
                    ]),
272
                    i64x8::from([
273
                        9180885022207963908,
274
                        3095981199532211089,
275
                        6586075293021332726,
276
                        419343203796414657,
277
                        3186951873057035255,
278
                        5287129228749947252,
279
                        444726432079249540,
280
                        -1587028029513790706,
281
                    ]),
282
                    i64x8::from([
283
                        6075236523189346388,
284
                        1351763722368165432,
285
                        -6192309979959753740,
286
                        -7697775502176768592,
287
                        -4482022114172078123,
288
                        7522501477800909500,
289
                        -1837258847956201231,
290
                        -586926753024886735,
291
                    ]),
292
                ],
293
            );
294
        }
295
    }
296
}