1//! Random value generation.
23use crate::range::{RangeFull, RangeInclusive};
45/// A source of randomness.
6#[unstable(feature = "random", issue = "130703")]
7pub trait Rng {
8/// Fills `bytes` with random bytes.
9 ///
10 /// Note that calling `fill_bytes` multiple times is not equivalent to calling `fill_bytes` once
11 /// with a larger buffer. An `Rng` is allowed to return different bytes for those two cases. For
12 /// instance, this allows an `Rng` to generate a word at a time and throw part of it away if not
13 /// needed.
14fn fill_bytes(&mut self, bytes: &mut [u8]);
15}
1617/// Implements `Rng` for mutable references to random number generators by
18/// forwarding all methods to the referenced generator.
19#[unstable(feature = "random", issue = "130703")]
20impl<'a, R: Rng + ?Sized> Rngfor &'a mut R {
21fn fill_bytes(&mut self, bytes: &mut [u8]) {
22 R::fill_bytes(self, bytes);
23 }
24}
2526/// A trait representing a distribution of random values for a type.
27#[unstable(feature = "random", issue = "130703")]
28pub trait Distribution<T> {
29/// Samples a random value from the distribution, using the specified random source.
30fn sample(&self, source: &mut (impl Rng + ?Sized)) -> T;
31}
3233impl<T, DT: Distribution<T>> Distribution<T> for &DT {
34fn sample(&self, source: &mut (impl Rng + ?Sized)) -> T {
35 (*self).sample(source)
36 }
37}
3839impl Distribution<bool> for RangeFull {
40fn sample(&self, source: &mut (impl Rng + ?Sized)) -> bool {
41let byte: u8 = RangeFull.sample(source);
42byte & 1 == 1
43}
44}
4546macro_rules!impl_full {
47 ($t:ty) => {
48impl Distribution<$t> for RangeFull {
49fn sample(&self, source: &mut (impl Rng + ?Sized)) -> $t {
50let mut bytes = (0 as $t).to_ne_bytes();
51 source.fill_bytes(&mut bytes);
52// Always use little-endian for reproducibility. Since the vast majority of code is
53 // mainly or exclusively tested on LE targets, giving different PRNG results for the
54 // same seed on BE targets is a serious portability hazard.
55<$t>::from_le_bytes(bytes)
56 }
57 }
58 };
59}
6061impl Distribution<u8> for RangeFull {
fn sample(&self, source: &mut (impl Rng + ?Sized)) -> u8 {
let mut bytes = (0 as u8).to_ne_bytes();
source.fill_bytes(&mut bytes);
<u8>::from_le_bytes(bytes)
}
}impl_full!(u8);
62impl Distribution<i8> for RangeFull {
fn sample(&self, source: &mut (impl Rng + ?Sized)) -> i8 {
let mut bytes = (0 as i8).to_ne_bytes();
source.fill_bytes(&mut bytes);
<i8>::from_le_bytes(bytes)
}
}impl_full!(i8);
63impl Distribution<u16> for RangeFull {
fn sample(&self, source: &mut (impl Rng + ?Sized)) -> u16 {
let mut bytes = (0 as u16).to_ne_bytes();
source.fill_bytes(&mut bytes);
<u16>::from_le_bytes(bytes)
}
}impl_full!(u16);
64impl Distribution<i16> for RangeFull {
fn sample(&self, source: &mut (impl Rng + ?Sized)) -> i16 {
let mut bytes = (0 as i16).to_ne_bytes();
source.fill_bytes(&mut bytes);
<i16>::from_le_bytes(bytes)
}
}impl_full!(i16);
65impl Distribution<u32> for RangeFull {
fn sample(&self, source: &mut (impl Rng + ?Sized)) -> u32 {
let mut bytes = (0 as u32).to_ne_bytes();
source.fill_bytes(&mut bytes);
<u32>::from_le_bytes(bytes)
}
}impl_full!(u32);
66impl Distribution<i32> for RangeFull {
fn sample(&self, source: &mut (impl Rng + ?Sized)) -> i32 {
let mut bytes = (0 as i32).to_ne_bytes();
source.fill_bytes(&mut bytes);
<i32>::from_le_bytes(bytes)
}
}impl_full!(i32);
67impl Distribution<u64> for RangeFull {
fn sample(&self, source: &mut (impl Rng + ?Sized)) -> u64 {
let mut bytes = (0 as u64).to_ne_bytes();
source.fill_bytes(&mut bytes);
<u64>::from_le_bytes(bytes)
}
}impl_full!(u64);
68impl Distribution<i64> for RangeFull {
fn sample(&self, source: &mut (impl Rng + ?Sized)) -> i64 {
let mut bytes = (0 as i64).to_ne_bytes();
source.fill_bytes(&mut bytes);
<i64>::from_le_bytes(bytes)
}
}impl_full!(i64);
69impl Distribution<u128> for RangeFull {
fn sample(&self, source: &mut (impl Rng + ?Sized)) -> u128 {
let mut bytes = (0 as u128).to_ne_bytes();
source.fill_bytes(&mut bytes);
<u128>::from_le_bytes(bytes)
}
}impl_full!(u128);
70impl Distribution<i128> for RangeFull {
fn sample(&self, source: &mut (impl Rng + ?Sized)) -> i128 {
let mut bytes = (0 as i128).to_ne_bytes();
source.fill_bytes(&mut bytes);
<i128>::from_le_bytes(bytes)
}
}impl_full!(i128);
71impl Distribution<usize> for RangeFull {
fn sample(&self, source: &mut (impl Rng + ?Sized)) -> usize {
let mut bytes = (0 as usize).to_ne_bytes();
source.fill_bytes(&mut bytes);
<usize>::from_le_bytes(bytes)
}
}impl_full!(usize);
72impl Distribution<isize> for RangeFull {
fn sample(&self, source: &mut (impl Rng + ?Sized)) -> isize {
let mut bytes = (0 as isize).to_ne_bytes();
source.fill_bytes(&mut bytes);
<isize>::from_le_bytes(bytes)
}
}impl_full!(isize);
7374#[cold]
75fn empty_range() -> ! {
76{
crate::panicking::panic_fmt(format_args!("cannot sample from an empty distribution"));
}panic!("cannot sample from an empty distribution")77}
7879macro_rules!lemire_sample {
80 ($name:ident($ty:ty)) => {
81// Unbiased uniform sampling of a number within the range [0, bound).
82 //
83 // By performing some clever modular arithmetic, this algorithm manages
84 // to both reduce divisions and minimize the chance of sample rejections.
85 //
86 // Algorithm from:
87 // spellchecker:off
88 // Daniel Lemire. 2019. Fast Random Integer Generation in an Interval.
89 // ACM Trans. Model. Comput. Simul. 29, 1, Article 3 (January 2019), 12 pages.
90 // https://doi.org/10.1145/3230636
91 // spellchecker:on
92fn $name(bound: $ty, source: &mut (impl Rng + ?Sized)) -> $ty {
93debug_assert_ne!(bound, 0);
9495let sample: $ty = (..).sample(source);
9697let (mut l, mut res) = sample.carrying_mul(bound, 0);
98if l < bound {
99let t = bound.wrapping_neg() % bound;
100while l < t {
101let sample: $ty = (..).sample(source);
102 (l, res) = sample.carrying_mul(bound, 0);
103 }
104 }
105106debug_assert!(res < bound);
107 res
108 }
109 };
110}
111112fn bounded32(bound: u32, source: &mut (impl Rng + ?Sized)) -> u32 {
if true {
{
match (&bound, &0) {
(left_val, right_val) => {
if *left_val == *right_val {
let kind = crate::panicking::AssertKind::Ne;
crate::panicking::assert_failed(kind, &*left_val,
&*right_val, crate::option::Option::None);
}
}
}
};
};
let sample: u32 = (..).sample(source);
let (mut l, mut res) = sample.carrying_mul(bound, 0);
if l < bound {
let t = bound.wrapping_neg() % bound;
while l < t {
let sample: u32 = (..).sample(source);
(l, res) = sample.carrying_mul(bound, 0);
}
}
if true {
if !(res < bound) {
crate::panicking::panic("assertion failed: res < bound")
};
};
res
}lemire_sample!(bounded32(u32));
113fn bounded64(bound: u64, source: &mut (impl Rng + ?Sized)) -> u64 {
if true {
{
match (&bound, &0) {
(left_val, right_val) => {
if *left_val == *right_val {
let kind = crate::panicking::AssertKind::Ne;
crate::panicking::assert_failed(kind, &*left_val,
&*right_val, crate::option::Option::None);
}
}
}
};
};
let sample: u64 = (..).sample(source);
let (mut l, mut res) = sample.carrying_mul(bound, 0);
if l < bound {
let t = bound.wrapping_neg() % bound;
while l < t {
let sample: u64 = (..).sample(source);
(l, res) = sample.carrying_mul(bound, 0);
}
}
if true {
if !(res < bound) {
crate::panicking::panic("assertion failed: res < bound")
};
};
res
}lemire_sample!(bounded64(u64));
114fn bounded128(bound: u128, source: &mut (impl Rng + ?Sized)) -> u128 {
if true {
{
match (&bound, &0) {
(left_val, right_val) => {
if *left_val == *right_val {
let kind = crate::panicking::AssertKind::Ne;
crate::panicking::assert_failed(kind, &*left_val,
&*right_val, crate::option::Option::None);
}
}
}
};
};
let sample: u128 = (..).sample(source);
let (mut l, mut res) = sample.carrying_mul(bound, 0);
if l < bound {
let t = bound.wrapping_neg() % bound;
while l < t {
let sample: u128 = (..).sample(source);
(l, res) = sample.carrying_mul(bound, 0);
}
}
if true {
if !(res < bound) {
crate::panicking::panic("assertion failed: res < bound")
};
};
res
}lemire_sample!(bounded128(u128));
115116macro_rules!impl_range {
117 ($unsigned:ty, $signed:ty as $base:ty => $bounded:ident) => {
118impl Distribution<$unsigned> for RangeInclusive<$unsigned> {
119/// Chooses a random number within the range.
120 ///
121 /// Every possible result value is equally likely. In other words,
122 /// this operation uses unbiased uniform sampling.
123 ///
124 /// # Panics
125 ///
126 /// Panics if the range is empty.
127 ///
128 /// # Side-channels
129 ///
130 /// This implementation does not claim to be resistant against side-
131 /// channel attacks. In particular, the execution time of this operation
132 /// may leak information about the returned value, and not just the
133 /// values of the range bounds. While this implementation tries to
134 /// avoid operations with particularly data-dependent timing (such
135 /// as divisions), Rust as a language has no facilities for ensuring
136 /// data-independent timing, voiding all promises about side-channel-
137 /// freedom.
138 ///
139 /// # Examples
140 ///
141 /// A D20 dice roll:
142 /// ```
143 /// #![feature(random)]
144 ///
145 /// use std::random::{Distribution, SystemRng};
146 /// use std::range::RangeInclusive;
147 ///
148 /// let roll = RangeInclusive::from(1..=20).sample(&mut SystemRng);
149 /// assert!(1 <= roll && roll <= 20);
150 /// if roll == 20 {
151 /// println!("Wow! You achieve writing a sound linked list.");
152 /// } else {
153 /// println!("Miri attacks!");
154 /// }
155 /// ```
156#[inline]
157fn sample(&self, source: &mut (impl Rng + ?Sized)) -> $unsigned {
158if self.start > self.last {
159 empty_range();
160 }
161162if self.start == self.last {
163return self.start;
164 }
165166let Some(bound) = (self.last - self.start).checked_add(1) else {
167// Overflow can only occur for Self::MIN..=Self::MAX, meaning
168 // the range is effectively unbounded.
169return RangeFull.sample(source);
170 };
171172let offset = if bound.is_power_of_two() {
173let sample: $unsigned = RangeFull.sample(source);
174 sample & (bound - 1)
175 } else {
176$bounded(bound as $base, source) as $unsigned
177};
178179self.start + offset
180 }
181 }
182183impl Distribution<$signed> for RangeInclusive<$signed> {
184/// Chooses a random number within the range.
185 ///
186 /// Every possible result value is equally likely. In other words,
187 /// this operation uses unbiased uniform sampling.
188 ///
189 /// # Panics
190 ///
191 /// Panics if the range is empty.
192 ///
193 /// # Side-channels
194 ///
195 /// This implementation does not claim to be resistant against side-
196 /// channel attacks. In particular, the execution time of this operation
197 /// may leak information about the returned value, and not just the
198 /// values of the range bounds. While this implementation tries to
199 /// avoid operations with particularly data-dependent timing (such
200 /// as divisions), Rust as a language has no facilities for ensuring
201 /// data-independent timing, voiding all promises about side-channel-
202 /// freedom.
203 ///
204 /// # Examples
205 ///
206 /// A D20 dice roll:
207 /// ```
208 /// #![feature(random)]
209 ///
210 /// use std::random::{Distribution, SystemRng};
211 /// use std::range::RangeInclusive;
212 ///
213 /// let roll = RangeInclusive::from(1..=20).sample(&mut SystemRng);
214 /// assert!(1 <= roll && roll <= 20);
215 /// if roll == 20 {
216 /// println!("Wow! You achieve writing a sound linked list.");
217 /// } else {
218 /// println!("Miri attacks!");
219 /// }
220 /// ```
221#[inline]
222fn sample(&self, source: &mut (impl Rng + ?Sized)) -> $signed {
223if self.start > self.last {
224 empty_range();
225 }
226227if self.start == self.last {
228return self.start;
229 }
230231let Some(bound) = self.last.wrapping_sub(self.start).cast_unsigned().checked_add(1)
232else {
233// Overflow can only occur for Self::MIN..=Self::MAX, meaning
234 // the range is effectively unbounded.
235return RangeFull.sample(source);
236 };
237238let offset = if bound.is_power_of_two() {
239let sample: $unsigned = RangeFull.sample(source);
240 sample & (bound - 1)
241 } else {
242$bounded(bound as $base, source) as $unsigned
243};
244245self.start.wrapping_add_unsigned(offset)
246 }
247 }
248 };
249}
250251// Use 32-bit integers for small integers since it reduces the likelihood of
252// sample rejections.
253impl Distribution<u8> for RangeInclusive<u8> {
/// Chooses a random number within the range.
///
/// Every possible result value is equally likely. In other words,
/// this operation uses unbiased uniform sampling.
///
/// # Panics
///
/// Panics if the range is empty.
///
/// # Side-channels
///
/// This implementation does not claim to be resistant against side-
/// channel attacks. In particular, the execution time of this operation
/// may leak information about the returned value, and not just the
/// values of the range bounds. While this implementation tries to
/// avoid operations with particularly data-dependent timing (such
/// as divisions), Rust as a language has no facilities for ensuring
/// data-independent timing, voiding all promises about side-channel-
/// freedom.
///
/// # Examples
///
/// A D20 dice roll:
/// ```
/// #![feature(random)]
///
/// use std::random::{Distribution, SystemRng};
/// use std::range::RangeInclusive;
///
/// let roll = RangeInclusive::from(1..=20).sample(&mut SystemRng);
/// assert!(1 <= roll && roll <= 20);
/// if roll == 20 {
/// println!("Wow! You achieve writing a sound linked list.");
/// } else {
/// println!("Miri attacks!");
/// }
/// ```
#[inline]
fn sample(&self, source: &mut (impl Rng + ?Sized)) -> u8 {
if self.start > self.last { empty_range(); }
if self.start == self.last { return self.start; }
let Some(bound) =
(self.last -
self.start).checked_add(1) else {
return RangeFull.sample(source);
};
let offset =
if bound.is_power_of_two() {
let sample: u8 = RangeFull.sample(source);
sample & (bound - 1)
} else { bounded32(bound as u32, source) as u8 };
self.start + offset
}
}
impl Distribution<i8> for RangeInclusive<i8> {
/// Chooses a random number within the range.
///
/// Every possible result value is equally likely. In other words,
/// this operation uses unbiased uniform sampling.
///
/// # Panics
///
/// Panics if the range is empty.
///
/// # Side-channels
///
/// This implementation does not claim to be resistant against side-
/// channel attacks. In particular, the execution time of this operation
/// may leak information about the returned value, and not just the
/// values of the range bounds. While this implementation tries to
/// avoid operations with particularly data-dependent timing (such
/// as divisions), Rust as a language has no facilities for ensuring
/// data-independent timing, voiding all promises about side-channel-
/// freedom.
///
/// # Examples
///
/// A D20 dice roll:
/// ```
/// #![feature(random)]
///
/// use std::random::{Distribution, SystemRng};
/// use std::range::RangeInclusive;
///
/// let roll = RangeInclusive::from(1..=20).sample(&mut SystemRng);
/// assert!(1 <= roll && roll <= 20);
/// if roll == 20 {
/// println!("Wow! You achieve writing a sound linked list.");
/// } else {
/// println!("Miri attacks!");
/// }
/// ```
#[inline]
fn sample(&self, source: &mut (impl Rng + ?Sized)) -> i8 {
if self.start > self.last { empty_range(); }
if self.start == self.last { return self.start; }
let Some(bound) =
self.last.wrapping_sub(self.start).cast_unsigned().checked_add(1) else {
return RangeFull.sample(source);
};
let offset =
if bound.is_power_of_two() {
let sample: u8 = RangeFull.sample(source);
sample & (bound - 1)
} else { bounded32(bound as u32, source) as u8 };
self.start.wrapping_add_unsigned(offset)
}
}impl_range!(u8, i8as u32 => bounded32);
254impl Distribution<u16> for RangeInclusive<u16> {
/// Chooses a random number within the range.
///
/// Every possible result value is equally likely. In other words,
/// this operation uses unbiased uniform sampling.
///
/// # Panics
///
/// Panics if the range is empty.
///
/// # Side-channels
///
/// This implementation does not claim to be resistant against side-
/// channel attacks. In particular, the execution time of this operation
/// may leak information about the returned value, and not just the
/// values of the range bounds. While this implementation tries to
/// avoid operations with particularly data-dependent timing (such
/// as divisions), Rust as a language has no facilities for ensuring
/// data-independent timing, voiding all promises about side-channel-
/// freedom.
///
/// # Examples
///
/// A D20 dice roll:
/// ```
/// #![feature(random)]
///
/// use std::random::{Distribution, SystemRng};
/// use std::range::RangeInclusive;
///
/// let roll = RangeInclusive::from(1..=20).sample(&mut SystemRng);
/// assert!(1 <= roll && roll <= 20);
/// if roll == 20 {
/// println!("Wow! You achieve writing a sound linked list.");
/// } else {
/// println!("Miri attacks!");
/// }
/// ```
#[inline]
fn sample(&self, source: &mut (impl Rng + ?Sized)) -> u16 {
if self.start > self.last { empty_range(); }
if self.start == self.last { return self.start; }
let Some(bound) =
(self.last -
self.start).checked_add(1) else {
return RangeFull.sample(source);
};
let offset =
if bound.is_power_of_two() {
let sample: u16 = RangeFull.sample(source);
sample & (bound - 1)
} else { bounded32(bound as u32, source) as u16 };
self.start + offset
}
}
impl Distribution<i16> for RangeInclusive<i16> {
/// Chooses a random number within the range.
///
/// Every possible result value is equally likely. In other words,
/// this operation uses unbiased uniform sampling.
///
/// # Panics
///
/// Panics if the range is empty.
///
/// # Side-channels
///
/// This implementation does not claim to be resistant against side-
/// channel attacks. In particular, the execution time of this operation
/// may leak information about the returned value, and not just the
/// values of the range bounds. While this implementation tries to
/// avoid operations with particularly data-dependent timing (such
/// as divisions), Rust as a language has no facilities for ensuring
/// data-independent timing, voiding all promises about side-channel-
/// freedom.
///
/// # Examples
///
/// A D20 dice roll:
/// ```
/// #![feature(random)]
///
/// use std::random::{Distribution, SystemRng};
/// use std::range::RangeInclusive;
///
/// let roll = RangeInclusive::from(1..=20).sample(&mut SystemRng);
/// assert!(1 <= roll && roll <= 20);
/// if roll == 20 {
/// println!("Wow! You achieve writing a sound linked list.");
/// } else {
/// println!("Miri attacks!");
/// }
/// ```
#[inline]
fn sample(&self, source: &mut (impl Rng + ?Sized)) -> i16 {
if self.start > self.last { empty_range(); }
if self.start == self.last { return self.start; }
let Some(bound) =
self.last.wrapping_sub(self.start).cast_unsigned().checked_add(1) else {
return RangeFull.sample(source);
};
let offset =
if bound.is_power_of_two() {
let sample: u16 = RangeFull.sample(source);
sample & (bound - 1)
} else { bounded32(bound as u32, source) as u16 };
self.start.wrapping_add_unsigned(offset)
}
}impl_range!(u16, i16as u32 => bounded32);
255256impl Distribution<u32> for RangeInclusive<u32> {
/// Chooses a random number within the range.
///
/// Every possible result value is equally likely. In other words,
/// this operation uses unbiased uniform sampling.
///
/// # Panics
///
/// Panics if the range is empty.
///
/// # Side-channels
///
/// This implementation does not claim to be resistant against side-
/// channel attacks. In particular, the execution time of this operation
/// may leak information about the returned value, and not just the
/// values of the range bounds. While this implementation tries to
/// avoid operations with particularly data-dependent timing (such
/// as divisions), Rust as a language has no facilities for ensuring
/// data-independent timing, voiding all promises about side-channel-
/// freedom.
///
/// # Examples
///
/// A D20 dice roll:
/// ```
/// #![feature(random)]
///
/// use std::random::{Distribution, SystemRng};
/// use std::range::RangeInclusive;
///
/// let roll = RangeInclusive::from(1..=20).sample(&mut SystemRng);
/// assert!(1 <= roll && roll <= 20);
/// if roll == 20 {
/// println!("Wow! You achieve writing a sound linked list.");
/// } else {
/// println!("Miri attacks!");
/// }
/// ```
#[inline]
fn sample(&self, source: &mut (impl Rng + ?Sized)) -> u32 {
if self.start > self.last { empty_range(); }
if self.start == self.last { return self.start; }
let Some(bound) =
(self.last -
self.start).checked_add(1) else {
return RangeFull.sample(source);
};
let offset =
if bound.is_power_of_two() {
let sample: u32 = RangeFull.sample(source);
sample & (bound - 1)
} else { bounded32(bound as u32, source) as u32 };
self.start + offset
}
}
impl Distribution<i32> for RangeInclusive<i32> {
/// Chooses a random number within the range.
///
/// Every possible result value is equally likely. In other words,
/// this operation uses unbiased uniform sampling.
///
/// # Panics
///
/// Panics if the range is empty.
///
/// # Side-channels
///
/// This implementation does not claim to be resistant against side-
/// channel attacks. In particular, the execution time of this operation
/// may leak information about the returned value, and not just the
/// values of the range bounds. While this implementation tries to
/// avoid operations with particularly data-dependent timing (such
/// as divisions), Rust as a language has no facilities for ensuring
/// data-independent timing, voiding all promises about side-channel-
/// freedom.
///
/// # Examples
///
/// A D20 dice roll:
/// ```
/// #![feature(random)]
///
/// use std::random::{Distribution, SystemRng};
/// use std::range::RangeInclusive;
///
/// let roll = RangeInclusive::from(1..=20).sample(&mut SystemRng);
/// assert!(1 <= roll && roll <= 20);
/// if roll == 20 {
/// println!("Wow! You achieve writing a sound linked list.");
/// } else {
/// println!("Miri attacks!");
/// }
/// ```
#[inline]
fn sample(&self, source: &mut (impl Rng + ?Sized)) -> i32 {
if self.start > self.last { empty_range(); }
if self.start == self.last { return self.start; }
let Some(bound) =
self.last.wrapping_sub(self.start).cast_unsigned().checked_add(1) else {
return RangeFull.sample(source);
};
let offset =
if bound.is_power_of_two() {
let sample: u32 = RangeFull.sample(source);
sample & (bound - 1)
} else { bounded32(bound as u32, source) as u32 };
self.start.wrapping_add_unsigned(offset)
}
}impl_range!(u32, i32as u32 => bounded32);
257impl Distribution<u64> for RangeInclusive<u64> {
/// Chooses a random number within the range.
///
/// Every possible result value is equally likely. In other words,
/// this operation uses unbiased uniform sampling.
///
/// # Panics
///
/// Panics if the range is empty.
///
/// # Side-channels
///
/// This implementation does not claim to be resistant against side-
/// channel attacks. In particular, the execution time of this operation
/// may leak information about the returned value, and not just the
/// values of the range bounds. While this implementation tries to
/// avoid operations with particularly data-dependent timing (such
/// as divisions), Rust as a language has no facilities for ensuring
/// data-independent timing, voiding all promises about side-channel-
/// freedom.
///
/// # Examples
///
/// A D20 dice roll:
/// ```
/// #![feature(random)]
///
/// use std::random::{Distribution, SystemRng};
/// use std::range::RangeInclusive;
///
/// let roll = RangeInclusive::from(1..=20).sample(&mut SystemRng);
/// assert!(1 <= roll && roll <= 20);
/// if roll == 20 {
/// println!("Wow! You achieve writing a sound linked list.");
/// } else {
/// println!("Miri attacks!");
/// }
/// ```
#[inline]
fn sample(&self, source: &mut (impl Rng + ?Sized)) -> u64 {
if self.start > self.last { empty_range(); }
if self.start == self.last { return self.start; }
let Some(bound) =
(self.last -
self.start).checked_add(1) else {
return RangeFull.sample(source);
};
let offset =
if bound.is_power_of_two() {
let sample: u64 = RangeFull.sample(source);
sample & (bound - 1)
} else { bounded64(bound as u64, source) as u64 };
self.start + offset
}
}
impl Distribution<i64> for RangeInclusive<i64> {
/// Chooses a random number within the range.
///
/// Every possible result value is equally likely. In other words,
/// this operation uses unbiased uniform sampling.
///
/// # Panics
///
/// Panics if the range is empty.
///
/// # Side-channels
///
/// This implementation does not claim to be resistant against side-
/// channel attacks. In particular, the execution time of this operation
/// may leak information about the returned value, and not just the
/// values of the range bounds. While this implementation tries to
/// avoid operations with particularly data-dependent timing (such
/// as divisions), Rust as a language has no facilities for ensuring
/// data-independent timing, voiding all promises about side-channel-
/// freedom.
///
/// # Examples
///
/// A D20 dice roll:
/// ```
/// #![feature(random)]
///
/// use std::random::{Distribution, SystemRng};
/// use std::range::RangeInclusive;
///
/// let roll = RangeInclusive::from(1..=20).sample(&mut SystemRng);
/// assert!(1 <= roll && roll <= 20);
/// if roll == 20 {
/// println!("Wow! You achieve writing a sound linked list.");
/// } else {
/// println!("Miri attacks!");
/// }
/// ```
#[inline]
fn sample(&self, source: &mut (impl Rng + ?Sized)) -> i64 {
if self.start > self.last { empty_range(); }
if self.start == self.last { return self.start; }
let Some(bound) =
self.last.wrapping_sub(self.start).cast_unsigned().checked_add(1) else {
return RangeFull.sample(source);
};
let offset =
if bound.is_power_of_two() {
let sample: u64 = RangeFull.sample(source);
sample & (bound - 1)
} else { bounded64(bound as u64, source) as u64 };
self.start.wrapping_add_unsigned(offset)
}
}impl_range!(u64, i64as u64 => bounded64);
258impl Distribution<u128> for RangeInclusive<u128> {
/// Chooses a random number within the range.
///
/// Every possible result value is equally likely. In other words,
/// this operation uses unbiased uniform sampling.
///
/// # Panics
///
/// Panics if the range is empty.
///
/// # Side-channels
///
/// This implementation does not claim to be resistant against side-
/// channel attacks. In particular, the execution time of this operation
/// may leak information about the returned value, and not just the
/// values of the range bounds. While this implementation tries to
/// avoid operations with particularly data-dependent timing (such
/// as divisions), Rust as a language has no facilities for ensuring
/// data-independent timing, voiding all promises about side-channel-
/// freedom.
///
/// # Examples
///
/// A D20 dice roll:
/// ```
/// #![feature(random)]
///
/// use std::random::{Distribution, SystemRng};
/// use std::range::RangeInclusive;
///
/// let roll = RangeInclusive::from(1..=20).sample(&mut SystemRng);
/// assert!(1 <= roll && roll <= 20);
/// if roll == 20 {
/// println!("Wow! You achieve writing a sound linked list.");
/// } else {
/// println!("Miri attacks!");
/// }
/// ```
#[inline]
fn sample(&self, source: &mut (impl Rng + ?Sized)) -> u128 {
if self.start > self.last { empty_range(); }
if self.start == self.last { return self.start; }
let Some(bound) =
(self.last -
self.start).checked_add(1) else {
return RangeFull.sample(source);
};
let offset =
if bound.is_power_of_two() {
let sample: u128 = RangeFull.sample(source);
sample & (bound - 1)
} else { bounded128(bound as u128, source) as u128 };
self.start + offset
}
}
impl Distribution<i128> for RangeInclusive<i128> {
/// Chooses a random number within the range.
///
/// Every possible result value is equally likely. In other words,
/// this operation uses unbiased uniform sampling.
///
/// # Panics
///
/// Panics if the range is empty.
///
/// # Side-channels
///
/// This implementation does not claim to be resistant against side-
/// channel attacks. In particular, the execution time of this operation
/// may leak information about the returned value, and not just the
/// values of the range bounds. While this implementation tries to
/// avoid operations with particularly data-dependent timing (such
/// as divisions), Rust as a language has no facilities for ensuring
/// data-independent timing, voiding all promises about side-channel-
/// freedom.
///
/// # Examples
///
/// A D20 dice roll:
/// ```
/// #![feature(random)]
///
/// use std::random::{Distribution, SystemRng};
/// use std::range::RangeInclusive;
///
/// let roll = RangeInclusive::from(1..=20).sample(&mut SystemRng);
/// assert!(1 <= roll && roll <= 20);
/// if roll == 20 {
/// println!("Wow! You achieve writing a sound linked list.");
/// } else {
/// println!("Miri attacks!");
/// }
/// ```
#[inline]
fn sample(&self, source: &mut (impl Rng + ?Sized)) -> i128 {
if self.start > self.last { empty_range(); }
if self.start == self.last { return self.start; }
let Some(bound) =
self.last.wrapping_sub(self.start).cast_unsigned().checked_add(1) else {
return RangeFull.sample(source);
};
let offset =
if bound.is_power_of_two() {
let sample: u128 = RangeFull.sample(source);
sample & (bound - 1)
} else { bounded128(bound as u128, source) as u128 };
self.start.wrapping_add_unsigned(offset)
}
}impl_range!(u128, i128as u128 => bounded128);
259#[cfg(any(target_pointer_width = "16", target_pointer_width = "32",))]
260impl_range!(usize, isize as u32 => bounded32);
261#[cfg(target_pointer_width = "64")]
262impl Distribution<usize> for RangeInclusive<usize> {
/// Chooses a random number within the range.
///
/// Every possible result value is equally likely. In other words,
/// this operation uses unbiased uniform sampling.
///
/// # Panics
///
/// Panics if the range is empty.
///
/// # Side-channels
///
/// This implementation does not claim to be resistant against side-
/// channel attacks. In particular, the execution time of this operation
/// may leak information about the returned value, and not just the
/// values of the range bounds. While this implementation tries to
/// avoid operations with particularly data-dependent timing (such
/// as divisions), Rust as a language has no facilities for ensuring
/// data-independent timing, voiding all promises about side-channel-
/// freedom.
///
/// # Examples
///
/// A D20 dice roll:
/// ```
/// #![feature(random)]
///
/// use std::random::{Distribution, SystemRng};
/// use std::range::RangeInclusive;
///
/// let roll = RangeInclusive::from(1..=20).sample(&mut SystemRng);
/// assert!(1 <= roll && roll <= 20);
/// if roll == 20 {
/// println!("Wow! You achieve writing a sound linked list.");
/// } else {
/// println!("Miri attacks!");
/// }
/// ```
#[inline]
fn sample(&self, source: &mut (impl Rng + ?Sized)) -> usize {
if self.start > self.last { empty_range(); }
if self.start == self.last { return self.start; }
let Some(bound) =
(self.last -
self.start).checked_add(1) else {
return RangeFull.sample(source);
};
let offset =
if bound.is_power_of_two() {
let sample: usize = RangeFull.sample(source);
sample & (bound - 1)
} else { bounded64(bound as u64, source) as usize };
self.start + offset
}
}
impl Distribution<isize> for RangeInclusive<isize> {
/// Chooses a random number within the range.
///
/// Every possible result value is equally likely. In other words,
/// this operation uses unbiased uniform sampling.
///
/// # Panics
///
/// Panics if the range is empty.
///
/// # Side-channels
///
/// This implementation does not claim to be resistant against side-
/// channel attacks. In particular, the execution time of this operation
/// may leak information about the returned value, and not just the
/// values of the range bounds. While this implementation tries to
/// avoid operations with particularly data-dependent timing (such
/// as divisions), Rust as a language has no facilities for ensuring
/// data-independent timing, voiding all promises about side-channel-
/// freedom.
///
/// # Examples
///
/// A D20 dice roll:
/// ```
/// #![feature(random)]
///
/// use std::random::{Distribution, SystemRng};
/// use std::range::RangeInclusive;
///
/// let roll = RangeInclusive::from(1..=20).sample(&mut SystemRng);
/// assert!(1 <= roll && roll <= 20);
/// if roll == 20 {
/// println!("Wow! You achieve writing a sound linked list.");
/// } else {
/// println!("Miri attacks!");
/// }
/// ```
#[inline]
fn sample(&self, source: &mut (impl Rng + ?Sized)) -> isize {
if self.start > self.last { empty_range(); }
if self.start == self.last { return self.start; }
let Some(bound) =
self.last.wrapping_sub(self.start).cast_unsigned().checked_add(1) else {
return RangeFull.sample(source);
};
let offset =
if bound.is_power_of_two() {
let sample: usize = RangeFull.sample(source);
sample & (bound - 1)
} else { bounded64(bound as u64, source) as usize };
self.start.wrapping_add_unsigned(offset)
}
}impl_range!(usize, isizeas u64 => bounded64);