1 // Copyright 2018-2020 Developers of the Rand project.
2 // Copyright 2017 The Rust Project Developers.
4 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
5 // https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
6 // <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
7 // option. This file may not be copied, modified, or distributed
8 // except according to those terms.
10 //! A distribution uniformly sampling numbers within a given range.
12 //! [`Uniform`] is the standard distribution to sample uniformly from a range;
13 //! e.g. `Uniform::new_inclusive(1, 6)` can sample integers from 1 to 6, like a
14 //! standard die. [`Rng::gen_range`] supports any type supported by
17 //! This distribution is provided with support for several primitive types
18 //! (all integer and floating-point types) as well as [`std::time::Duration`],
19 //! and supports extension to user-defined types via a type-specific *back-end*
22 //! The types [`UniformInt`], [`UniformFloat`] and [`UniformDuration`] are the
23 //! back-ends supporting sampling from primitive integer and floating-point
24 //! ranges as well as from [`std::time::Duration`]; these types do not normally
25 //! need to be used directly (unless implementing a derived back-end).
30 //! use rand::{Rng, thread_rng};
31 //! use rand::distributions::Uniform;
33 //! let mut rng = thread_rng();
34 //! let side = Uniform::new(-10.0, 10.0);
36 //! // sample between 1 and 10 points
37 //! for _ in 0..rng.gen_range(1..=10) {
38 //! // sample a point from the square with sides -10 - 10 in two dimensions
39 //! let (x, y) = (rng.sample(side), rng.sample(side));
40 //! println!("Point: {}, {}", x, y);
44 //! # Extending `Uniform` to support a custom type
46 //! To extend [`Uniform`] to support your own types, write a back-end which
47 //! implements the [`UniformSampler`] trait, then implement the [`SampleUniform`]
48 //! helper trait to "register" your back-end. See the `MyF32` example below.
50 //! At a minimum, the back-end needs to store any parameters needed for sampling
51 //! (e.g. the target range) and implement `new`, `new_inclusive` and `sample`.
52 //! Those methods should include an assert to check the range is valid (i.e.
53 //! `low < high`). The example below merely wraps another back-end.
55 //! The `new`, `new_inclusive` and `sample_single` functions use arguments of
56 //! type SampleBorrow<X> in order to support passing in values by reference or
57 //! by value. In the implementation of these functions, you can choose to
58 //! simply use the reference returned by [`SampleBorrow::borrow`], or you can choose
59 //! to copy or clone the value, whatever is appropriate for your type.
62 //! use rand::prelude::*;
63 //! use rand::distributions::uniform::{Uniform, SampleUniform,
64 //! UniformSampler, UniformFloat, SampleBorrow};
66 //! struct MyF32(f32);
68 //! #[derive(Clone, Copy, Debug)]
69 //! struct UniformMyF32(UniformFloat<f32>);
71 //! impl UniformSampler for UniformMyF32 {
73 //! fn new<B1, B2>(low: B1, high: B2) -> Self
74 //! where B1: SampleBorrow<Self::X> + Sized,
75 //! B2: SampleBorrow<Self::X> + Sized
77 //! UniformMyF32(UniformFloat::<f32>::new(low.borrow().0, high.borrow().0))
79 //! fn new_inclusive<B1, B2>(low: B1, high: B2) -> Self
80 //! where B1: SampleBorrow<Self::X> + Sized,
81 //! B2: SampleBorrow<Self::X> + Sized
83 //! UniformMyF32(UniformFloat::<f32>::new_inclusive(
88 //! fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Self::X {
89 //! MyF32(self.0.sample(rng))
93 //! impl SampleUniform for MyF32 {
94 //! type Sampler = UniformMyF32;
97 //! let (low, high) = (MyF32(17.0f32), MyF32(22.0f32));
98 //! let uniform = Uniform::new(low, high);
99 //! let x = uniform.sample(&mut thread_rng());
102 //! [`SampleUniform`]: crate::distributions::uniform::SampleUniform
103 //! [`UniformSampler`]: crate::distributions::uniform::UniformSampler
104 //! [`UniformInt`]: crate::distributions::uniform::UniformInt
105 //! [`UniformFloat`]: crate::distributions::uniform::UniformFloat
106 //! [`UniformDuration`]: crate::distributions::uniform::UniformDuration
107 //! [`SampleBorrow::borrow`]: crate::distributions::uniform::SampleBorrow::borrow
109 use core
::time
::Duration
;
110 use core
::ops
::{Range, RangeInclusive}
;
112 use crate::distributions
::float
::IntoFloat
;
113 use crate::distributions
::utils
::{BoolAsSIMD, FloatAsSIMD, FloatSIMDUtils, WideningMultiply}
;
114 use crate::distributions
::Distribution
;
115 use crate::{Rng, RngCore}
;
117 #[cfg(not(feature = "std"))]
118 #[allow(unused_imports)] // rustc doesn't detect that this is actually used
119 use crate::distributions
::utils
::Float
;
121 #[cfg(feature = "simd_support")] use packed_simd::*;
123 #[cfg(feature = "serde1")]
124 use serde
::{Serialize, Deserialize}
;
126 /// Sample values uniformly between two bounds.
128 /// [`Uniform::new`] and [`Uniform::new_inclusive`] construct a uniform
129 /// distribution sampling from the given range; these functions may do extra
130 /// work up front to make sampling of multiple values faster. If only one sample
131 /// from the range is required, [`Rng::gen_range`] can be more efficient.
133 /// When sampling from a constant range, many calculations can happen at
134 /// compile-time and all methods should be fast; for floating-point ranges and
135 /// the full range of integer types this should have comparable performance to
136 /// the `Standard` distribution.
138 /// Steps are taken to avoid bias which might be present in naive
139 /// implementations; for example `rng.gen::<u8>() % 170` samples from the range
140 /// `[0, 169]` but is twice as likely to select numbers less than 85 than other
141 /// values. Further, the implementations here give more weight to the high-bits
142 /// generated by the RNG than the low bits, since with some RNGs the low-bits
143 /// are of lower quality than the high bits.
145 /// Implementations must sample in `[low, high)` range for
146 /// `Uniform::new(low, high)`, i.e., excluding `high`. In particular, care must
147 /// be taken to ensure that rounding never results values `< low` or `>= high`.
152 /// use rand::distributions::{Distribution, Uniform};
154 /// let between = Uniform::from(10..10000);
155 /// let mut rng = rand::thread_rng();
157 /// for _ in 0..1000 {
158 /// sum += between.sample(&mut rng);
160 /// println!("{}", sum);
163 /// For a single sample, [`Rng::gen_range`] may be preferred:
168 /// let mut rng = rand::thread_rng();
169 /// println!("{}", rng.gen_range(0..10));
172 /// [`new`]: Uniform::new
173 /// [`new_inclusive`]: Uniform::new_inclusive
174 /// [`Rng::gen_range`]: Rng::gen_range
175 #[derive(Clone, Copy, Debug, PartialEq)]
176 #[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
177 #[cfg_attr(feature = "serde1", serde(bound(serialize = "X::Sampler: Serialize")))]
178 #[cfg_attr(feature = "serde1", serde(bound(deserialize = "X::Sampler: Deserialize<'de>")))]
179 pub struct Uniform
<X
: SampleUniform
>(X
::Sampler
);
181 impl<X
: SampleUniform
> Uniform
<X
> {
182 /// Create a new `Uniform` instance which samples uniformly from the half
183 /// open range `[low, high)` (excluding `high`). Panics if `low >= high`.
184 pub fn new
<B1
, B2
>(low
: B1
, high
: B2
) -> Uniform
<X
>
186 B1
: SampleBorrow
<X
> + Sized
,
187 B2
: SampleBorrow
<X
> + Sized
,
189 Uniform(X
::Sampler
::new(low
, high
))
192 /// Create a new `Uniform` instance which samples uniformly from the closed
193 /// range `[low, high]` (inclusive). Panics if `low > high`.
194 pub fn new_inclusive
<B1
, B2
>(low
: B1
, high
: B2
) -> Uniform
<X
>
196 B1
: SampleBorrow
<X
> + Sized
,
197 B2
: SampleBorrow
<X
> + Sized
,
199 Uniform(X
::Sampler
::new_inclusive(low
, high
))
203 impl<X
: SampleUniform
> Distribution
<X
> for Uniform
<X
> {
204 fn sample
<R
: Rng
+ ?Sized
>(&self, rng
: &mut R
) -> X
{
209 /// Helper trait for creating objects using the correct implementation of
210 /// [`UniformSampler`] for the sampling type.
212 /// See the [module documentation] on how to implement [`Uniform`] range
213 /// sampling for a custom type.
215 /// [module documentation]: crate::distributions::uniform
216 pub trait SampleUniform
: Sized
{
217 /// The `UniformSampler` implementation supporting type `X`.
218 type Sampler
: UniformSampler
<X
= Self>;
221 /// Helper trait handling actual uniform sampling.
223 /// See the [module documentation] on how to implement [`Uniform`] range
224 /// sampling for a custom type.
226 /// Implementation of [`sample_single`] is optional, and is only useful when
227 /// the implementation can be faster than `Self::new(low, high).sample(rng)`.
229 /// [module documentation]: crate::distributions::uniform
230 /// [`sample_single`]: UniformSampler::sample_single
231 pub trait UniformSampler
: Sized
{
232 /// The type sampled by this implementation.
235 /// Construct self, with inclusive lower bound and exclusive upper bound
238 /// Usually users should not call this directly but instead use
239 /// `Uniform::new`, which asserts that `low < high` before calling this.
240 fn new
<B1
, B2
>(low
: B1
, high
: B2
) -> Self
242 B1
: SampleBorrow
<Self::X
> + Sized
,
243 B2
: SampleBorrow
<Self::X
> + Sized
;
245 /// Construct self, with inclusive bounds `[low, high]`.
247 /// Usually users should not call this directly but instead use
248 /// `Uniform::new_inclusive`, which asserts that `low <= high` before
250 fn new_inclusive
<B1
, B2
>(low
: B1
, high
: B2
) -> Self
252 B1
: SampleBorrow
<Self::X
> + Sized
,
253 B2
: SampleBorrow
<Self::X
> + Sized
;
256 fn sample
<R
: Rng
+ ?Sized
>(&self, rng
: &mut R
) -> Self::X
;
258 /// Sample a single value uniformly from a range with inclusive lower bound
259 /// and exclusive upper bound `[low, high)`.
261 /// By default this is implemented using
262 /// `UniformSampler::new(low, high).sample(rng)`. However, for some types
263 /// more optimal implementations for single usage may be provided via this
264 /// method (which is the case for integers and floats).
265 /// Results may not be identical.
267 /// Note that to use this method in a generic context, the type needs to be
268 /// retrieved via `SampleUniform::Sampler` as follows:
270 /// use rand::{thread_rng, distributions::uniform::{SampleUniform, UniformSampler}};
271 /// # #[allow(unused)]
272 /// fn sample_from_range<T: SampleUniform>(lb: T, ub: T) -> T {
273 /// let mut rng = thread_rng();
274 /// <T as SampleUniform>::Sampler::sample_single(lb, ub, &mut rng)
277 fn sample_single
<R
: Rng
+ ?Sized
, B1
, B2
>(low
: B1
, high
: B2
, rng
: &mut R
) -> Self::X
279 B1
: SampleBorrow
<Self::X
> + Sized
,
280 B2
: SampleBorrow
<Self::X
> + Sized
,
282 let uniform
: Self = UniformSampler
::new(low
, high
);
286 /// Sample a single value uniformly from a range with inclusive lower bound
287 /// and inclusive upper bound `[low, high]`.
289 /// By default this is implemented using
290 /// `UniformSampler::new_inclusive(low, high).sample(rng)`. However, for
291 /// some types more optimal implementations for single usage may be provided
293 /// Results may not be identical.
294 fn sample_single_inclusive
<R
: Rng
+ ?Sized
, B1
, B2
>(low
: B1
, high
: B2
, rng
: &mut R
)
296 where B1
: SampleBorrow
<Self::X
> + Sized
,
297 B2
: SampleBorrow
<Self::X
> + Sized
299 let uniform
: Self = UniformSampler
::new_inclusive(low
, high
);
304 impl<X
: SampleUniform
> From
<Range
<X
>> for Uniform
<X
> {
305 fn from(r
: ::core
::ops
::Range
<X
>) -> Uniform
<X
> {
306 Uniform
::new(r
.start
, r
.end
)
310 impl<X
: SampleUniform
> From
<RangeInclusive
<X
>> for Uniform
<X
> {
311 fn from(r
: ::core
::ops
::RangeInclusive
<X
>) -> Uniform
<X
> {
312 Uniform
::new_inclusive(r
.start(), r
.end())
317 /// Helper trait similar to [`Borrow`] but implemented
318 /// only for SampleUniform and references to SampleUniform in
319 /// order to resolve ambiguity issues.
321 /// [`Borrow`]: std::borrow::Borrow
322 pub trait SampleBorrow
<Borrowed
> {
323 /// Immutably borrows from an owned value. See [`Borrow::borrow`]
325 /// [`Borrow::borrow`]: std::borrow::Borrow::borrow
326 fn borrow(&self) -> &Borrowed
;
328 impl<Borrowed
> SampleBorrow
<Borrowed
> for Borrowed
329 where Borrowed
: SampleUniform
332 fn borrow(&self) -> &Borrowed
{
336 impl<'a
, Borrowed
> SampleBorrow
<Borrowed
> for &'a Borrowed
337 where Borrowed
: SampleUniform
340 fn borrow(&self) -> &Borrowed
{
345 /// Range that supports generating a single sample efficiently.
347 /// Any type implementing this trait can be used to specify the sampled range
348 /// for `Rng::gen_range`.
349 pub trait SampleRange
<T
> {
350 /// Generate a sample from the given range.
351 fn sample_single
<R
: RngCore
+ ?Sized
>(self, rng
: &mut R
) -> T
;
353 /// Check whether the range is empty.
354 fn is_empty(&self) -> bool
;
357 impl<T
: SampleUniform
+ PartialOrd
> SampleRange
<T
> for Range
<T
> {
359 fn sample_single
<R
: RngCore
+ ?Sized
>(self, rng
: &mut R
) -> T
{
360 T
::Sampler
::sample_single(self.start
, self.end
, rng
)
364 fn is_empty(&self) -> bool
{
365 !(self.start
< self.end
)
369 impl<T
: SampleUniform
+ PartialOrd
> SampleRange
<T
> for RangeInclusive
<T
> {
371 fn sample_single
<R
: RngCore
+ ?Sized
>(self, rng
: &mut R
) -> T
{
372 T
::Sampler
::sample_single_inclusive(self.start(), self.end(), rng
)
376 fn is_empty(&self) -> bool
{
377 !(self.start() <= self.end())
382 ////////////////////////////////////////////////////////////////////////////////
384 // What follows are all back-ends.
387 /// The back-end implementing [`UniformSampler`] for integer types.
389 /// Unless you are implementing [`UniformSampler`] for your own type, this type
390 /// should not be used directly, use [`Uniform`] instead.
392 /// # Implementation notes
394 /// For simplicity, we use the same generic struct `UniformInt<X>` for all
395 /// integer types `X`. This gives us only one field type, `X`; to store unsigned
396 /// values of this size, we take use the fact that these conversions are no-ops.
398 /// For a closed range, the number of possible numbers we should generate is
399 /// `range = (high - low + 1)`. To avoid bias, we must ensure that the size of
400 /// our sample space, `zone`, is a multiple of `range`; other values must be
401 /// rejected (by replacing with a new random sample).
403 /// As a special case, we use `range = 0` to represent the full range of the
404 /// result type (i.e. for `new_inclusive($ty::MIN, $ty::MAX)`).
406 /// The optimum `zone` is the largest product of `range` which fits in our
407 /// (unsigned) target type. We calculate this by calculating how many numbers we
408 /// must reject: `reject = (MAX + 1) % range = (MAX - range + 1) % range`. Any (large)
409 /// product of `range` will suffice, thus in `sample_single` we multiply by a
410 /// power of 2 via bit-shifting (faster but may cause more rejections).
412 /// The smallest integer PRNGs generate is `u32`. For 8- and 16-bit outputs we
413 /// use `u32` for our `zone` and samples (because it's not slower and because
414 /// it reduces the chance of having to reject a sample). In this case we cannot
415 /// store `zone` in the target type since it is too large, however we know
416 /// `ints_to_reject < range <= $unsigned::MAX`.
418 /// An alternative to using a modulus is widening multiply: After a widening
419 /// multiply by `range`, the result is in the high word. Then comparing the low
420 /// word against `zone` makes sure our distribution is uniform.
421 #[derive(Clone, Copy, Debug, PartialEq)]
422 #[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
423 pub struct UniformInt
<X
> {
426 z
: X
, // either ints_to_reject or zone depending on implementation
429 macro_rules
! uniform_int_impl
{
430 ($ty
:ty
, $unsigned
:ident
, $u_large
:ident
) => {
431 impl SampleUniform
for $ty
{
432 type Sampler
= UniformInt
<$ty
>;
435 impl UniformSampler
for UniformInt
<$ty
> {
436 // We play free and fast with unsigned vs signed here
437 // (when $ty is signed), but that's fine, since the
438 // contract of this macro is for $ty and $unsigned to be
439 // "bit-equal", so casting between them is a no-op.
443 #[inline] // if the range is constant, this helps LLVM to do the
444 // calculations at compile-time.
445 fn new
<B1
, B2
>(low_b
: B1
, high_b
: B2
) -> Self
447 B1
: SampleBorrow
<Self::X
> + Sized
,
448 B2
: SampleBorrow
<Self::X
> + Sized
,
450 let low
= *low_b
.borrow();
451 let high
= *high_b
.borrow();
452 assert
!(low
< high
, "Uniform::new called with `low >= high`");
453 UniformSampler
::new_inclusive(low
, high
- 1)
456 #[inline] // if the range is constant, this helps LLVM to do the
457 // calculations at compile-time.
458 fn new_inclusive
<B1
, B2
>(low_b
: B1
, high_b
: B2
) -> Self
460 B1
: SampleBorrow
<Self::X
> + Sized
,
461 B2
: SampleBorrow
<Self::X
> + Sized
,
463 let low
= *low_b
.borrow();
464 let high
= *high_b
.borrow();
467 "Uniform::new_inclusive called with `low > high`"
469 let unsigned_max
= ::core
::$u_large
::MAX
;
471 let range
= high
.wrapping_sub(low
).wrapping_add(1) as $unsigned
;
472 let ints_to_reject
= if range
> 0 {
473 let range
= $u_large
::from(range
);
474 (unsigned_max
- range
+ 1) % range
481 // These are really $unsigned values, but store as $ty:
483 z
: ints_to_reject
as $unsigned
as $ty
,
488 fn sample
<R
: Rng
+ ?Sized
>(&self, rng
: &mut R
) -> Self::X
{
489 let range
= self.range
as $unsigned
as $u_large
;
491 let unsigned_max
= ::core
::$u_large
::MAX
;
492 let zone
= unsigned_max
- (self.z
as $unsigned
as $u_large
);
494 let v
: $u_large
= rng
.gen();
495 let (hi
, lo
) = v
.wmul(range
);
497 return self.low
.wrapping_add(hi
as $ty
);
501 // Sample from the entire integer range.
507 fn sample_single
<R
: Rng
+ ?Sized
, B1
, B2
>(low_b
: B1
, high_b
: B2
, rng
: &mut R
) -> Self::X
509 B1
: SampleBorrow
<Self::X
> + Sized
,
510 B2
: SampleBorrow
<Self::X
> + Sized
,
512 let low
= *low_b
.borrow();
513 let high
= *high_b
.borrow();
514 assert
!(low
< high
, "UniformSampler::sample_single: low >= high");
515 Self::sample_single_inclusive(low
, high
- 1, rng
)
519 fn sample_single_inclusive
<R
: Rng
+ ?Sized
, B1
, B2
>(low_b
: B1
, high_b
: B2
, rng
: &mut R
) -> Self::X
521 B1
: SampleBorrow
<Self::X
> + Sized
,
522 B2
: SampleBorrow
<Self::X
> + Sized
,
524 let low
= *low_b
.borrow();
525 let high
= *high_b
.borrow();
526 assert
!(low
<= high
, "UniformSampler::sample_single_inclusive: low > high");
527 let range
= high
.wrapping_sub(low
).wrapping_add(1) as $unsigned
as $u_large
;
528 // If the above resulted in wrap-around to 0, the range is $ty::MIN..=$ty::MAX,
529 // and any integer will do.
534 let zone
= if ::core
::$unsigned
::MAX
<= ::core
::u16::MAX
as $unsigned
{
535 // Using a modulus is faster than the approximation for
536 // i8 and i16. I suppose we trade the cost of one
537 // modulus for near-perfect branch prediction.
538 let unsigned_max
: $u_large
= ::core
::$u_large
::MAX
;
539 let ints_to_reject
= (unsigned_max
- range
+ 1) % range
;
540 unsigned_max
- ints_to_reject
542 // conservative but fast approximation. `- 1` is necessary to allow the
543 // same comparison without bias.
544 (range
<< range
.leading_zeros()).wrapping_sub(1)
548 let v
: $u_large
= rng
.gen();
549 let (hi
, lo
) = v
.wmul(range
);
551 return low
.wrapping_add(hi
as $ty
);
559 uniform_int_impl
! { i8, u8, u32 }
560 uniform_int_impl
! { i16, u16, u32 }
561 uniform_int_impl
! { i32, u32, u32 }
562 uniform_int_impl
! { i64, u64, u64 }
563 uniform_int_impl
! { i128, u128, u128 }
564 uniform_int_impl
! { isize, usize, usize }
565 uniform_int_impl
! { u8, u8, u32 }
566 uniform_int_impl
! { u16, u16, u32 }
567 uniform_int_impl
! { u32, u32, u32 }
568 uniform_int_impl
! { u64, u64, u64 }
569 uniform_int_impl
! { usize, usize, usize }
570 uniform_int_impl
! { u128, u128, u128 }
572 #[cfg(feature = "simd_support")]
573 macro_rules
! uniform_simd_int_impl
{
574 ($ty
:ident
, $unsigned
:ident
, $u_scalar
:ident
) => {
575 // The "pick the largest zone that can fit in an `u32`" optimization
576 // is less useful here. Multiple lanes complicate things, we don't
577 // know the PRNG's minimal output size, and casting to a larger vector
578 // is generally a bad idea for SIMD performance. The user can still
579 // implement it manually.
581 // TODO: look into `Uniform::<u32x4>::new(0u32, 100)` functionality
582 // perhaps `impl SampleUniform for $u_scalar`?
583 impl SampleUniform
for $ty
{
584 type Sampler
= UniformInt
<$ty
>;
587 impl UniformSampler
for UniformInt
<$ty
> {
590 #[inline] // if the range is constant, this helps LLVM to do the
591 // calculations at compile-time.
592 fn new
<B1
, B2
>(low_b
: B1
, high_b
: B2
) -> Self
593 where B1
: SampleBorrow
<Self::X
> + Sized
,
594 B2
: SampleBorrow
<Self::X
> + Sized
596 let low
= *low_b
.borrow();
597 let high
= *high_b
.borrow();
598 assert
!(low
.lt(high
).all(), "Uniform::new called with `low >= high`");
599 UniformSampler
::new_inclusive(low
, high
- 1)
602 #[inline] // if the range is constant, this helps LLVM to do the
603 // calculations at compile-time.
604 fn new_inclusive
<B1
, B2
>(low_b
: B1
, high_b
: B2
) -> Self
605 where B1
: SampleBorrow
<Self::X
> + Sized
,
606 B2
: SampleBorrow
<Self::X
> + Sized
608 let low
= *low_b
.borrow();
609 let high
= *high_b
.borrow();
610 assert
!(low
.le(high
).all(),
611 "Uniform::new_inclusive called with `low > high`");
612 let unsigned_max
= ::core
::$u_scalar
::MAX
;
614 // NOTE: these may need to be replaced with explicitly
615 // wrapping operations if `packed_simd` changes
616 let range
: $unsigned
= ((high
- low
) + 1).cast();
617 // `% 0` will panic at runtime.
618 let not_full_range
= range
.gt($unsigned
::splat(0));
619 // replacing 0 with `unsigned_max` allows a faster `select`
621 let modulo
= not_full_range
.select(range
, $unsigned
::splat(unsigned_max
));
623 let ints_to_reject
= (unsigned_max
- range
+ 1) % modulo
;
624 // When `range` is 0, `lo` of `v.wmul(range)` will always be
625 // zero which means only one sample is needed.
626 let zone
= unsigned_max
- ints_to_reject
;
630 // These are really $unsigned values, but store as $ty:
636 fn sample
<R
: Rng
+ ?Sized
>(&self, rng
: &mut R
) -> Self::X
{
637 let range
: $unsigned
= self.range
.cast();
638 let zone
: $unsigned
= self.z
.cast();
640 // This might seem very slow, generating a whole new
641 // SIMD vector for every sample rejection. For most uses
642 // though, the chance of rejection is small and provides good
643 // general performance. With multiple lanes, that chance is
644 // multiplied. To mitigate this, we replace only the lanes of
645 // the vector which fail, iteratively reducing the chance of
646 // rejection. The replacement method does however add a little
647 // overhead. Benchmarking or calculating probabilities might
648 // reveal contexts where this replacement method is slower.
649 let mut v
: $unsigned
= rng
.gen();
651 let (hi
, lo
) = v
.wmul(range
);
652 let mask
= lo
.le(zone
);
654 let hi
: $ty
= hi
.cast();
656 let result
= self.low
+ hi
;
657 // `select` here compiles to a blend operation
658 // When `range.eq(0).none()` the compare and blend
659 // operations are avoided.
660 let v
: $ty
= v
.cast();
661 return range
.gt($unsigned
::splat(0)).select(result
, v
);
663 // Replace only the failing lanes
664 v
= mask
.select(v
, rng
.gen());
670 // bulk implementation
671 ($
(($unsigned
:ident
, $signed
:ident
),)+ $u_scalar
:ident
) => {
673 uniform_simd_int_impl
!($unsigned
, $unsigned
, $u_scalar
);
674 uniform_simd_int_impl
!($signed
, $unsigned
, $u_scalar
);
679 #[cfg(feature = "simd_support")]
680 uniform_simd_int_impl
! {
687 #[cfg(feature = "simd_support")]
688 uniform_simd_int_impl
! {
696 #[cfg(feature = "simd_support")]
697 uniform_simd_int_impl
! {
706 #[cfg(feature = "simd_support")]
707 uniform_simd_int_impl
! {
717 impl SampleUniform
for char {
718 type Sampler
= UniformChar
;
721 /// The back-end implementing [`UniformSampler`] for `char`.
723 /// Unless you are implementing [`UniformSampler`] for your own type, this type
724 /// should not be used directly, use [`Uniform`] instead.
726 /// This differs from integer range sampling since the range `0xD800..=0xDFFF`
727 /// are used for surrogate pairs in UCS and UTF-16, and consequently are not
728 /// valid Unicode code points. We must therefore avoid sampling values in this
730 #[derive(Clone, Copy, Debug)]
731 #[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
732 pub struct UniformChar
{
733 sampler
: UniformInt
<u32>,
736 /// UTF-16 surrogate range start
737 const CHAR_SURROGATE_START
: u32 = 0xD800;
738 /// UTF-16 surrogate range size
739 const CHAR_SURROGATE_LEN
: u32 = 0xE000 - CHAR_SURROGATE_START
;
741 /// Convert `char` to compressed `u32`
742 fn char_to_comp_u32(c
: char) -> u32 {
744 c
if c
>= CHAR_SURROGATE_START
=> c
- CHAR_SURROGATE_LEN
,
749 impl UniformSampler
for UniformChar
{
752 #[inline] // if the range is constant, this helps LLVM to do the
753 // calculations at compile-time.
754 fn new
<B1
, B2
>(low_b
: B1
, high_b
: B2
) -> Self
756 B1
: SampleBorrow
<Self::X
> + Sized
,
757 B2
: SampleBorrow
<Self::X
> + Sized
,
759 let low
= char_to_comp_u32(*low_b
.borrow());
760 let high
= char_to_comp_u32(*high_b
.borrow());
761 let sampler
= UniformInt
::<u32>::new(low
, high
);
762 UniformChar { sampler }
765 #[inline] // if the range is constant, this helps LLVM to do the
766 // calculations at compile-time.
767 fn new_inclusive
<B1
, B2
>(low_b
: B1
, high_b
: B2
) -> Self
769 B1
: SampleBorrow
<Self::X
> + Sized
,
770 B2
: SampleBorrow
<Self::X
> + Sized
,
772 let low
= char_to_comp_u32(*low_b
.borrow());
773 let high
= char_to_comp_u32(*high_b
.borrow());
774 let sampler
= UniformInt
::<u32>::new_inclusive(low
, high
);
775 UniformChar { sampler }
778 fn sample
<R
: Rng
+ ?Sized
>(&self, rng
: &mut R
) -> Self::X
{
779 let mut x
= self.sampler
.sample(rng
);
780 if x
>= CHAR_SURROGATE_START
{
781 x
+= CHAR_SURROGATE_LEN
;
783 // SAFETY: x must not be in surrogate range or greater than char::MAX.
784 // This relies on range constructors which accept char arguments.
785 // Validity of input char values is assumed.
786 unsafe { core::char::from_u32_unchecked(x) }
790 /// The back-end implementing [`UniformSampler`] for floating-point types.
792 /// Unless you are implementing [`UniformSampler`] for your own type, this type
793 /// should not be used directly, use [`Uniform`] instead.
795 /// # Implementation notes
797 /// Instead of generating a float in the `[0, 1)` range using [`Standard`], the
798 /// `UniformFloat` implementation converts the output of an PRNG itself. This
799 /// way one or two steps can be optimized out.
801 /// The floats are first converted to a value in the `[1, 2)` interval using a
802 /// transmute-based method, and then mapped to the expected range with a
803 /// multiply and addition. Values produced this way have what equals 23 bits of
804 /// random digits for an `f32`, and 52 for an `f64`.
806 /// [`new`]: UniformSampler::new
807 /// [`new_inclusive`]: UniformSampler::new_inclusive
808 /// [`Standard`]: crate::distributions::Standard
809 #[derive(Clone, Copy, Debug, PartialEq)]
810 #[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
811 pub struct UniformFloat
<X
> {
816 macro_rules
! uniform_float_impl
{
817 ($ty
:ty
, $uty
:ident
, $f_scalar
:ident
, $u_scalar
:ident
, $bits_to_discard
:expr
) => {
818 impl SampleUniform
for $ty
{
819 type Sampler
= UniformFloat
<$ty
>;
822 impl UniformSampler
for UniformFloat
<$ty
> {
825 fn new
<B1
, B2
>(low_b
: B1
, high_b
: B2
) -> Self
827 B1
: SampleBorrow
<Self::X
> + Sized
,
828 B2
: SampleBorrow
<Self::X
> + Sized
,
830 let low
= *low_b
.borrow();
831 let high
= *high_b
.borrow();
834 "Uniform::new called with `low` non-finite."
838 "Uniform::new called with `high` non-finite."
840 assert
!(low
.all_lt(high
), "Uniform::new called with `low >= high`");
841 let max_rand
= <$ty
>::splat(
842 (::core
::$u_scalar
::MAX
>> $bits_to_discard
).into_float_with_exponent(0) - 1.0,
845 let mut scale
= high
- low
;
846 assert
!(scale
.all_finite(), "Uniform::new: range overflow");
849 let mask
= (scale
* max_rand
+ low
).ge_mask(high
);
853 scale
= scale
.decrease_masked(mask
);
856 debug_assert
!(<$ty
>::splat(0.0).all_le(scale
));
858 UniformFloat { low, scale }
861 fn new_inclusive
<B1
, B2
>(low_b
: B1
, high_b
: B2
) -> Self
863 B1
: SampleBorrow
<Self::X
> + Sized
,
864 B2
: SampleBorrow
<Self::X
> + Sized
,
866 let low
= *low_b
.borrow();
867 let high
= *high_b
.borrow();
870 "Uniform::new_inclusive called with `low` non-finite."
874 "Uniform::new_inclusive called with `high` non-finite."
878 "Uniform::new_inclusive called with `low > high`"
880 let max_rand
= <$ty
>::splat(
881 (::core
::$u_scalar
::MAX
>> $bits_to_discard
).into_float_with_exponent(0) - 1.0,
884 let mut scale
= (high
- low
) / max_rand
;
885 assert
!(scale
.all_finite(), "Uniform::new_inclusive: range overflow");
888 let mask
= (scale
* max_rand
+ low
).gt_mask(high
);
892 scale
= scale
.decrease_masked(mask
);
895 debug_assert
!(<$ty
>::splat(0.0).all_le(scale
));
897 UniformFloat { low, scale }
900 fn sample
<R
: Rng
+ ?Sized
>(&self, rng
: &mut R
) -> Self::X
{
901 // Generate a value in the range [1, 2)
902 let value1_2
= (rng
.gen
::<$uty
>() >> $bits_to_discard
).into_float_with_exponent(0);
904 // Get a value in the range [0, 1) in order to avoid
905 // overflowing into infinity when multiplying with scale
906 let value0_1
= value1_2
- 1.0;
908 // We don't use `f64::mul_add`, because it is not available with
909 // `no_std`. Furthermore, it is slower for some targets (but
910 // faster for others). However, the order of multiplication and
911 // addition is important, because on some platforms (e.g. ARM)
912 // it will be optimized to a single (non-FMA) instruction.
913 value0_1
* self.scale
+ self.low
917 fn sample_single
<R
: Rng
+ ?Sized
, B1
, B2
>(low_b
: B1
, high_b
: B2
, rng
: &mut R
) -> Self::X
919 B1
: SampleBorrow
<Self::X
> + Sized
,
920 B2
: SampleBorrow
<Self::X
> + Sized
,
922 let low
= *low_b
.borrow();
923 let high
= *high_b
.borrow();
926 "UniformSampler::sample_single called with `low` non-finite."
930 "UniformSampler::sample_single called with `high` non-finite."
934 "UniformSampler::sample_single: low >= high"
936 let mut scale
= high
- low
;
937 assert
!(scale
.all_finite(), "UniformSampler::sample_single: range overflow");
940 // Generate a value in the range [1, 2)
942 (rng
.gen
::<$uty
>() >> $bits_to_discard
).into_float_with_exponent(0);
944 // Get a value in the range [0, 1) in order to avoid
945 // overflowing into infinity when multiplying with scale
946 let value0_1
= value1_2
- 1.0;
948 // Doing multiply before addition allows some architectures
949 // to use a single instruction.
950 let res
= value0_1
* scale
+ low
;
952 debug_assert
!(low
.all_le(res
) || !scale
.all_finite());
953 if res
.all_lt(high
) {
957 // This handles a number of edge cases.
958 // * `low` or `high` is NaN. In this case `scale` and
959 // `res` are going to end up as NaN.
960 // * `low` is negative infinity and `high` is finite.
961 // `scale` is going to be infinite and `res` will be
963 // * `high` is positive infinity and `low` is finite.
964 // `scale` is going to be infinite and `res` will
965 // be infinite or NaN (if value0_1 is 0).
966 // * `low` is negative infinity and `high` is positive
967 // infinity. `scale` will be infinite and `res` will
969 // * `low` and `high` are finite, but `high - low`
970 // overflows to infinite. `scale` will be infinite
971 // and `res` will be infinite or NaN (if value0_1 is 0).
972 // So if `high` or `low` are non-finite, we are guaranteed
973 // to fail the `res < high` check above and end up here.
975 // While we technically should check for non-finite `low`
976 // and `high` before entering the loop, by doing the checks
977 // here instead, we allow the common case to avoid these
978 // checks. But we are still guaranteed that if `low` or
979 // `high` are non-finite we'll end up here and can do the
980 // appropriate checks.
982 // Likewise `high - low` overflowing to infinity is also
983 // rare, so handle it here after the common case.
984 let mask
= !scale
.finite_mask();
987 low
.all_finite() && high
.all_finite(),
988 "Uniform::sample_single: low and high must be finite"
990 scale
= scale
.decrease_masked(mask
);
998 uniform_float_impl
! { f32, u32, f32, u32, 32 - 23 }
999 uniform_float_impl
! { f64, u64, f64, u64, 64 - 52 }
1001 #[cfg(feature = "simd_support")]
1002 uniform_float_impl
! { f32x2, u32x2, f32, u32, 32 - 23 }
1003 #[cfg(feature = "simd_support")]
1004 uniform_float_impl
! { f32x4, u32x4, f32, u32, 32 - 23 }
1005 #[cfg(feature = "simd_support")]
1006 uniform_float_impl
! { f32x8, u32x8, f32, u32, 32 - 23 }
1007 #[cfg(feature = "simd_support")]
1008 uniform_float_impl
! { f32x16, u32x16, f32, u32, 32 - 23 }
1010 #[cfg(feature = "simd_support")]
1011 uniform_float_impl
! { f64x2, u64x2, f64, u64, 64 - 52 }
1012 #[cfg(feature = "simd_support")]
1013 uniform_float_impl
! { f64x4, u64x4, f64, u64, 64 - 52 }
1014 #[cfg(feature = "simd_support")]
1015 uniform_float_impl
! { f64x8, u64x8, f64, u64, 64 - 52 }
1018 /// The back-end implementing [`UniformSampler`] for `Duration`.
1020 /// Unless you are implementing [`UniformSampler`] for your own types, this type
1021 /// should not be used directly, use [`Uniform`] instead.
1022 #[derive(Clone, Copy, Debug)]
1023 #[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
1024 pub struct UniformDuration
{
1025 mode
: UniformDurationMode
,
1029 #[derive(Debug, Copy, Clone)]
1030 #[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
1031 enum UniformDurationMode
{
1034 nanos
: Uniform
<u32>,
1037 nanos
: Uniform
<u64>,
1046 impl SampleUniform
for Duration
{
1047 type Sampler
= UniformDuration
;
1050 impl UniformSampler
for UniformDuration
{
1054 fn new
<B1
, B2
>(low_b
: B1
, high_b
: B2
) -> Self
1056 B1
: SampleBorrow
<Self::X
> + Sized
,
1057 B2
: SampleBorrow
<Self::X
> + Sized
,
1059 let low
= *low_b
.borrow();
1060 let high
= *high_b
.borrow();
1061 assert
!(low
< high
, "Uniform::new called with `low >= high`");
1062 UniformDuration
::new_inclusive(low
, high
- Duration
::new(0, 1))
1066 fn new_inclusive
<B1
, B2
>(low_b
: B1
, high_b
: B2
) -> Self
1068 B1
: SampleBorrow
<Self::X
> + Sized
,
1069 B2
: SampleBorrow
<Self::X
> + Sized
,
1071 let low
= *low_b
.borrow();
1072 let high
= *high_b
.borrow();
1075 "Uniform::new_inclusive called with `low > high`"
1078 let low_s
= low
.as_secs();
1079 let low_n
= low
.subsec_nanos();
1080 let mut high_s
= high
.as_secs();
1081 let mut high_n
= high
.subsec_nanos();
1085 high_n
+= 1_000_000_000;
1088 let mode
= if low_s
== high_s
{
1089 UniformDurationMode
::Small
{
1091 nanos
: Uniform
::new_inclusive(low_n
, high_n
),
1095 .checked_mul(1_000_000_000)
1096 .and_then(|n
| n
.checked_add(u64::from(high_n
)));
1098 if let Some(higher_bound
) = max
{
1099 let lower_bound
= low_s
* 1_000_000_000 + u64::from(low_n
);
1100 UniformDurationMode
::Medium
{
1101 nanos
: Uniform
::new_inclusive(lower_bound
, higher_bound
),
1104 // An offset is applied to simplify generation of nanoseconds
1105 let max_nanos
= high_n
- low_n
;
1106 UniformDurationMode
::Large
{
1109 secs
: Uniform
::new_inclusive(low_s
, high_s
),
1120 fn sample
<R
: Rng
+ ?Sized
>(&self, rng
: &mut R
) -> Duration
{
1122 UniformDurationMode
::Small { secs, nanos }
=> {
1123 let n
= nanos
.sample(rng
);
1124 Duration
::new(secs
, n
)
1126 UniformDurationMode
::Medium { nanos }
=> {
1127 let nanos
= nanos
.sample(rng
);
1128 Duration
::new(nanos
/ 1_000_000_000, (nanos
% 1_000_000_000) as u32)
1130 UniformDurationMode
::Large
{
1135 // constant folding means this is at least as fast as `Rng::sample(Range)`
1136 let nano_range
= Uniform
::new(0, 1_000_000_000);
1138 let s
= secs
.sample(rng
);
1139 let n
= nano_range
.sample(rng
);
1140 if !(s
== max_secs
&& n
> max_nanos
) {
1141 let sum
= n
+ self.offset
;
1142 break Duration
::new(s
, sum
);
1153 use crate::rngs
::mock
::StepRng
;
1156 #[cfg(feature = "serde1")]
1157 fn test_serialization_uniform_duration() {
1158 let distr
= UniformDuration
::new(Duration
::from_secs(10), Duration
::from_secs(60));
1159 let de_distr
: UniformDuration
= bincode
::deserialize(&bincode
::serialize(&distr
).unwrap()).unwrap();
1161 distr
.offset
, de_distr
.offset
1163 match (distr
.mode
, de_distr
.mode
) {
1164 (UniformDurationMode
::Small {secs: a_secs, nanos: a_nanos}
, UniformDurationMode
::Small {secs, nanos}
) => {
1165 assert_eq
!(a_secs
, secs
);
1167 assert_eq
!(a_nanos
.0.low
, nanos
.0.low
);
1168 assert_eq
!(a_nanos
.0.range
, nanos
.0.range
);
1169 assert_eq
!(a_nanos
.0.z
, nanos
.0.z
);
1171 (UniformDurationMode
::Medium {nanos: a_nanos}
, UniformDurationMode
::Medium {nanos}
) => {
1172 assert_eq
!(a_nanos
.0.low
, nanos
.0.low
);
1173 assert_eq
!(a_nanos
.0.range
, nanos
.0.range
);
1174 assert_eq
!(a_nanos
.0.z
, nanos
.0.z
);
1176 (UniformDurationMode
::Large {max_secs:a_max_secs, max_nanos:a_max_nanos, secs:a_secs}
, UniformDurationMode
::Large {max_secs, max_nanos, secs}
) => {
1177 assert_eq
!(a_max_secs
, max_secs
);
1178 assert_eq
!(a_max_nanos
, max_nanos
);
1180 assert_eq
!(a_secs
.0.low
, secs
.0.low
);
1181 assert_eq
!(a_secs
.0.range
, secs
.0.range
);
1182 assert_eq
!(a_secs
.0.z
, secs
.0.z
);
1184 _
=> panic
!("`UniformDurationMode` was not serialized/deserialized correctly")
1189 #[cfg(feature = "serde1")]
1190 fn test_uniform_serialization() {
1191 let unit_box
: Uniform
<i32> = Uniform
::new(-1, 1);
1192 let de_unit_box
: Uniform
<i32> = bincode
::deserialize(&bincode
::serialize(&unit_box
).unwrap()).unwrap();
1194 assert_eq
!(unit_box
.0.low
, de_unit_box
.0.low
);
1195 assert_eq
!(unit_box
.0.range
, de_unit_box
.0.range
);
1196 assert_eq
!(unit_box
.0.z
, de_unit_box
.0.z
);
1198 let unit_box
: Uniform
<f32> = Uniform
::new(-1., 1.);
1199 let de_unit_box
: Uniform
<f32> = bincode
::deserialize(&bincode
::serialize(&unit_box
).unwrap()).unwrap();
1201 assert_eq
!(unit_box
.0.low
, de_unit_box
.0.low
);
1202 assert_eq
!(unit_box
.0.scale
, de_unit_box
.0.scale
);
1207 fn test_uniform_bad_limits_equal_int() {
1208 Uniform
::new(10, 10);
1212 fn test_uniform_good_limits_equal_int() {
1213 let mut rng
= crate::test
::rng(804);
1214 let dist
= Uniform
::new_inclusive(10, 10);
1216 assert_eq
!(rng
.sample(dist
), 10);
1222 fn test_uniform_bad_limits_flipped_int() {
1223 Uniform
::new(10, 5);
1227 #[cfg_attr(miri, ignore)] // Miri is too slow
1228 fn test_integers() {
1229 use core
::{i128, u128}
;
1230 use core
::{i16, i32, i64, i8, isize}
;
1231 use core
::{u16, u32, u64, u8, usize}
;
1233 let mut rng
= crate::test
::rng(251);
1235 ($ty
:ident
, $v
:expr
, $le
:expr
, $lt
:expr
) => {{
1236 for &(low
, high
) in $v
.iter() {
1237 let my_uniform
= Uniform
::new(low
, high
);
1239 let v
: $ty
= rng
.sample(my_uniform
);
1240 assert
!($
le(low
, v
) && $
lt(v
, high
));
1243 let my_uniform
= Uniform
::new_inclusive(low
, high
);
1245 let v
: $ty
= rng
.sample(my_uniform
);
1246 assert
!($
le(low
, v
) && $
le(v
, high
));
1249 let my_uniform
= Uniform
::new(&low
, high
);
1251 let v
: $ty
= rng
.sample(my_uniform
);
1252 assert
!($
le(low
, v
) && $
lt(v
, high
));
1255 let my_uniform
= Uniform
::new_inclusive(&low
, &high
);
1257 let v
: $ty
= rng
.sample(my_uniform
);
1258 assert
!($
le(low
, v
) && $
le(v
, high
));
1262 let v
= <$ty
as SampleUniform
>::Sampler
::sample_single(low
, high
, &mut rng
);
1263 assert
!($
le(low
, v
) && $
lt(v
, high
));
1267 let v
= <$ty
as SampleUniform
>::Sampler
::sample_single_inclusive(low
, high
, &mut rng
);
1268 assert
!($
le(low
, v
) && $
le(v
, high
));
1274 ($
($ty
:ident
),*) => {{
1277 [(0, 10), (10, 127), ($ty
::MIN
, $ty
::MAX
)],
1284 ($
($ty
:ident
),* => $scalar
:ident
) => {{
1288 ($ty
::splat(0), $ty
::splat(10)),
1289 ($ty
::splat(10), $ty
::splat(127)),
1290 ($ty
::splat($scalar
::MIN
), $ty
::splat($scalar
::MAX
)),
1292 |x
: $ty
, y
| x
.le(y
).all(),
1293 |x
: $ty
, y
| x
.lt(y
).all()
1297 t
!(i8, i16, i32, i64, isize, u8, u16, u32, u64, usize, i128
, u128
);
1299 #[cfg(feature = "simd_support")]
1301 t
!(u8x2
, u8x4
, u8x8
, u8x16
, u8x32
, u8x64
=> u8);
1302 t
!(i8x2
, i8x4
, i8x8
, i8x16
, i8x32
, i8x64
=> i8);
1303 t
!(u16x2
, u16x4
, u16x8
, u16x16
, u16x32
=> u16);
1304 t
!(i16x2
, i16x4
, i16x8
, i16x16
, i16x32
=> i16);
1305 t
!(u32x2
, u32x4
, u32x8
, u32x16
=> u32);
1306 t
!(i32x2
, i32x4
, i32x8
, i32x16
=> i32);
1307 t
!(u64x2
, u64x4
, u64x8
=> u64);
1308 t
!(i64x2
, i64x4
, i64x8
=> i64);
1313 #[cfg_attr(miri, ignore)] // Miri is too slow
1315 let mut rng
= crate::test
::rng(891);
1316 let mut max
= core
::char::from_u32(0).unwrap();
1318 let c
= rng
.gen_range('A'
..='Z'
);
1319 assert
!(('A'
..='Z'
).contains(&c
));
1322 assert_eq
!(max
, 'Z'
);
1323 let d
= Uniform
::new(
1324 core
::char::from_u32(0xD7F0).unwrap(),
1325 core
::char::from_u32(0xE010).unwrap(),
1328 let c
= d
.sample(&mut rng
);
1329 assert
!((c
as u32) < 0xD800 || (c
as u32) > 0xDFFF);
1334 #[cfg_attr(miri, ignore)] // Miri is too slow
1336 let mut rng
= crate::test
::rng(252);
1337 let mut zero_rng
= StepRng
::new(0, 0);
1338 let mut max_rng
= StepRng
::new(0xffff_ffff_ffff_ffff, 0);
1340 ($ty
:ty
, $f_scalar
:ident
, $bits_shifted
:expr
) => {{
1341 let v
: &[($f_scalar
, $f_scalar
)] = &[
1346 (<$f_scalar
>::from_bits(0), <$f_scalar
>::from_bits(3)),
1347 (-<$f_scalar
>::from_bits(10), -<$f_scalar
>::from_bits(1)),
1348 (-<$f_scalar
>::from_bits(5), 0.0),
1349 (-<$f_scalar
>::from_bits(7), -0.0),
1350 (0.1 * ::core
::$f_scalar
::MAX
, ::core
::$f_scalar
::MAX
),
1351 (-::core
::$f_scalar
::MAX
* 0.2, ::core
::$f_scalar
::MAX
* 0.7),
1353 for &(low_scalar
, high_scalar
) in v
.iter() {
1354 for lane
in 0..<$ty
>::lanes() {
1355 let low
= <$ty
>::splat(0.0 as $f_scalar
).replace(lane
, low_scalar
);
1356 let high
= <$ty
>::splat(1.0 as $f_scalar
).replace(lane
, high_scalar
);
1357 let my_uniform
= Uniform
::new(low
, high
);
1358 let my_incl_uniform
= Uniform
::new_inclusive(low
, high
);
1360 let v
= rng
.sample(my_uniform
).extract(lane
);
1361 assert
!(low_scalar
<= v
&& v
< high_scalar
);
1362 let v
= rng
.sample(my_incl_uniform
).extract(lane
);
1363 assert
!(low_scalar
<= v
&& v
<= high_scalar
);
1364 let v
= <$ty
as SampleUniform
>::Sampler
1365 ::sample_single(low
, high
, &mut rng
).extract(lane
);
1366 assert
!(low_scalar
<= v
&& v
< high_scalar
);
1370 rng
.sample(Uniform
::new_inclusive(low
, low
)).extract(lane
),
1374 assert_eq
!(zero_rng
.sample(my_uniform
).extract(lane
), low_scalar
);
1375 assert_eq
!(zero_rng
.sample(my_incl_uniform
).extract(lane
), low_scalar
);
1376 assert_eq
!(<$ty
as SampleUniform
>::Sampler
1377 ::sample_single(low
, high
, &mut zero_rng
)
1378 .extract(lane
), low_scalar
);
1379 assert
!(max_rng
.sample(my_uniform
).extract(lane
) < high_scalar
);
1380 assert
!(max_rng
.sample(my_incl_uniform
).extract(lane
) <= high_scalar
);
1382 // Don't run this test for really tiny differences between high and low
1383 // since for those rounding might result in selecting high for a very
1385 if (high_scalar
- low_scalar
) > 0.0001 {
1386 let mut lowering_max_rng
= StepRng
::new(
1387 0xffff_ffff_ffff_ffff,
1388 (-1i64 << $bits_shifted
) as u64,
1391 <$ty
as SampleUniform
>::Sampler
1392 ::sample_single(low
, high
, &mut lowering_max_rng
)
1393 .extract(lane
) < high_scalar
1400 rng
.sample(Uniform
::new_inclusive(
1401 ::core
::$f_scalar
::MAX
,
1402 ::core
::$f_scalar
::MAX
1404 ::core
::$f_scalar
::MAX
1407 rng
.sample(Uniform
::new_inclusive(
1408 -::core
::$f_scalar
::MAX
,
1409 -::core
::$f_scalar
::MAX
1411 -::core
::$f_scalar
::MAX
1416 t
!(f32, f32, 32 - 23);
1417 t
!(f64, f64, 64 - 52);
1418 #[cfg(feature = "simd_support")]
1420 t
!(f32x2
, f32, 32 - 23);
1421 t
!(f32x4
, f32, 32 - 23);
1422 t
!(f32x8
, f32, 32 - 23);
1423 t
!(f32x16
, f32, 32 - 23);
1424 t
!(f64x2
, f64, 64 - 52);
1425 t
!(f64x4
, f64, 64 - 52);
1426 t
!(f64x8
, f64, 64 - 52);
1432 fn test_float_overflow() {
1433 let _
= Uniform
::from(::core
::f64::MIN
..::core
::f64::MAX
);
1438 fn test_float_overflow_single() {
1439 let mut rng
= crate::test
::rng(252);
1440 rng
.gen_range(::core
::f64::MIN
..::core
::f64::MAX
);
1446 not(target_arch
= "wasm32"),
1447 not(target_arch
= "asmjs")
1449 fn test_float_assertions() {
1450 use super::SampleUniform
;
1451 use std
::panic
::catch_unwind
;
1452 fn range
<T
: SampleUniform
>(low
: T
, high
: T
) {
1453 let mut rng
= crate::test
::rng(253);
1454 T
::Sampler
::sample_single(low
, high
, &mut rng
);
1458 ($ty
:ident
, $f_scalar
:ident
) => {{
1459 let v
: &[($f_scalar
, $f_scalar
)] = &[
1460 (::std
::$f_scalar
::NAN
, 0.0),
1461 (1.0, ::std
::$f_scalar
::NAN
),
1462 (::std
::$f_scalar
::NAN
, ::std
::$f_scalar
::NAN
),
1464 (::std
::$f_scalar
::MAX
, -::std
::$f_scalar
::MAX
),
1465 (::std
::$f_scalar
::INFINITY
, ::std
::$f_scalar
::INFINITY
),
1467 ::std
::$f_scalar
::NEG_INFINITY
,
1468 ::std
::$f_scalar
::NEG_INFINITY
,
1470 (::std
::$f_scalar
::NEG_INFINITY
, 5.0),
1471 (5.0, ::std
::$f_scalar
::INFINITY
),
1472 (::std
::$f_scalar
::NAN
, ::std
::$f_scalar
::INFINITY
),
1473 (::std
::$f_scalar
::NEG_INFINITY
, ::std
::$f_scalar
::NAN
),
1474 (::std
::$f_scalar
::NEG_INFINITY
, ::std
::$f_scalar
::INFINITY
),
1476 for &(low_scalar
, high_scalar
) in v
.iter() {
1477 for lane
in 0..<$ty
>::lanes() {
1478 let low
= <$ty
>::splat(0.0 as $f_scalar
).replace(lane
, low_scalar
);
1479 let high
= <$ty
>::splat(1.0 as $f_scalar
).replace(lane
, high_scalar
);
1480 assert
!(catch_unwind(|| range(low
, high
)).is_err());
1481 assert
!(catch_unwind(|| Uniform
::new(low
, high
)).is_err());
1482 assert
!(catch_unwind(|| Uniform
::new_inclusive(low
, high
)).is_err());
1483 assert
!(catch_unwind(|| range(low
, low
)).is_err());
1484 assert
!(catch_unwind(|| Uniform
::new(low
, low
)).is_err());
1492 #[cfg(feature = "simd_support")]
1506 #[cfg_attr(miri, ignore)] // Miri is too slow
1507 fn test_durations() {
1508 let mut rng
= crate::test
::rng(253);
1511 (Duration
::new(10, 50000), Duration
::new(100, 1234)),
1512 (Duration
::new(0, 100), Duration
::new(1, 50)),
1514 Duration
::new(0, 0),
1515 Duration
::new(u64::max_value(), 999_999_999),
1518 for &(low
, high
) in v
.iter() {
1519 let my_uniform
= Uniform
::new(low
, high
);
1521 let v
= rng
.sample(my_uniform
);
1522 assert
!(low
<= v
&& v
< high
);
1528 fn test_custom_uniform() {
1529 use crate::distributions
::uniform
::{
1530 SampleBorrow
, SampleUniform
, UniformFloat
, UniformSampler
,
1532 #[derive(Clone, Copy, PartialEq, PartialOrd)]
1536 #[derive(Clone, Copy, Debug)]
1537 struct UniformMyF32(UniformFloat
<f32>);
1538 impl UniformSampler
for UniformMyF32
{
1541 fn new
<B1
, B2
>(low
: B1
, high
: B2
) -> Self
1543 B1
: SampleBorrow
<Self::X
> + Sized
,
1544 B2
: SampleBorrow
<Self::X
> + Sized
,
1546 UniformMyF32(UniformFloat
::<f32>::new(low
.borrow().x
, high
.borrow().x
))
1549 fn new_inclusive
<B1
, B2
>(low
: B1
, high
: B2
) -> Self
1551 B1
: SampleBorrow
<Self::X
> + Sized
,
1552 B2
: SampleBorrow
<Self::X
> + Sized
,
1554 UniformSampler
::new(low
, high
)
1557 fn sample
<R
: Rng
+ ?Sized
>(&self, rng
: &mut R
) -> Self::X
{
1559 x
: self.0.sample(rng
),
1563 impl SampleUniform
for MyF32
{
1564 type Sampler
= UniformMyF32
;
1567 let (low
, high
) = (MyF32 { x: 17.0f32 }
, MyF32 { x: 22.0f32 }
);
1568 let uniform
= Uniform
::new(low
, high
);
1569 let mut rng
= crate::test
::rng(804);
1571 let x
: MyF32
= rng
.sample(uniform
);
1572 assert
!(low
<= x
&& x
< high
);
1577 fn test_uniform_from_std_range() {
1578 let r
= Uniform
::from(2u32..7);
1579 assert_eq
!(r
.0.low
, 2);
1580 assert_eq
!(r
.0.range
, 5);
1581 let r
= Uniform
::from(2.0f64..7.0);
1582 assert_eq
!(r
.0.low
, 2.0);
1583 assert_eq
!(r
.0.scale
, 5.0);
1587 fn test_uniform_from_std_range_inclusive() {
1588 let r
= Uniform
::from(2u32..=6);
1589 assert_eq
!(r
.0.low
, 2);
1590 assert_eq
!(r
.0.range
, 5);
1591 let r
= Uniform
::from(2.0f64..=7.0);
1592 assert_eq
!(r
.0.low
, 2.0);
1593 assert
!(r
.0.scale
> 5.0);
1594 assert
!(r
.0.scale
< 5.0 + 1e
-14);
1598 fn value_stability() {
1599 fn test_samples
<T
: SampleUniform
+ Copy
+ core
::fmt
::Debug
+ PartialEq
>(
1600 lb
: T
, ub
: T
, expected_single
: &[T
], expected_multiple
: &[T
],
1601 ) where Uniform
<T
>: Distribution
<T
> {
1602 let mut rng
= crate::test
::rng(897);
1603 let mut buf
= [lb
; 3];
1606 *x
= T
::Sampler
::sample_single(lb
, ub
, &mut rng
);
1608 assert_eq
!(&buf
, expected_single
);
1610 let distr
= Uniform
::new(lb
, ub
);
1612 *x
= rng
.sample(&distr
);
1614 assert_eq
!(&buf
, expected_multiple
);
1617 // We test on a sub-set of types; possibly we should do more.
1620 test_samples(11u8, 219, &[17, 66, 214], &[181, 93, 165]);
1621 test_samples(11u32, 219, &[17, 66, 214], &[181, 93, 165]);
1623 test_samples(0f32, 1e
-2f32, &[0.0003070104, 0.0026630748, 0.00979833], &[
1631 &[-4673848682.871551, 6388267422.932352, 4857075081.198343],
1632 &[1173375212.1808167, 1917642852.109581, 2365076174.3153973],
1636 Duration
::new(2, 0),
1637 Duration
::new(4, 0),
1639 Duration
::new(2, 532615131),
1640 Duration
::new(3, 638826742),
1641 Duration
::new(3, 485707508),
1644 Duration
::new(3, 117337521),
1645 Duration
::new(3, 191764285),
1646 Duration
::new(3, 236507617),
1652 fn uniform_distributions_can_be_compared() {
1653 assert_eq
!(Uniform
::new(1.0, 2.0), Uniform
::new(1.0, 2.0));
1655 // To cover UniformInt
1656 assert_eq
!(Uniform
::new(1 as u32, 2 as u32), Uniform
::new(1 as u32, 2 as u32));