1use super::{Error, SampleBorrow, SampleUniform, UniformSampler};
13use crate::distr::utils::WideningMultiply;
14#[cfg(feature = "simd_support")]
15use crate::distr::{Distribution, StandardUniform};
16use crate::{Rng, RngExt};
17
18#[cfg(feature = "simd_support")]
19use core::simd::{Select, prelude::*};
20
21#[cfg(feature = "serde")]
22use serde::{Deserialize, Serialize};
23
24#[derive(#[automatically_derived]
impl<X: ::core::clone::Clone> ::core::clone::Clone for UniformInt<X> {
#[inline]
fn clone(&self) -> UniformInt<X> {
UniformInt {
low: ::core::clone::Clone::clone(&self.low),
range: ::core::clone::Clone::clone(&self.range),
thresh: ::core::clone::Clone::clone(&self.thresh),
}
}
}Clone, #[automatically_derived]
impl<X: ::core::marker::Copy> ::core::marker::Copy for UniformInt<X> { }Copy, #[automatically_derived]
impl<X: ::core::fmt::Debug> ::core::fmt::Debug for UniformInt<X> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field3_finish(f, "UniformInt",
"low", &self.low, "range", &self.range, "thresh", &&self.thresh)
}
}Debug, #[automatically_derived]
impl<X: ::core::cmp::PartialEq> ::core::cmp::PartialEq for UniformInt<X> {
#[inline]
fn eq(&self, other: &UniformInt<X>) -> bool {
self.low == other.low && self.range == other.range &&
self.thresh == other.thresh
}
}PartialEq, #[automatically_derived]
impl<X: ::core::cmp::Eq> ::core::cmp::Eq for UniformInt<X> {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_receiver_is_total_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<X>;
}
}Eq)]
68#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
69pub struct UniformInt<X> {
70 pub(super) low: X,
71 pub(super) range: X,
72 thresh: X, }
74
75macro_rules! uniform_int_impl {
76 ($ty:ty, $uty:ty, $sample_ty:ident) => {
77 impl SampleUniform for $ty {
78 type Sampler = UniformInt<$ty>;
79 }
80
81 impl UniformSampler for UniformInt<$ty> {
82 type X = $ty;
88
89 #[inline] fn new<B1, B2>(low_b: B1, high_b: B2) -> Result<Self, Error>
92 where
93 B1: SampleBorrow<Self::X> + Sized,
94 B2: SampleBorrow<Self::X> + Sized,
95 {
96 let low = *low_b.borrow();
97 let high = *high_b.borrow();
98 if !(low < high) {
99 return Err(Error::EmptyRange);
100 }
101 UniformSampler::new_inclusive(low, high - 1)
102 }
103
104 #[inline] fn new_inclusive<B1, B2>(low_b: B1, high_b: B2) -> Result<Self, Error>
107 where
108 B1: SampleBorrow<Self::X> + Sized,
109 B2: SampleBorrow<Self::X> + Sized,
110 {
111 let low = *low_b.borrow();
112 let high = *high_b.borrow();
113 if !(low <= high) {
114 return Err(Error::EmptyRange);
115 }
116
117 let range = high.wrapping_sub(low).wrapping_add(1) as $uty;
118 let thresh = if range > 0 {
119 let range = $sample_ty::from(range);
120 (range.wrapping_neg() % range)
121 } else {
122 0
123 };
124
125 Ok(UniformInt {
126 low,
127 range: range as $ty, thresh: thresh as $uty as $ty, })
130 }
131
132 #[inline]
134 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Self::X {
135 let range = self.range as $uty as $sample_ty;
136 if range == 0 {
137 return rng.random();
138 }
139
140 let thresh = self.thresh as $uty as $sample_ty;
141 let hi = loop {
142 let (hi, lo) = rng.random::<$sample_ty>().wmul(range);
143 if lo >= thresh {
144 break hi;
145 }
146 };
147 self.low.wrapping_add(hi as $ty)
148 }
149
150 #[inline]
151 fn sample_single<R: Rng + ?Sized, B1, B2>(
152 low_b: B1,
153 high_b: B2,
154 rng: &mut R,
155 ) -> Result<Self::X, Error>
156 where
157 B1: SampleBorrow<Self::X> + Sized,
158 B2: SampleBorrow<Self::X> + Sized,
159 {
160 let low = *low_b.borrow();
161 let high = *high_b.borrow();
162 if !(low < high) {
163 return Err(Error::EmptyRange);
164 }
165 Self::sample_single_inclusive(low, high - 1, rng)
166 }
167
168 #[cfg(not(feature = "unbiased"))]
173 #[inline]
174 fn sample_single_inclusive<R: Rng + ?Sized, B1, B2>(
175 low_b: B1,
176 high_b: B2,
177 rng: &mut R,
178 ) -> Result<Self::X, Error>
179 where
180 B1: SampleBorrow<Self::X> + Sized,
181 B2: SampleBorrow<Self::X> + Sized,
182 {
183 let low = *low_b.borrow();
184 let high = *high_b.borrow();
185 if !(low <= high) {
186 return Err(Error::EmptyRange);
187 }
188 let range = high.wrapping_sub(low).wrapping_add(1) as $uty as $sample_ty;
189 if range == 0 {
190 return Ok(rng.random());
192 }
193
194 let (mut result, lo_order) = rng.random::<$sample_ty>().wmul(range);
196
197 if lo_order > range.wrapping_neg() {
199 let (new_hi_order, _) = (rng.random::<$sample_ty>()).wmul(range as $sample_ty);
201 let is_overflow = lo_order.checked_add(new_hi_order as $sample_ty).is_none();
203 result += is_overflow as $sample_ty;
204 }
205
206 Ok(low.wrapping_add(result as $ty))
207 }
208
209 #[cfg(feature = "unbiased")]
211 #[inline]
212 fn sample_single_inclusive<R: Rng + ?Sized, B1, B2>(
213 low_b: B1,
214 high_b: B2,
215 rng: &mut R,
216 ) -> Result<Self::X, Error>
217 where
218 B1: SampleBorrow<$ty> + Sized,
219 B2: SampleBorrow<$ty> + Sized,
220 {
221 let low = *low_b.borrow();
222 let high = *high_b.borrow();
223 if !(low <= high) {
224 return Err(Error::EmptyRange);
225 }
226 let range = high.wrapping_sub(low).wrapping_add(1) as $uty as $sample_ty;
227 if range == 0 {
228 return Ok(rng.random());
230 }
231
232 let (mut result, mut lo) = rng.random::<$sample_ty>().wmul(range);
233
234 while lo > range.wrapping_neg() {
236 let (new_hi, new_lo) = (rng.random::<$sample_ty>()).wmul(range);
237 match lo.checked_add(new_hi) {
238 Some(x) if x < $sample_ty::MAX => {
239 break;
241 }
242 None => {
243 result += 1;
245 break;
246 }
247 _ => {
248 lo = new_lo;
250 continue;
251 }
252 }
253 }
254
255 Ok(low.wrapping_add(result as $ty))
256 }
257 }
258 };
259}
260
261impl SampleUniform for i8 {
type Sampler = UniformInt<i8>;
}
impl UniformSampler for UniformInt<i8> {
type X = i8;
#[inline]
fn new<B1, B2>(low_b: B1, high_b: B2) -> Result<Self, Error> where
B1: SampleBorrow<Self::X> + Sized, B2: SampleBorrow<Self::X> + Sized {
let low = *low_b.borrow();
let high = *high_b.borrow();
if !(low < high) { return Err(Error::EmptyRange); }
UniformSampler::new_inclusive(low, high - 1)
}
#[inline]
fn new_inclusive<B1, B2>(low_b: B1, high_b: B2) -> Result<Self, Error>
where B1: SampleBorrow<Self::X> + Sized, B2: SampleBorrow<Self::X> +
Sized {
let low = *low_b.borrow();
let high = *high_b.borrow();
if !(low <= high) { return Err(Error::EmptyRange); }
let range = high.wrapping_sub(low).wrapping_add(1) as u8;
let thresh =
if range > 0 {
let range = u32::from(range);
(range.wrapping_neg() % range)
} else { 0 };
Ok(UniformInt { low, range: range as i8, thresh: thresh as u8 as i8 })
}
#[inline]
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Self::X {
let range = self.range as u8 as u32;
if range == 0 { return rng.random(); }
let thresh = self.thresh as u8 as u32;
let hi =
loop {
let (hi, lo) = rng.random::<u32>().wmul(range);
if lo >= thresh { break hi; }
};
self.low.wrapping_add(hi as i8)
}
#[inline]
fn sample_single<R: Rng + ?Sized, B1,
B2>(low_b: B1, high_b: B2, rng: &mut R) -> Result<Self::X, Error>
where B1: SampleBorrow<Self::X> + Sized, B2: SampleBorrow<Self::X> +
Sized {
let low = *low_b.borrow();
let high = *high_b.borrow();
if !(low < high) { return Err(Error::EmptyRange); }
Self::sample_single_inclusive(low, high - 1, rng)
}
#[inline]
fn sample_single_inclusive<R: Rng + ?Sized, B1,
B2>(low_b: B1, high_b: B2, rng: &mut R) -> Result<Self::X, Error>
where B1: SampleBorrow<Self::X> + Sized, B2: SampleBorrow<Self::X> +
Sized {
let low = *low_b.borrow();
let high = *high_b.borrow();
if !(low <= high) { return Err(Error::EmptyRange); }
let range = high.wrapping_sub(low).wrapping_add(1) as u8 as u32;
if range == 0 { return Ok(rng.random()); }
let (mut result, lo_order) = rng.random::<u32>().wmul(range);
if lo_order > range.wrapping_neg() {
let (new_hi_order, _) = (rng.random::<u32>()).wmul(range as u32);
let is_overflow =
lo_order.checked_add(new_hi_order as u32).is_none();
result += is_overflow as u32;
}
Ok(low.wrapping_add(result as i8))
}
}uniform_int_impl! { i8, u8, u32 }
262impl SampleUniform for i16 {
type Sampler = UniformInt<i16>;
}
impl UniformSampler for UniformInt<i16> {
type X = i16;
#[inline]
fn new<B1, B2>(low_b: B1, high_b: B2) -> Result<Self, Error> where
B1: SampleBorrow<Self::X> + Sized, B2: SampleBorrow<Self::X> + Sized {
let low = *low_b.borrow();
let high = *high_b.borrow();
if !(low < high) { return Err(Error::EmptyRange); }
UniformSampler::new_inclusive(low, high - 1)
}
#[inline]
fn new_inclusive<B1, B2>(low_b: B1, high_b: B2) -> Result<Self, Error>
where B1: SampleBorrow<Self::X> + Sized, B2: SampleBorrow<Self::X> +
Sized {
let low = *low_b.borrow();
let high = *high_b.borrow();
if !(low <= high) { return Err(Error::EmptyRange); }
let range = high.wrapping_sub(low).wrapping_add(1) as u16;
let thresh =
if range > 0 {
let range = u32::from(range);
(range.wrapping_neg() % range)
} else { 0 };
Ok(UniformInt {
low,
range: range as i16,
thresh: thresh as u16 as i16,
})
}
#[inline]
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Self::X {
let range = self.range as u16 as u32;
if range == 0 { return rng.random(); }
let thresh = self.thresh as u16 as u32;
let hi =
loop {
let (hi, lo) = rng.random::<u32>().wmul(range);
if lo >= thresh { break hi; }
};
self.low.wrapping_add(hi as i16)
}
#[inline]
fn sample_single<R: Rng + ?Sized, B1,
B2>(low_b: B1, high_b: B2, rng: &mut R) -> Result<Self::X, Error>
where B1: SampleBorrow<Self::X> + Sized, B2: SampleBorrow<Self::X> +
Sized {
let low = *low_b.borrow();
let high = *high_b.borrow();
if !(low < high) { return Err(Error::EmptyRange); }
Self::sample_single_inclusive(low, high - 1, rng)
}
#[inline]
fn sample_single_inclusive<R: Rng + ?Sized, B1,
B2>(low_b: B1, high_b: B2, rng: &mut R) -> Result<Self::X, Error>
where B1: SampleBorrow<Self::X> + Sized, B2: SampleBorrow<Self::X> +
Sized {
let low = *low_b.borrow();
let high = *high_b.borrow();
if !(low <= high) { return Err(Error::EmptyRange); }
let range = high.wrapping_sub(low).wrapping_add(1) as u16 as u32;
if range == 0 { return Ok(rng.random()); }
let (mut result, lo_order) = rng.random::<u32>().wmul(range);
if lo_order > range.wrapping_neg() {
let (new_hi_order, _) = (rng.random::<u32>()).wmul(range as u32);
let is_overflow =
lo_order.checked_add(new_hi_order as u32).is_none();
result += is_overflow as u32;
}
Ok(low.wrapping_add(result as i16))
}
}uniform_int_impl! { i16, u16, u32 }
263impl SampleUniform for i32 {
type Sampler = UniformInt<i32>;
}
impl UniformSampler for UniformInt<i32> {
type X = i32;
#[inline]
fn new<B1, B2>(low_b: B1, high_b: B2) -> Result<Self, Error> where
B1: SampleBorrow<Self::X> + Sized, B2: SampleBorrow<Self::X> + Sized {
let low = *low_b.borrow();
let high = *high_b.borrow();
if !(low < high) { return Err(Error::EmptyRange); }
UniformSampler::new_inclusive(low, high - 1)
}
#[inline]
fn new_inclusive<B1, B2>(low_b: B1, high_b: B2) -> Result<Self, Error>
where B1: SampleBorrow<Self::X> + Sized, B2: SampleBorrow<Self::X> +
Sized {
let low = *low_b.borrow();
let high = *high_b.borrow();
if !(low <= high) { return Err(Error::EmptyRange); }
let range = high.wrapping_sub(low).wrapping_add(1) as u32;
let thresh =
if range > 0 {
let range = u32::from(range);
(range.wrapping_neg() % range)
} else { 0 };
Ok(UniformInt {
low,
range: range as i32,
thresh: thresh as u32 as i32,
})
}
#[inline]
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Self::X {
let range = self.range as u32 as u32;
if range == 0 { return rng.random(); }
let thresh = self.thresh as u32 as u32;
let hi =
loop {
let (hi, lo) = rng.random::<u32>().wmul(range);
if lo >= thresh { break hi; }
};
self.low.wrapping_add(hi as i32)
}
#[inline]
fn sample_single<R: Rng + ?Sized, B1,
B2>(low_b: B1, high_b: B2, rng: &mut R) -> Result<Self::X, Error>
where B1: SampleBorrow<Self::X> + Sized, B2: SampleBorrow<Self::X> +
Sized {
let low = *low_b.borrow();
let high = *high_b.borrow();
if !(low < high) { return Err(Error::EmptyRange); }
Self::sample_single_inclusive(low, high - 1, rng)
}
#[inline]
fn sample_single_inclusive<R: Rng + ?Sized, B1,
B2>(low_b: B1, high_b: B2, rng: &mut R) -> Result<Self::X, Error>
where B1: SampleBorrow<Self::X> + Sized, B2: SampleBorrow<Self::X> +
Sized {
let low = *low_b.borrow();
let high = *high_b.borrow();
if !(low <= high) { return Err(Error::EmptyRange); }
let range = high.wrapping_sub(low).wrapping_add(1) as u32 as u32;
if range == 0 { return Ok(rng.random()); }
let (mut result, lo_order) = rng.random::<u32>().wmul(range);
if lo_order > range.wrapping_neg() {
let (new_hi_order, _) = (rng.random::<u32>()).wmul(range as u32);
let is_overflow =
lo_order.checked_add(new_hi_order as u32).is_none();
result += is_overflow as u32;
}
Ok(low.wrapping_add(result as i32))
}
}uniform_int_impl! { i32, u32, u32 }
264impl SampleUniform for i64 {
type Sampler = UniformInt<i64>;
}
impl UniformSampler for UniformInt<i64> {
type X = i64;
#[inline]
fn new<B1, B2>(low_b: B1, high_b: B2) -> Result<Self, Error> where
B1: SampleBorrow<Self::X> + Sized, B2: SampleBorrow<Self::X> + Sized {
let low = *low_b.borrow();
let high = *high_b.borrow();
if !(low < high) { return Err(Error::EmptyRange); }
UniformSampler::new_inclusive(low, high - 1)
}
#[inline]
fn new_inclusive<B1, B2>(low_b: B1, high_b: B2) -> Result<Self, Error>
where B1: SampleBorrow<Self::X> + Sized, B2: SampleBorrow<Self::X> +
Sized {
let low = *low_b.borrow();
let high = *high_b.borrow();
if !(low <= high) { return Err(Error::EmptyRange); }
let range = high.wrapping_sub(low).wrapping_add(1) as u64;
let thresh =
if range > 0 {
let range = u64::from(range);
(range.wrapping_neg() % range)
} else { 0 };
Ok(UniformInt {
low,
range: range as i64,
thresh: thresh as u64 as i64,
})
}
#[inline]
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Self::X {
let range = self.range as u64 as u64;
if range == 0 { return rng.random(); }
let thresh = self.thresh as u64 as u64;
let hi =
loop {
let (hi, lo) = rng.random::<u64>().wmul(range);
if lo >= thresh { break hi; }
};
self.low.wrapping_add(hi as i64)
}
#[inline]
fn sample_single<R: Rng + ?Sized, B1,
B2>(low_b: B1, high_b: B2, rng: &mut R) -> Result<Self::X, Error>
where B1: SampleBorrow<Self::X> + Sized, B2: SampleBorrow<Self::X> +
Sized {
let low = *low_b.borrow();
let high = *high_b.borrow();
if !(low < high) { return Err(Error::EmptyRange); }
Self::sample_single_inclusive(low, high - 1, rng)
}
#[inline]
fn sample_single_inclusive<R: Rng + ?Sized, B1,
B2>(low_b: B1, high_b: B2, rng: &mut R) -> Result<Self::X, Error>
where B1: SampleBorrow<Self::X> + Sized, B2: SampleBorrow<Self::X> +
Sized {
let low = *low_b.borrow();
let high = *high_b.borrow();
if !(low <= high) { return Err(Error::EmptyRange); }
let range = high.wrapping_sub(low).wrapping_add(1) as u64 as u64;
if range == 0 { return Ok(rng.random()); }
let (mut result, lo_order) = rng.random::<u64>().wmul(range);
if lo_order > range.wrapping_neg() {
let (new_hi_order, _) = (rng.random::<u64>()).wmul(range as u64);
let is_overflow =
lo_order.checked_add(new_hi_order as u64).is_none();
result += is_overflow as u64;
}
Ok(low.wrapping_add(result as i64))
}
}uniform_int_impl! { i64, u64, u64 }
265impl SampleUniform for i128 {
type Sampler = UniformInt<i128>;
}
impl UniformSampler for UniformInt<i128> {
type X = i128;
#[inline]
fn new<B1, B2>(low_b: B1, high_b: B2) -> Result<Self, Error> where
B1: SampleBorrow<Self::X> + Sized, B2: SampleBorrow<Self::X> + Sized {
let low = *low_b.borrow();
let high = *high_b.borrow();
if !(low < high) { return Err(Error::EmptyRange); }
UniformSampler::new_inclusive(low, high - 1)
}
#[inline]
fn new_inclusive<B1, B2>(low_b: B1, high_b: B2) -> Result<Self, Error>
where B1: SampleBorrow<Self::X> + Sized, B2: SampleBorrow<Self::X> +
Sized {
let low = *low_b.borrow();
let high = *high_b.borrow();
if !(low <= high) { return Err(Error::EmptyRange); }
let range = high.wrapping_sub(low).wrapping_add(1) as u128;
let thresh =
if range > 0 {
let range = u128::from(range);
(range.wrapping_neg() % range)
} else { 0 };
Ok(UniformInt {
low,
range: range as i128,
thresh: thresh as u128 as i128,
})
}
#[inline]
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Self::X {
let range = self.range as u128 as u128;
if range == 0 { return rng.random(); }
let thresh = self.thresh as u128 as u128;
let hi =
loop {
let (hi, lo) = rng.random::<u128>().wmul(range);
if lo >= thresh { break hi; }
};
self.low.wrapping_add(hi as i128)
}
#[inline]
fn sample_single<R: Rng + ?Sized, B1,
B2>(low_b: B1, high_b: B2, rng: &mut R) -> Result<Self::X, Error>
where B1: SampleBorrow<Self::X> + Sized, B2: SampleBorrow<Self::X> +
Sized {
let low = *low_b.borrow();
let high = *high_b.borrow();
if !(low < high) { return Err(Error::EmptyRange); }
Self::sample_single_inclusive(low, high - 1, rng)
}
#[inline]
fn sample_single_inclusive<R: Rng + ?Sized, B1,
B2>(low_b: B1, high_b: B2, rng: &mut R) -> Result<Self::X, Error>
where B1: SampleBorrow<Self::X> + Sized, B2: SampleBorrow<Self::X> +
Sized {
let low = *low_b.borrow();
let high = *high_b.borrow();
if !(low <= high) { return Err(Error::EmptyRange); }
let range = high.wrapping_sub(low).wrapping_add(1) as u128 as u128;
if range == 0 { return Ok(rng.random()); }
let (mut result, lo_order) = rng.random::<u128>().wmul(range);
if lo_order > range.wrapping_neg() {
let (new_hi_order, _) =
(rng.random::<u128>()).wmul(range as u128);
let is_overflow =
lo_order.checked_add(new_hi_order as u128).is_none();
result += is_overflow as u128;
}
Ok(low.wrapping_add(result as i128))
}
}uniform_int_impl! { i128, u128, u128 }
266impl SampleUniform for u8 {
type Sampler = UniformInt<u8>;
}
impl UniformSampler for UniformInt<u8> {
type X = u8;
#[inline]
fn new<B1, B2>(low_b: B1, high_b: B2) -> Result<Self, Error> where
B1: SampleBorrow<Self::X> + Sized, B2: SampleBorrow<Self::X> + Sized {
let low = *low_b.borrow();
let high = *high_b.borrow();
if !(low < high) { return Err(Error::EmptyRange); }
UniformSampler::new_inclusive(low, high - 1)
}
#[inline]
fn new_inclusive<B1, B2>(low_b: B1, high_b: B2) -> Result<Self, Error>
where B1: SampleBorrow<Self::X> + Sized, B2: SampleBorrow<Self::X> +
Sized {
let low = *low_b.borrow();
let high = *high_b.borrow();
if !(low <= high) { return Err(Error::EmptyRange); }
let range = high.wrapping_sub(low).wrapping_add(1) as u8;
let thresh =
if range > 0 {
let range = u32::from(range);
(range.wrapping_neg() % range)
} else { 0 };
Ok(UniformInt { low, range: range as u8, thresh: thresh as u8 as u8 })
}
#[inline]
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Self::X {
let range = self.range as u8 as u32;
if range == 0 { return rng.random(); }
let thresh = self.thresh as u8 as u32;
let hi =
loop {
let (hi, lo) = rng.random::<u32>().wmul(range);
if lo >= thresh { break hi; }
};
self.low.wrapping_add(hi as u8)
}
#[inline]
fn sample_single<R: Rng + ?Sized, B1,
B2>(low_b: B1, high_b: B2, rng: &mut R) -> Result<Self::X, Error>
where B1: SampleBorrow<Self::X> + Sized, B2: SampleBorrow<Self::X> +
Sized {
let low = *low_b.borrow();
let high = *high_b.borrow();
if !(low < high) { return Err(Error::EmptyRange); }
Self::sample_single_inclusive(low, high - 1, rng)
}
#[inline]
fn sample_single_inclusive<R: Rng + ?Sized, B1,
B2>(low_b: B1, high_b: B2, rng: &mut R) -> Result<Self::X, Error>
where B1: SampleBorrow<Self::X> + Sized, B2: SampleBorrow<Self::X> +
Sized {
let low = *low_b.borrow();
let high = *high_b.borrow();
if !(low <= high) { return Err(Error::EmptyRange); }
let range = high.wrapping_sub(low).wrapping_add(1) as u8 as u32;
if range == 0 { return Ok(rng.random()); }
let (mut result, lo_order) = rng.random::<u32>().wmul(range);
if lo_order > range.wrapping_neg() {
let (new_hi_order, _) = (rng.random::<u32>()).wmul(range as u32);
let is_overflow =
lo_order.checked_add(new_hi_order as u32).is_none();
result += is_overflow as u32;
}
Ok(low.wrapping_add(result as u8))
}
}uniform_int_impl! { u8, u8, u32 }
267impl SampleUniform for u16 {
type Sampler = UniformInt<u16>;
}
impl UniformSampler for UniformInt<u16> {
type X = u16;
#[inline]
fn new<B1, B2>(low_b: B1, high_b: B2) -> Result<Self, Error> where
B1: SampleBorrow<Self::X> + Sized, B2: SampleBorrow<Self::X> + Sized {
let low = *low_b.borrow();
let high = *high_b.borrow();
if !(low < high) { return Err(Error::EmptyRange); }
UniformSampler::new_inclusive(low, high - 1)
}
#[inline]
fn new_inclusive<B1, B2>(low_b: B1, high_b: B2) -> Result<Self, Error>
where B1: SampleBorrow<Self::X> + Sized, B2: SampleBorrow<Self::X> +
Sized {
let low = *low_b.borrow();
let high = *high_b.borrow();
if !(low <= high) { return Err(Error::EmptyRange); }
let range = high.wrapping_sub(low).wrapping_add(1) as u16;
let thresh =
if range > 0 {
let range = u32::from(range);
(range.wrapping_neg() % range)
} else { 0 };
Ok(UniformInt {
low,
range: range as u16,
thresh: thresh as u16 as u16,
})
}
#[inline]
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Self::X {
let range = self.range as u16 as u32;
if range == 0 { return rng.random(); }
let thresh = self.thresh as u16 as u32;
let hi =
loop {
let (hi, lo) = rng.random::<u32>().wmul(range);
if lo >= thresh { break hi; }
};
self.low.wrapping_add(hi as u16)
}
#[inline]
fn sample_single<R: Rng + ?Sized, B1,
B2>(low_b: B1, high_b: B2, rng: &mut R) -> Result<Self::X, Error>
where B1: SampleBorrow<Self::X> + Sized, B2: SampleBorrow<Self::X> +
Sized {
let low = *low_b.borrow();
let high = *high_b.borrow();
if !(low < high) { return Err(Error::EmptyRange); }
Self::sample_single_inclusive(low, high - 1, rng)
}
#[inline]
fn sample_single_inclusive<R: Rng + ?Sized, B1,
B2>(low_b: B1, high_b: B2, rng: &mut R) -> Result<Self::X, Error>
where B1: SampleBorrow<Self::X> + Sized, B2: SampleBorrow<Self::X> +
Sized {
let low = *low_b.borrow();
let high = *high_b.borrow();
if !(low <= high) { return Err(Error::EmptyRange); }
let range = high.wrapping_sub(low).wrapping_add(1) as u16 as u32;
if range == 0 { return Ok(rng.random()); }
let (mut result, lo_order) = rng.random::<u32>().wmul(range);
if lo_order > range.wrapping_neg() {
let (new_hi_order, _) = (rng.random::<u32>()).wmul(range as u32);
let is_overflow =
lo_order.checked_add(new_hi_order as u32).is_none();
result += is_overflow as u32;
}
Ok(low.wrapping_add(result as u16))
}
}uniform_int_impl! { u16, u16, u32 }
268impl SampleUniform for u32 {
type Sampler = UniformInt<u32>;
}
impl UniformSampler for UniformInt<u32> {
type X = u32;
#[inline]
fn new<B1, B2>(low_b: B1, high_b: B2) -> Result<Self, Error> where
B1: SampleBorrow<Self::X> + Sized, B2: SampleBorrow<Self::X> + Sized {
let low = *low_b.borrow();
let high = *high_b.borrow();
if !(low < high) { return Err(Error::EmptyRange); }
UniformSampler::new_inclusive(low, high - 1)
}
#[inline]
fn new_inclusive<B1, B2>(low_b: B1, high_b: B2) -> Result<Self, Error>
where B1: SampleBorrow<Self::X> + Sized, B2: SampleBorrow<Self::X> +
Sized {
let low = *low_b.borrow();
let high = *high_b.borrow();
if !(low <= high) { return Err(Error::EmptyRange); }
let range = high.wrapping_sub(low).wrapping_add(1) as u32;
let thresh =
if range > 0 {
let range = u32::from(range);
(range.wrapping_neg() % range)
} else { 0 };
Ok(UniformInt {
low,
range: range as u32,
thresh: thresh as u32 as u32,
})
}
#[inline]
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Self::X {
let range = self.range as u32 as u32;
if range == 0 { return rng.random(); }
let thresh = self.thresh as u32 as u32;
let hi =
loop {
let (hi, lo) = rng.random::<u32>().wmul(range);
if lo >= thresh { break hi; }
};
self.low.wrapping_add(hi as u32)
}
#[inline]
fn sample_single<R: Rng + ?Sized, B1,
B2>(low_b: B1, high_b: B2, rng: &mut R) -> Result<Self::X, Error>
where B1: SampleBorrow<Self::X> + Sized, B2: SampleBorrow<Self::X> +
Sized {
let low = *low_b.borrow();
let high = *high_b.borrow();
if !(low < high) { return Err(Error::EmptyRange); }
Self::sample_single_inclusive(low, high - 1, rng)
}
#[inline]
fn sample_single_inclusive<R: Rng + ?Sized, B1,
B2>(low_b: B1, high_b: B2, rng: &mut R) -> Result<Self::X, Error>
where B1: SampleBorrow<Self::X> + Sized, B2: SampleBorrow<Self::X> +
Sized {
let low = *low_b.borrow();
let high = *high_b.borrow();
if !(low <= high) { return Err(Error::EmptyRange); }
let range = high.wrapping_sub(low).wrapping_add(1) as u32 as u32;
if range == 0 { return Ok(rng.random()); }
let (mut result, lo_order) = rng.random::<u32>().wmul(range);
if lo_order > range.wrapping_neg() {
let (new_hi_order, _) = (rng.random::<u32>()).wmul(range as u32);
let is_overflow =
lo_order.checked_add(new_hi_order as u32).is_none();
result += is_overflow as u32;
}
Ok(low.wrapping_add(result as u32))
}
}uniform_int_impl! { u32, u32, u32 }
269impl SampleUniform for u64 {
type Sampler = UniformInt<u64>;
}
impl UniformSampler for UniformInt<u64> {
type X = u64;
#[inline]
fn new<B1, B2>(low_b: B1, high_b: B2) -> Result<Self, Error> where
B1: SampleBorrow<Self::X> + Sized, B2: SampleBorrow<Self::X> + Sized {
let low = *low_b.borrow();
let high = *high_b.borrow();
if !(low < high) { return Err(Error::EmptyRange); }
UniformSampler::new_inclusive(low, high - 1)
}
#[inline]
fn new_inclusive<B1, B2>(low_b: B1, high_b: B2) -> Result<Self, Error>
where B1: SampleBorrow<Self::X> + Sized, B2: SampleBorrow<Self::X> +
Sized {
let low = *low_b.borrow();
let high = *high_b.borrow();
if !(low <= high) { return Err(Error::EmptyRange); }
let range = high.wrapping_sub(low).wrapping_add(1) as u64;
let thresh =
if range > 0 {
let range = u64::from(range);
(range.wrapping_neg() % range)
} else { 0 };
Ok(UniformInt {
low,
range: range as u64,
thresh: thresh as u64 as u64,
})
}
#[inline]
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Self::X {
let range = self.range as u64 as u64;
if range == 0 { return rng.random(); }
let thresh = self.thresh as u64 as u64;
let hi =
loop {
let (hi, lo) = rng.random::<u64>().wmul(range);
if lo >= thresh { break hi; }
};
self.low.wrapping_add(hi as u64)
}
#[inline]
fn sample_single<R: Rng + ?Sized, B1,
B2>(low_b: B1, high_b: B2, rng: &mut R) -> Result<Self::X, Error>
where B1: SampleBorrow<Self::X> + Sized, B2: SampleBorrow<Self::X> +
Sized {
let low = *low_b.borrow();
let high = *high_b.borrow();
if !(low < high) { return Err(Error::EmptyRange); }
Self::sample_single_inclusive(low, high - 1, rng)
}
#[inline]
fn sample_single_inclusive<R: Rng + ?Sized, B1,
B2>(low_b: B1, high_b: B2, rng: &mut R) -> Result<Self::X, Error>
where B1: SampleBorrow<Self::X> + Sized, B2: SampleBorrow<Self::X> +
Sized {
let low = *low_b.borrow();
let high = *high_b.borrow();
if !(low <= high) { return Err(Error::EmptyRange); }
let range = high.wrapping_sub(low).wrapping_add(1) as u64 as u64;
if range == 0 { return Ok(rng.random()); }
let (mut result, lo_order) = rng.random::<u64>().wmul(range);
if lo_order > range.wrapping_neg() {
let (new_hi_order, _) = (rng.random::<u64>()).wmul(range as u64);
let is_overflow =
lo_order.checked_add(new_hi_order as u64).is_none();
result += is_overflow as u64;
}
Ok(low.wrapping_add(result as u64))
}
}uniform_int_impl! { u64, u64, u64 }
270impl SampleUniform for u128 {
type Sampler = UniformInt<u128>;
}
impl UniformSampler for UniformInt<u128> {
type X = u128;
#[inline]
fn new<B1, B2>(low_b: B1, high_b: B2) -> Result<Self, Error> where
B1: SampleBorrow<Self::X> + Sized, B2: SampleBorrow<Self::X> + Sized {
let low = *low_b.borrow();
let high = *high_b.borrow();
if !(low < high) { return Err(Error::EmptyRange); }
UniformSampler::new_inclusive(low, high - 1)
}
#[inline]
fn new_inclusive<B1, B2>(low_b: B1, high_b: B2) -> Result<Self, Error>
where B1: SampleBorrow<Self::X> + Sized, B2: SampleBorrow<Self::X> +
Sized {
let low = *low_b.borrow();
let high = *high_b.borrow();
if !(low <= high) { return Err(Error::EmptyRange); }
let range = high.wrapping_sub(low).wrapping_add(1) as u128;
let thresh =
if range > 0 {
let range = u128::from(range);
(range.wrapping_neg() % range)
} else { 0 };
Ok(UniformInt {
low,
range: range as u128,
thresh: thresh as u128 as u128,
})
}
#[inline]
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Self::X {
let range = self.range as u128 as u128;
if range == 0 { return rng.random(); }
let thresh = self.thresh as u128 as u128;
let hi =
loop {
let (hi, lo) = rng.random::<u128>().wmul(range);
if lo >= thresh { break hi; }
};
self.low.wrapping_add(hi as u128)
}
#[inline]
fn sample_single<R: Rng + ?Sized, B1,
B2>(low_b: B1, high_b: B2, rng: &mut R) -> Result<Self::X, Error>
where B1: SampleBorrow<Self::X> + Sized, B2: SampleBorrow<Self::X> +
Sized {
let low = *low_b.borrow();
let high = *high_b.borrow();
if !(low < high) { return Err(Error::EmptyRange); }
Self::sample_single_inclusive(low, high - 1, rng)
}
#[inline]
fn sample_single_inclusive<R: Rng + ?Sized, B1,
B2>(low_b: B1, high_b: B2, rng: &mut R) -> Result<Self::X, Error>
where B1: SampleBorrow<Self::X> + Sized, B2: SampleBorrow<Self::X> +
Sized {
let low = *low_b.borrow();
let high = *high_b.borrow();
if !(low <= high) { return Err(Error::EmptyRange); }
let range = high.wrapping_sub(low).wrapping_add(1) as u128 as u128;
if range == 0 { return Ok(rng.random()); }
let (mut result, lo_order) = rng.random::<u128>().wmul(range);
if lo_order > range.wrapping_neg() {
let (new_hi_order, _) =
(rng.random::<u128>()).wmul(range as u128);
let is_overflow =
lo_order.checked_add(new_hi_order as u128).is_none();
result += is_overflow as u128;
}
Ok(low.wrapping_add(result as u128))
}
}uniform_int_impl! { u128, u128, u128 }
271
272#[cfg(feature = "simd_support")]
273macro_rules! uniform_simd_int_impl {
274 ($ty:ident, $unsigned:ident) => {
275 #[cfg(feature = "simd_support")]
282 impl<const LANES: usize> SampleUniform for Simd<$ty, LANES>
283 where
284 Simd<$unsigned, LANES>:
285 WideningMultiply<Output = (Simd<$unsigned, LANES>, Simd<$unsigned, LANES>)>,
286 StandardUniform: Distribution<Simd<$unsigned, LANES>>,
287 {
288 type Sampler = UniformInt<Simd<$ty, LANES>>;
289 }
290
291 #[cfg(feature = "simd_support")]
292 impl<const LANES: usize> UniformSampler for UniformInt<Simd<$ty, LANES>>
293 where
294 Simd<$unsigned, LANES>:
295 WideningMultiply<Output = (Simd<$unsigned, LANES>, Simd<$unsigned, LANES>)>,
296 StandardUniform: Distribution<Simd<$unsigned, LANES>>,
297 {
298 type X = Simd<$ty, LANES>;
299
300 #[inline] fn new<B1, B2>(low_b: B1, high_b: B2) -> Result<Self, Error>
303 where B1: SampleBorrow<Self::X> + Sized,
304 B2: SampleBorrow<Self::X> + Sized
305 {
306 let low = *low_b.borrow();
307 let high = *high_b.borrow();
308 if !(low.simd_lt(high).all()) {
309 return Err(Error::EmptyRange);
310 }
311 UniformSampler::new_inclusive(low, high - Simd::splat(1))
312 }
313
314 #[inline] fn new_inclusive<B1, B2>(low_b: B1, high_b: B2) -> Result<Self, Error>
317 where B1: SampleBorrow<Self::X> + Sized,
318 B2: SampleBorrow<Self::X> + Sized
319 {
320 let low = *low_b.borrow();
321 let high = *high_b.borrow();
322 if !(low.simd_le(high).all()) {
323 return Err(Error::EmptyRange);
324 }
325
326 let range: Simd<$unsigned, LANES> = ((high - low) + Simd::splat(1)).cast();
329
330 let not_full_range = range.simd_gt(Simd::splat(0));
332 let modulo = not_full_range.select(range, Simd::splat(1));
333 let ints_to_reject = range.wrapping_neg() % modulo;
334
335 Ok(UniformInt {
336 low,
337 range: range.cast(),
339 thresh: ints_to_reject.cast(),
340 })
341 }
342
343 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Self::X {
344 let range: Simd<$unsigned, LANES> = self.range.cast();
345 let thresh: Simd<$unsigned, LANES> = self.thresh.cast();
346
347 let mut v: Simd<$unsigned, LANES> = rng.random();
357 loop {
358 let (hi, lo) = v.wmul(range);
359 let mask = lo.simd_ge(thresh);
360 if mask.all() {
361 let hi: Simd<$ty, LANES> = hi.cast();
362 let result = self.low + hi;
364 let v: Simd<$ty, LANES> = v.cast();
368 return range.simd_gt(Simd::splat(0)).select(result, v);
369 }
370 v = mask.select(v, rng.random());
372 }
373 }
374 }
375 };
376
377 ($(($unsigned:ident, $signed:ident)),+) => {
379 $(
380 uniform_simd_int_impl!($unsigned, $unsigned);
381 uniform_simd_int_impl!($signed, $unsigned);
382 )+
383 };
384}
385
386#[cfg(feature = "simd_support")]
387uniform_simd_int_impl! { (u8, i8), (u16, i16), (u32, i32), (u64, i64) }
388
389#[cfg(any(target_pointer_width = "32", target_pointer_width = "64"))]
400#[derive(#[automatically_derived]
impl ::core::clone::Clone for UniformUsize {
#[inline]
fn clone(&self) -> UniformUsize {
let _: ::core::clone::AssertParamIsClone<usize>;
let _: ::core::clone::AssertParamIsClone<bool>;
*self
}
}Clone, #[automatically_derived]
impl ::core::marker::Copy for UniformUsize { }Copy, #[automatically_derived]
impl ::core::fmt::Debug for UniformUsize {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field4_finish(f, "UniformUsize",
"low", &self.low, "range", &self.range, "thresh", &self.thresh,
"mode64", &&self.mode64)
}
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for UniformUsize {
#[inline]
fn eq(&self, other: &UniformUsize) -> bool {
self.mode64 == other.mode64 && self.low == other.low &&
self.range == other.range && self.thresh == other.thresh
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for UniformUsize {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_receiver_is_total_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<usize>;
let _: ::core::cmp::AssertParamIsEq<bool>;
}
}Eq)]
401#[cfg_attr(all(feature = "serde"), derive(Serialize))]
402#[cfg_attr(
408 all(feature = "serde", target_pointer_width = "64"),
409 derive(Deserialize)
410)]
411pub struct UniformUsize {
412 low: usize,
414 range: usize,
416 thresh: usize,
418 #[cfg(target_pointer_width = "64")]
420 #[cfg_attr(feature = "serde", serde(default))]
423 mode64: bool,
424}
425
426#[cfg(any(target_pointer_width = "32", target_pointer_width = "64"))]
427impl SampleUniform for usize {
428 type Sampler = UniformUsize;
429}
430
431#[cfg(any(target_pointer_width = "32", target_pointer_width = "64"))]
432impl UniformSampler for UniformUsize {
433 type X = usize;
434
435 #[inline] fn new<B1, B2>(low_b: B1, high_b: B2) -> Result<Self, Error>
438 where
439 B1: SampleBorrow<Self::X> + Sized,
440 B2: SampleBorrow<Self::X> + Sized,
441 {
442 let low = *low_b.borrow();
443 let high = *high_b.borrow();
444 if !(low < high) {
445 return Err(Error::EmptyRange);
446 }
447
448 UniformSampler::new_inclusive(low, high - 1)
449 }
450
451 #[inline] fn new_inclusive<B1, B2>(low_b: B1, high_b: B2) -> Result<Self, Error>
454 where
455 B1: SampleBorrow<Self::X> + Sized,
456 B2: SampleBorrow<Self::X> + Sized,
457 {
458 let low = *low_b.borrow();
459 let high = *high_b.borrow();
460 if !(low <= high) {
461 return Err(Error::EmptyRange);
462 }
463
464 #[cfg(target_pointer_width = "64")]
465 let mode64 = high > (u32::MAX as usize);
466 #[cfg(target_pointer_width = "32")]
467 let mode64 = false;
468
469 let (range, thresh);
470 if truecfg!(target_pointer_width = "64") && !mode64 {
471 let range32 = (high as u32).wrapping_sub(low as u32).wrapping_add(1);
472 range = range32 as usize;
473 thresh = if range32 > 0 {
474 (range32.wrapping_neg() % range32) as usize
475 } else {
476 0
477 };
478 } else {
479 range = high.wrapping_sub(low).wrapping_add(1);
480 thresh = if range > 0 {
481 range.wrapping_neg() % range
482 } else {
483 0
484 };
485 }
486
487 Ok(UniformUsize {
488 low,
489 range,
490 thresh,
491 #[cfg(target_pointer_width = "64")]
492 mode64,
493 })
494 }
495
496 #[inline]
497 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> usize {
498 #[cfg(target_pointer_width = "32")]
499 let mode32 = true;
500 #[cfg(target_pointer_width = "64")]
501 let mode32 = !self.mode64;
502
503 if mode32 {
504 let range = self.range as u32;
505 if range == 0 {
506 return rng.random::<u32>() as usize;
507 }
508
509 let thresh = self.thresh as u32;
510 let hi = loop {
511 let (hi, lo) = rng.random::<u32>().wmul(range);
512 if lo >= thresh {
513 break hi;
514 }
515 };
516 self.low.wrapping_add(hi as usize)
517 } else {
518 let range = self.range as u64;
519 if range == 0 {
520 return rng.random::<u64>() as usize;
521 }
522
523 let thresh = self.thresh as u64;
524 let hi = loop {
525 let (hi, lo) = rng.random::<u64>().wmul(range);
526 if lo >= thresh {
527 break hi;
528 }
529 };
530 self.low.wrapping_add(hi as usize)
531 }
532 }
533
534 #[inline]
535 fn sample_single<R: Rng + ?Sized, B1, B2>(
536 low_b: B1,
537 high_b: B2,
538 rng: &mut R,
539 ) -> Result<Self::X, Error>
540 where
541 B1: SampleBorrow<Self::X> + Sized,
542 B2: SampleBorrow<Self::X> + Sized,
543 {
544 let low = *low_b.borrow();
545 let high = *high_b.borrow();
546 if !(low < high) {
547 return Err(Error::EmptyRange);
548 }
549
550 if truecfg!(target_pointer_width = "64") && high > (u32::MAX as usize) {
551 return UniformInt::<u64>::sample_single(low as u64, high as u64, rng)
552 .map(|x| x as usize);
553 }
554
555 UniformInt::<u32>::sample_single(low as u32, high as u32, rng).map(|x| x as usize)
556 }
557
558 #[inline]
559 fn sample_single_inclusive<R: Rng + ?Sized, B1, B2>(
560 low_b: B1,
561 high_b: B2,
562 rng: &mut R,
563 ) -> Result<Self::X, Error>
564 where
565 B1: SampleBorrow<Self::X> + Sized,
566 B2: SampleBorrow<Self::X> + Sized,
567 {
568 let low = *low_b.borrow();
569 let high = *high_b.borrow();
570 if !(low <= high) {
571 return Err(Error::EmptyRange);
572 }
573
574 if truecfg!(target_pointer_width = "64") && high > (u32::MAX as usize) {
575 return UniformInt::<u64>::sample_single_inclusive(low as u64, high as u64, rng)
576 .map(|x| x as usize);
577 }
578
579 UniformInt::<u32>::sample_single_inclusive(low as u32, high as u32, rng).map(|x| x as usize)
580 }
581}
582
583#[cfg(test)]
584mod tests {
585 use super::*;
586 use crate::distr::{Distribution, Uniform};
587 use core::fmt::Debug;
588 use core::ops::Add;
589
590 #[test]
591 fn test_uniform_bad_limits_equal_int() {
592 assert_eq!(Uniform::new(10, 10), Err(Error::EmptyRange));
593 }
594
595 #[test]
596 fn test_uniform_good_limits_equal_int() {
597 let mut rng = crate::test::rng(804);
598 let dist = Uniform::new_inclusive(10, 10).unwrap();
599 for _ in 0..20 {
600 assert_eq!(rng.sample(dist), 10);
601 }
602 }
603
604 #[test]
605 fn test_uniform_bad_limits_flipped_int() {
606 assert_eq!(Uniform::new(10, 5), Err(Error::EmptyRange));
607 }
608
609 #[test]
610 #[cfg_attr(miri, ignore)] fn test_integers() {
612 let mut rng = crate::test::rng(251);
613 macro_rules! t {
614 ($ty:ident, $v:expr, $le:expr, $lt:expr) => {{
615 for &(low, high) in $v.iter() {
616 let my_uniform = Uniform::new(low, high).unwrap();
617 for _ in 0..1000 {
618 let v: $ty = rng.sample(my_uniform);
619 assert!($le(low, v) && $lt(v, high));
620 }
621
622 let my_uniform = Uniform::new_inclusive(low, high).unwrap();
623 for _ in 0..1000 {
624 let v: $ty = rng.sample(my_uniform);
625 assert!($le(low, v) && $le(v, high));
626 }
627
628 let my_uniform = Uniform::new(&low, high).unwrap();
629 for _ in 0..1000 {
630 let v: $ty = rng.sample(my_uniform);
631 assert!($le(low, v) && $lt(v, high));
632 }
633
634 let my_uniform = Uniform::new_inclusive(&low, &high).unwrap();
635 for _ in 0..1000 {
636 let v: $ty = rng.sample(my_uniform);
637 assert!($le(low, v) && $le(v, high));
638 }
639
640 for _ in 0..1000 {
641 let v = <$ty as SampleUniform>::Sampler::sample_single(low, high, &mut rng).unwrap();
642 assert!($le(low, v) && $lt(v, high));
643 }
644
645 for _ in 0..1000 {
646 let v = <$ty as SampleUniform>::Sampler::sample_single_inclusive(low, high, &mut rng).unwrap();
647 assert!($le(low, v) && $le(v, high));
648 }
649 }
650 }};
651
652 ($($ty:ident),*) => {{
654 $(t!(
655 $ty,
656 [(0, 10), (10, 127), ($ty::MIN, $ty::MAX)],
657 |x, y| x <= y,
658 |x, y| x < y
659 );)*
660 }};
661
662 ($($ty:ident),* => $scalar:ident) => {{
664 $(t!(
665 $ty,
666 [
667 ($ty::splat(0), $ty::splat(10)),
668 ($ty::splat(10), $ty::splat(127)),
669 ($ty::splat($scalar::MIN), $ty::splat($scalar::MAX)),
670 ],
671 |x: $ty, y| x.simd_le(y).all(),
672 |x: $ty, y| x.simd_lt(y).all()
673 );)*
674 }};
675 }
676 t!(i8, i16, i32, i64, i128, u8, u16, u32, u64, usize, u128);
677
678 #[cfg(feature = "simd_support")]
679 {
680 t!(u8x4, u8x8, u8x16, u8x32, u8x64 => u8);
681 t!(i8x4, i8x8, i8x16, i8x32, i8x64 => i8);
682 t!(u16x2, u16x4, u16x8, u16x16, u16x32 => u16);
683 t!(i16x2, i16x4, i16x8, i16x16, i16x32 => i16);
684 t!(u32x2, u32x4, u32x8, u32x16 => u32);
685 t!(i32x2, i32x4, i32x8, i32x16 => i32);
686 t!(u64x2, u64x4, u64x8 => u64);
687 t!(i64x2, i64x4, i64x8 => i64);
688 }
689 }
690
691 #[test]
692 fn test_uniform_from_std_range() {
693 let r = Uniform::try_from(2u32..7).unwrap();
694 assert_eq!(r.0.low, 2);
695 assert_eq!(r.0.range, 5);
696 }
697
698 #[test]
699 fn test_uniform_from_std_range_bad_limits() {
700 #![allow(clippy::reversed_empty_ranges)]
701 assert!(Uniform::try_from(100..10).is_err());
702 assert!(Uniform::try_from(100..100).is_err());
703 }
704
705 #[test]
706 fn test_uniform_from_std_range_inclusive() {
707 let r = Uniform::try_from(2u32..=6).unwrap();
708 assert_eq!(r.0.low, 2);
709 assert_eq!(r.0.range, 5);
710 }
711
712 #[test]
713 fn test_uniform_from_std_range_inclusive_bad_limits() {
714 #![allow(clippy::reversed_empty_ranges)]
715 assert!(Uniform::try_from(100..=10).is_err());
716 assert!(Uniform::try_from(100..=99).is_err());
717 }
718
719 #[test]
720 fn value_stability() {
721 fn test_samples<T: SampleUniform + Copy + Debug + PartialEq + Add<T>>(
722 lb: T,
723 ub: T,
724 ub_excl: T,
725 expected: &[T],
726 ) where
727 Uniform<T>: Distribution<T>,
728 {
729 let mut rng = crate::test::rng(897);
730 let mut buf = [lb; 6];
731
732 for x in &mut buf[0..3] {
733 *x = T::Sampler::sample_single_inclusive(lb, ub, &mut rng).unwrap();
734 }
735
736 let distr = Uniform::new_inclusive(lb, ub).unwrap();
737 for x in &mut buf[3..6] {
738 *x = rng.sample(&distr);
739 }
740 assert_eq!(&buf, expected);
741
742 let mut rng = crate::test::rng(897);
743
744 for x in &mut buf[0..3] {
745 *x = T::Sampler::sample_single(lb, ub_excl, &mut rng).unwrap();
746 }
747
748 let distr = Uniform::new(lb, ub_excl).unwrap();
749 for x in &mut buf[3..6] {
750 *x = rng.sample(&distr);
751 }
752 assert_eq!(&buf, expected);
753 }
754
755 test_samples(-105i8, 111, 112, &[-99, -48, 107, 72, -19, 56]);
756 test_samples(2i16, 1352, 1353, &[43, 361, 1325, 1109, 539, 1005]);
757 test_samples(
758 -313853i32,
759 13513,
760 13514,
761 &[-303803, -226673, 6912, -45605, -183505, -70668],
762 );
763 test_samples(
764 131521i64,
765 6542165,
766 6542166,
767 &[1838724, 5384489, 4893692, 3712948, 3951509, 4094926],
768 );
769 test_samples(
770 -0x8000_0000_0000_0000_0000_0000_0000_0000i128,
771 -1,
772 0,
773 &[
774 -30725222750250982319765550926688025855,
775 -75088619368053423329503924805178012357,
776 -64950748766625548510467638647674468829,
777 -41794017901603587121582892414659436495,
778 -63623852319608406524605295913876414006,
779 -17404679390297612013597359206379189023,
780 ],
781 );
782 test_samples(11u8, 218, 219, &[17, 66, 214, 181, 93, 165]);
783 test_samples(11u16, 218, 219, &[17, 66, 214, 181, 93, 165]);
784 test_samples(11u32, 218, 219, &[17, 66, 214, 181, 93, 165]);
785 test_samples(11u64, 218, 219, &[66, 181, 165, 127, 134, 139]);
786 test_samples(11u128, 218, 219, &[181, 127, 139, 167, 141, 197]);
787 test_samples(11usize, 218, 219, &[17, 66, 214, 181, 93, 165]);
788
789 #[cfg(feature = "simd_support")]
790 {
791 let lb = Simd::from([11u8, 0, 128, 127]);
792 let ub = Simd::from([218, 254, 254, 254]);
793 let ub_excl = ub + Simd::splat(1);
794 test_samples(
795 lb,
796 ub,
797 ub_excl,
798 &[
799 Simd::from([13, 5, 237, 130]),
800 Simd::from([126, 186, 149, 161]),
801 Simd::from([103, 86, 234, 252]),
802 Simd::from([35, 18, 225, 231]),
803 Simd::from([106, 153, 246, 177]),
804 Simd::from([195, 168, 149, 222]),
805 ],
806 );
807 }
808 }
809
810 #[test]
811 fn test_uniform_usize_empty_range() {
812 assert_eq!(UniformUsize::new(10, 10), Err(Error::EmptyRange));
813 assert!(UniformUsize::new(10, 11).is_ok());
814
815 assert_eq!(UniformUsize::new_inclusive(10, 9), Err(Error::EmptyRange));
816 assert!(UniformUsize::new_inclusive(10, 10).is_ok());
817 }
818
819 #[test]
820 fn test_uniform_usize_constructors() {
821 assert_eq!(
822 UniformUsize::new_inclusive(u32::MAX as usize, u32::MAX as usize),
823 Ok(UniformUsize {
824 low: u32::MAX as usize,
825 range: 1,
826 thresh: 0,
827 #[cfg(target_pointer_width = "64")]
828 mode64: false
829 })
830 );
831 assert_eq!(
832 UniformUsize::new_inclusive(0, u32::MAX as usize),
833 Ok(UniformUsize {
834 low: 0,
835 range: 0,
836 thresh: 0,
837 #[cfg(target_pointer_width = "64")]
838 mode64: false
839 })
840 );
841 #[cfg(target_pointer_width = "64")]
842 assert_eq!(
843 UniformUsize::new_inclusive(0, u32::MAX as usize + 1),
844 Ok(UniformUsize {
845 low: 0,
846 range: u32::MAX as usize + 2,
847 thresh: 1,
848 mode64: true
849 })
850 );
851 #[cfg(target_pointer_width = "64")]
852 assert_eq!(
853 UniformUsize::new_inclusive(u32::MAX as usize, u64::MAX as usize),
854 Ok(UniformUsize {
855 low: u32::MAX as usize,
856 range: u64::MAX as usize - u32::MAX as usize + 1,
857 thresh: u32::MAX as usize,
858 mode64: true
859 })
860 );
861 }
862
863 #[cfg(all(feature = "serde", target_pointer_width = "64"))]
865 #[test]
866 fn test_uniform_usize_deserialization() {
867 use serde_json;
868 let original = UniformUsize::new_inclusive(10, 100).expect("creation");
869 let serialized = serde_json::to_string(&original).expect("serialization");
870 let deserialized: UniformUsize =
871 serde_json::from_str(&serialized).expect("deserialization");
872 assert_eq!(deserialized, original);
873 }
874
875 #[cfg(all(feature = "serde", target_pointer_width = "64"))]
876 #[test]
877 fn test_uniform_usize_deserialization_from_32bit() {
878 use serde_json;
879 let serialized_on_32bit = r#"{"low":10,"range":91,"thresh":74}"#;
880 let deserialized: UniformUsize =
881 serde_json::from_str(serialized_on_32bit).expect("deserialization");
882 assert_eq!(
883 deserialized,
884 UniformUsize::new_inclusive(10, 100).expect("creation")
885 );
886 }
887
888 #[cfg(all(feature = "serde", target_pointer_width = "64"))]
889 #[test]
890 fn test_uniform_usize_deserialization_64bit() {
891 use serde_json;
892 let original = UniformUsize::new_inclusive(1, u64::MAX as usize - 1).expect("creation");
893 assert!(original.mode64);
894 let serialized = serde_json::to_string(&original).expect("serialization");
895 let deserialized: UniformUsize =
896 serde_json::from_str(&serialized).expect("deserialization");
897 assert_eq!(deserialized, original);
898 }
899}