Skip to main content
This is unreleased documentation for the main (development) branch of crypto-glue.

rand/distributions/
integer.rs

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
11use crate::distributions::{Distribution, Standard};
12use crate::Rng;
13use core::num::{NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize,
14    NonZeroU128};
15
16impl Distribution<u8> for Standard {
17    #[inline]
18    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> u8 {
19        rng.next_u32() as u8
20    }
21}
22
23impl Distribution<u16> for Standard {
24    #[inline]
25    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> u16 {
26        rng.next_u32() as u16
27    }
28}
29
30impl Distribution<u32> for Standard {
31    #[inline]
32    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> u32 {
33        rng.next_u32()
34    }
35}
36
37impl Distribution<u64> for Standard {
38    #[inline]
39    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> u64 {
40        rng.next_u64()
41    }
42}
43
44impl Distribution<u128> for Standard {
45    #[inline]
46    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> u128 {
47        // Use LE; we explicitly generate one value before the next.
48        let x = u128::from(rng.next_u64());
49        let y = u128::from(rng.next_u64());
50        (y << 64) | x
51    }
52}
53
54impl Distribution<usize> for Standard {
55    #[inline]
56    #[cfg(any(target_pointer_width = "32", target_pointer_width = "16"))]
57    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> usize {
58        rng.next_u32() as usize
59    }
60
61    #[inline]
62    #[cfg(target_pointer_width = "64")]
63    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> usize {
64        rng.next_u64() as usize
65    }
66}
67
68macro_rules! impl_int_from_uint {
69    ($ty:ty, $uty:ty) => {
70        impl Distribution<$ty> for Standard {
71            #[inline]
72            fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> $ty {
73                rng.gen::<$uty>() as $ty
74            }
75        }
76    };
77}
78
79impl_int_from_uint! { i8, u8 }
80impl_int_from_uint! { i16, u16 }
81impl_int_from_uint! { i32, u32 }
82impl_int_from_uint! { i64, u64 }
83impl_int_from_uint! { i128, u128 }
84impl_int_from_uint! { isize, usize }
85
86macro_rules! impl_nzint {
87    ($ty:ty, $new:path) => {
88        impl Distribution<$ty> for Standard {
89            fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> $ty {
90                loop {
91                    if let Some(nz) = $new(rng.gen()) {
92                        break nz;
93                    }
94                }
95            }
96        }
97    };
98}
99
100impl_nzint!(NonZeroU8, NonZeroU8::new);
101impl_nzint!(NonZeroU16, NonZeroU16::new);
102impl_nzint!(NonZeroU32, NonZeroU32::new);
103impl_nzint!(NonZeroU64, NonZeroU64::new);
104impl_nzint!(NonZeroU128, NonZeroU128::new);
105impl_nzint!(NonZeroUsize, NonZeroUsize::new);
106
107#[cfg(test)]
108mod tests {
109    use super::*;
110
111    #[test]
112    fn test_integers() {
113        let mut rng = crate::test::rng(806);
114
115        rng.sample::<isize, _>(Standard);
116        rng.sample::<i8, _>(Standard);
117        rng.sample::<i16, _>(Standard);
118        rng.sample::<i32, _>(Standard);
119        rng.sample::<i64, _>(Standard);
120        rng.sample::<i128, _>(Standard);
121
122        rng.sample::<usize, _>(Standard);
123        rng.sample::<u8, _>(Standard);
124        rng.sample::<u16, _>(Standard);
125        rng.sample::<u32, _>(Standard);
126        rng.sample::<u64, _>(Standard);
127        rng.sample::<u128, _>(Standard);
128    }
129
130    #[test]
131    fn value_stability() {
132        fn test_samples<T: Copy + core::fmt::Debug + PartialEq>(zero: T, expected: &[T])
133        where Standard: Distribution<T> {
134            let mut rng = crate::test::rng(807);
135            let mut buf = [zero; 3];
136            for x in &mut buf {
137                *x = rng.sample(Standard);
138            }
139            assert_eq!(&buf, expected);
140        }
141
142        test_samples(0u8, &[9, 247, 111]);
143        test_samples(0u16, &[32265, 42999, 38255]);
144        test_samples(0u32, &[2220326409, 2575017975, 2018088303]);
145        test_samples(0u64, &[
146            11059617991457472009,
147            16096616328739788143,
148            1487364411147516184,
149        ]);
150        test_samples(0u128, &[
151            296930161868957086625409848350820761097,
152            145644820879247630242265036535529306392,
153            111087889832015897993126088499035356354,
154        ]);
155        #[cfg(any(target_pointer_width = "32", target_pointer_width = "16"))]
156        test_samples(0usize, &[2220326409, 2575017975, 2018088303]);
157        #[cfg(target_pointer_width = "64")]
158        test_samples(0usize, &[
159            11059617991457472009,
160            16096616328739788143,
161            1487364411147516184,
162        ]);
163
164        test_samples(0i8, &[9, -9, 111]);
165        // Skip further i* types: they are simple reinterpretation of u* samples
166    }
167}