fuchsia / third_party / rust-crates / 07cbccdb4f89c8cea98e22273c8550436ef7dc04 / . / rustc_deps / vendor / rand-0.5.6 / src / distributions / uniform.rs

// Copyright 2017 The Rust Project Developers. See the COPYRIGHT | |

// file at the top-level directory of this distribution and at | |

// https://rust-lang.org/COPYRIGHT. | |

// | |

// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |

// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |

// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your | |

// option. This file may not be copied, modified, or distributed | |

// except according to those terms. | |

//! A distribution uniformly sampling numbers within a given range. | |

//! | |

//! [`Uniform`] is the standard distribution to sample uniformly from a range; | |

//! e.g. `Uniform::new_inclusive(1, 6)` can sample integers from 1 to 6, like a | |

//! standard die. [`Rng::gen_range`] supports any type supported by | |

//! [`Uniform`]. | |

//! | |

//! This distribution is provided with support for several primitive types | |

//! (all integer and floating-point types) as well as `std::time::Duration`, | |

//! and supports extension to user-defined types via a type-specific *back-end* | |

//! implementation. | |

//! | |

//! The types [`UniformInt`], [`UniformFloat`] and [`UniformDuration`] are the | |

//! back-ends supporting sampling from primitive integer and floating-point | |

//! ranges as well as from `std::time::Duration`; these types do not normally | |

//! need to be used directly (unless implementing a derived back-end). | |

//! | |

//! # Example usage | |

//! | |

//! ``` | |

//! use rand::{Rng, thread_rng}; | |

//! use rand::distributions::Uniform; | |

//! | |

//! let mut rng = thread_rng(); | |

//! let side = Uniform::new(-10.0, 10.0); | |

//! | |

//! // sample between 1 and 10 points | |

//! for _ in 0..rng.gen_range(1, 11) { | |

//! // sample a point from the square with sides -10 - 10 in two dimensions | |

//! let (x, y) = (rng.sample(side), rng.sample(side)); | |

//! println!("Point: {}, {}", x, y); | |

//! } | |

//! ``` | |

//! | |

//! # Extending `Uniform` to support a custom type | |

//! | |

//! To extend [`Uniform`] to support your own types, write a back-end which | |

//! implements the [`UniformSampler`] trait, then implement the [`SampleUniform`] | |

//! helper trait to "register" your back-end. See the `MyF32` example below. | |

//! | |

//! At a minimum, the back-end needs to store any parameters needed for sampling | |

//! (e.g. the target range) and implement `new`, `new_inclusive` and `sample`. | |

//! Those methods should include an assert to check the range is valid (i.e. | |

//! `low < high`). The example below merely wraps another back-end. | |

//! | |

//! ``` | |

//! use rand::prelude::*; | |

//! use rand::distributions::uniform::{Uniform, SampleUniform, | |

//! UniformSampler, UniformFloat}; | |

//! | |

//! struct MyF32(f32); | |

//! | |

//! #[derive(Clone, Copy, Debug)] | |

//! struct UniformMyF32 { | |

//! inner: UniformFloat<f32>, | |

//! } | |

//! | |

//! impl UniformSampler for UniformMyF32 { | |

//! type X = MyF32; | |

//! fn new(low: Self::X, high: Self::X) -> Self { | |

//! UniformMyF32 { | |

//! inner: UniformFloat::<f32>::new(low.0, high.0), | |

//! } | |

//! } | |

//! fn new_inclusive(low: Self::X, high: Self::X) -> Self { | |

//! UniformSampler::new(low, high) | |

//! } | |

//! fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Self::X { | |

//! MyF32(self.inner.sample(rng)) | |

//! } | |

//! } | |

//! | |

//! impl SampleUniform for MyF32 { | |

//! type Sampler = UniformMyF32; | |

//! } | |

//! | |

//! let (low, high) = (MyF32(17.0f32), MyF32(22.0f32)); | |

//! let uniform = Uniform::new(low, high); | |

//! let x = uniform.sample(&mut thread_rng()); | |

//! ``` | |

//! | |

//! [`Uniform`]: struct.Uniform.html | |

//! [`Rng::gen_range`]: ../../trait.Rng.html#method.gen_range | |

//! [`SampleUniform`]: trait.SampleUniform.html | |

//! [`UniformSampler`]: trait.UniformSampler.html | |

//! [`UniformInt`]: struct.UniformInt.html | |

//! [`UniformFloat`]: struct.UniformFloat.html | |

//! [`UniformDuration`]: struct.UniformDuration.html | |

#[cfg(feature = "std")] | |

use std::time::Duration; | |

use Rng; | |

use distributions::Distribution; | |

use distributions::float::IntoFloat; | |

/// Sample values uniformly between two bounds. | |

/// | |

/// [`Uniform::new`] and [`Uniform::new_inclusive`] construct a uniform | |

/// distribution sampling from the given range; these functions may do extra | |

/// work up front to make sampling of multiple values faster. | |

/// | |

/// When sampling from a constant range, many calculations can happen at | |

/// compile-time and all methods should be fast; for floating-point ranges and | |

/// the full range of integer types this should have comparable performance to | |

/// the `Standard` distribution. | |

/// | |

/// Steps are taken to avoid bias which might be present in naive | |

/// implementations; for example `rng.gen::<u8>() % 170` samples from the range | |

/// `[0, 169]` but is twice as likely to select numbers less than 85 than other | |

/// values. Further, the implementations here give more weight to the high-bits | |

/// generated by the RNG than the low bits, since with some RNGs the low-bits | |

/// are of lower quality than the high bits. | |

/// | |

/// Implementations should attempt to sample in `[low, high)` for | |

/// `Uniform::new(low, high)`, i.e., excluding `high`, but this may be very | |

/// difficult. All the primitive integer types satisfy this property, and the | |

/// float types normally satisfy it, but rounding may mean `high` can occur. | |

/// | |

/// # Example | |

/// | |

/// ``` | |

/// use rand::distributions::{Distribution, Uniform}; | |

/// | |

/// fn main() { | |

/// let between = Uniform::from(10..10000); | |

/// let mut rng = rand::thread_rng(); | |

/// let mut sum = 0; | |

/// for _ in 0..1000 { | |

/// sum += between.sample(&mut rng); | |

/// } | |

/// println!("{}", sum); | |

/// } | |

/// ``` | |

/// | |

/// [`Uniform::new`]: struct.Uniform.html#method.new | |

/// [`Uniform::new_inclusive`]: struct.Uniform.html#method.new_inclusive | |

/// [`new`]: struct.Uniform.html#method.new | |

/// [`new_inclusive`]: struct.Uniform.html#method.new_inclusive | |

#[derive(Clone, Copy, Debug)] | |

pub struct Uniform<X: SampleUniform> { | |

inner: X::Sampler, | |

} | |

impl<X: SampleUniform> Uniform<X> { | |

/// Create a new `Uniform` instance which samples uniformly from the half | |

/// open range `[low, high)` (excluding `high`). Panics if `low >= high`. | |

pub fn new(low: X, high: X) -> Uniform<X> { | |

Uniform { inner: X::Sampler::new(low, high) } | |

} | |

/// Create a new `Uniform` instance which samples uniformly from the closed | |

/// range `[low, high]` (inclusive). Panics if `low > high`. | |

pub fn new_inclusive(low: X, high: X) -> Uniform<X> { | |

Uniform { inner: X::Sampler::new_inclusive(low, high) } | |

} | |

} | |

impl<X: SampleUniform> Distribution<X> for Uniform<X> { | |

fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> X { | |

self.inner.sample(rng) | |

} | |

} | |

/// Helper trait for creating objects using the correct implementation of | |

/// [`UniformSampler`] for the sampling type. | |

/// | |

/// See the [module documentation] on how to implement [`Uniform`] range | |

/// sampling for a custom type. | |

/// | |

/// [`UniformSampler`]: trait.UniformSampler.html | |

/// [module documentation]: index.html | |

/// [`Uniform`]: struct.Uniform.html | |

pub trait SampleUniform: Sized { | |

/// The `UniformSampler` implementation supporting type `X`. | |

type Sampler: UniformSampler<X = Self>; | |

} | |

/// Helper trait handling actual uniform sampling. | |

/// | |

/// See the [module documentation] on how to implement [`Uniform`] range | |

/// sampling for a custom type. | |

/// | |

/// Implementation of [`sample_single`] is optional, and is only useful when | |

/// the implementation can be faster than `Self::new(low, high).sample(rng)`. | |

/// | |

/// [module documentation]: index.html | |

/// [`Uniform`]: struct.Uniform.html | |

/// [`sample_single`]: trait.UniformSampler.html#method.sample_single | |

pub trait UniformSampler: Sized { | |

/// The type sampled by this implementation. | |

type X; | |

/// Construct self, with inclusive lower bound and exclusive upper bound | |

/// `[low, high)`. | |

/// | |

/// Usually users should not call this directly but instead use | |

/// `Uniform::new`, which asserts that `low < high` before calling this. | |

fn new(low: Self::X, high: Self::X) -> Self; | |

/// Construct self, with inclusive bounds `[low, high]`. | |

/// | |

/// Usually users should not call this directly but instead use | |

/// `Uniform::new_inclusive`, which asserts that `low <= high` before | |

/// calling this. | |

fn new_inclusive(low: Self::X, high: Self::X) -> Self; | |

/// Sample a value. | |

fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Self::X; | |

/// Sample a single value uniformly from a range with inclusive lower bound | |

/// and exclusive upper bound `[low, high)`. | |

/// | |

/// Usually users should not call this directly but instead use | |

/// `Uniform::sample_single`, which asserts that `low < high` before calling | |

/// this. | |

/// | |

/// Via this method, implementations can provide a method optimized for | |

/// sampling only a single value from the specified range. The default | |

/// implementation simply calls `UniformSampler::new` then `sample` on the | |

/// result. | |

fn sample_single<R: Rng + ?Sized>(low: Self::X, high: Self::X, rng: &mut R) | |

-> Self::X | |

{ | |

let uniform: Self = UniformSampler::new(low, high); | |

uniform.sample(rng) | |

} | |

} | |

impl<X: SampleUniform> From<::core::ops::Range<X>> for Uniform<X> { | |

fn from(r: ::core::ops::Range<X>) -> Uniform<X> { | |

Uniform::new(r.start, r.end) | |

} | |

} | |

//////////////////////////////////////////////////////////////////////////////// | |

// What follows are all back-ends. | |

/// The back-end implementing [`UniformSampler`] for integer types. | |

/// | |

/// Unless you are implementing [`UniformSampler`] for your own type, this type | |

/// should not be used directly, use [`Uniform`] instead. | |

/// | |

/// # Implementation notes | |

/// | |

/// For a closed range, the number of possible numbers we should generate is | |

/// `range = (high - low + 1)`. It is not possible to end up with a uniform | |

/// distribution if we map *all* the random integers that can be generated to | |

/// this range. We have to map integers from a `zone` that is a multiple of the | |

/// range. The rest of the integers, that cause a bias, are rejected. | |

/// | |

/// The problem with `range` is that to cover the full range of the type, it has | |

/// to store `unsigned_max + 1`, which can't be represented. But if the range | |

/// covers the full range of the type, no modulus is needed. A range of size 0 | |

/// can't exist, so we use that to represent this special case. Wrapping | |

/// arithmetic even makes representing `unsigned_max + 1` as 0 simple. | |

/// | |

/// We don't calculate `zone` directly, but first calculate the number of | |

/// integers to reject. To handle `unsigned_max + 1` not fitting in the type, | |

/// we use: | |

/// `ints_to_reject = (unsigned_max + 1) % range;` | |

/// `ints_to_reject = (unsigned_max - range + 1) % range;` | |

/// | |

/// The smallest integer PRNGs generate is `u32`. That is why for small integer | |

/// sizes (`i8`/`u8` and `i16`/`u16`) there is an optimization: don't pick the | |

/// largest zone that can fit in the small type, but pick the largest zone that | |

/// can fit in an `u32`. `ints_to_reject` is always less than half the size of | |

/// the small integer. This means the first bit of `zone` is always 1, and so | |

/// are all the other preceding bits of a larger integer. The easiest way to | |

/// grow the `zone` for the larger type is to simply sign extend it. | |

/// | |

/// An alternative to using a modulus is widening multiply: After a widening | |

/// multiply by `range`, the result is in the high word. Then comparing the low | |

/// word against `zone` makes sure our distribution is uniform. | |

/// | |

/// [`UniformSampler`]: trait.UniformSampler.html | |

/// [`Uniform`]: struct.Uniform.html | |

#[derive(Clone, Copy, Debug)] | |

pub struct UniformInt<X> { | |

low: X, | |

range: X, | |

zone: X, | |

} | |

macro_rules! uniform_int_impl { | |

($ty:ty, $signed:ty, $unsigned:ident, | |

$i_large:ident, $u_large:ident) => { | |

impl SampleUniform for $ty { | |

type Sampler = UniformInt<$ty>; | |

} | |

impl UniformSampler for UniformInt<$ty> { | |

// We play free and fast with unsigned vs signed here | |

// (when $ty is signed), but that's fine, since the | |

// contract of this macro is for $ty and $unsigned to be | |

// "bit-equal", so casting between them is a no-op. | |

type X = $ty; | |

#[inline] // if the range is constant, this helps LLVM to do the | |

// calculations at compile-time. | |

fn new(low: Self::X, high: Self::X) -> Self { | |

assert!(low < high, "Uniform::new called with `low >= high`"); | |

UniformSampler::new_inclusive(low, high - 1) | |

} | |

#[inline] // if the range is constant, this helps LLVM to do the | |

// calculations at compile-time. | |

fn new_inclusive(low: Self::X, high: Self::X) -> Self { | |

assert!(low <= high, | |

"Uniform::new_inclusive called with `low > high`"); | |

let unsigned_max = ::core::$unsigned::MAX; | |

let range = high.wrapping_sub(low).wrapping_add(1) as $unsigned; | |

let ints_to_reject = | |

if range > 0 { | |

(unsigned_max - range + 1) % range | |

} else { | |

0 | |

}; | |

let zone = unsigned_max - ints_to_reject; | |

UniformInt { | |

low: low, | |

// These are really $unsigned values, but store as $ty: | |

range: range as $ty, | |

zone: zone as $ty | |

} | |

} | |

fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Self::X { | |

let range = self.range as $unsigned as $u_large; | |

if range > 0 { | |

// Grow `zone` to fit a type of at least 32 bits, by | |

// sign-extending it (the first bit is always 1, so are all | |

// the preceding bits of the larger type). | |

// For types that already have the right size, all the | |

// casting is a no-op. | |

let zone = self.zone as $signed as $i_large as $u_large; | |

loop { | |

let v: $u_large = rng.gen(); | |

let (hi, lo) = v.wmul(range); | |

if lo <= zone { | |

return self.low.wrapping_add(hi as $ty); | |

} | |

} | |

} else { | |

// Sample from the entire integer range. | |

rng.gen() | |

} | |

} | |

fn sample_single<R: Rng + ?Sized>(low: Self::X, | |

high: Self::X, | |

rng: &mut R) -> Self::X | |

{ | |

assert!(low < high, | |

"Uniform::sample_single called with low >= high"); | |

let range = high.wrapping_sub(low) as $unsigned as $u_large; | |

let zone = | |

if ::core::$unsigned::MAX <= ::core::u16::MAX as $unsigned { | |

// Using a modulus is faster than the approximation for | |

// i8 and i16. I suppose we trade the cost of one | |

// modulus for near-perfect branch prediction. | |

let unsigned_max: $u_large = ::core::$u_large::MAX; | |

let ints_to_reject = (unsigned_max - range + 1) % range; | |

unsigned_max - ints_to_reject | |

} else { | |

// conservative but fast approximation | |

range << range.leading_zeros() | |

}; | |

loop { | |

let v: $u_large = rng.gen(); | |

let (hi, lo) = v.wmul(range); | |

if lo <= zone { | |

return low.wrapping_add(hi as $ty); | |

} | |

} | |

} | |

} | |

} | |

} | |

uniform_int_impl! { i8, i8, u8, i32, u32 } | |

uniform_int_impl! { i16, i16, u16, i32, u32 } | |

uniform_int_impl! { i32, i32, u32, i32, u32 } | |

uniform_int_impl! { i64, i64, u64, i64, u64 } | |

#[cfg(feature = "i128_support")] | |

uniform_int_impl! { i128, i128, u128, u128, u128 } | |

uniform_int_impl! { isize, isize, usize, isize, usize } | |

uniform_int_impl! { u8, i8, u8, i32, u32 } | |

uniform_int_impl! { u16, i16, u16, i32, u32 } | |

uniform_int_impl! { u32, i32, u32, i32, u32 } | |

uniform_int_impl! { u64, i64, u64, i64, u64 } | |

uniform_int_impl! { usize, isize, usize, isize, usize } | |

#[cfg(feature = "i128_support")] | |

uniform_int_impl! { u128, u128, u128, i128, u128 } | |

trait WideningMultiply<RHS = Self> { | |

type Output; | |

fn wmul(self, x: RHS) -> Self::Output; | |

} | |

macro_rules! wmul_impl { | |

($ty:ty, $wide:ty, $shift:expr) => { | |

impl WideningMultiply for $ty { | |

type Output = ($ty, $ty); | |

#[inline(always)] | |

fn wmul(self, x: $ty) -> Self::Output { | |

let tmp = (self as $wide) * (x as $wide); | |

((tmp >> $shift) as $ty, tmp as $ty) | |

} | |

} | |

} | |

} | |

wmul_impl! { u8, u16, 8 } | |

wmul_impl! { u16, u32, 16 } | |

wmul_impl! { u32, u64, 32 } | |

#[cfg(feature = "i128_support")] | |

wmul_impl! { u64, u128, 64 } | |

// This code is a translation of the __mulddi3 function in LLVM's | |

// compiler-rt. It is an optimised variant of the common method | |

// `(a + b) * (c + d) = ac + ad + bc + bd`. | |

// | |

// For some reason LLVM can optimise the C version very well, but | |

// keeps shuffeling registers in this Rust translation. | |

macro_rules! wmul_impl_large { | |

($ty:ty, $half:expr) => { | |

impl WideningMultiply for $ty { | |

type Output = ($ty, $ty); | |

#[inline(always)] | |

fn wmul(self, b: $ty) -> Self::Output { | |

const LOWER_MASK: $ty = !0 >> $half; | |

let mut low = (self & LOWER_MASK).wrapping_mul(b & LOWER_MASK); | |

let mut t = low >> $half; | |

low &= LOWER_MASK; | |

t += (self >> $half).wrapping_mul(b & LOWER_MASK); | |

low += (t & LOWER_MASK) << $half; | |

let mut high = t >> $half; | |

t = low >> $half; | |

low &= LOWER_MASK; | |

t += (b >> $half).wrapping_mul(self & LOWER_MASK); | |

low += (t & LOWER_MASK) << $half; | |

high += t >> $half; | |

high += (self >> $half).wrapping_mul(b >> $half); | |

(high, low) | |

} | |

} | |

} | |

} | |

#[cfg(not(feature = "i128_support"))] | |

wmul_impl_large! { u64, 32 } | |

#[cfg(feature = "i128_support")] | |

wmul_impl_large! { u128, 64 } | |

macro_rules! wmul_impl_usize { | |

($ty:ty) => { | |

impl WideningMultiply for usize { | |

type Output = (usize, usize); | |

#[inline(always)] | |

fn wmul(self, x: usize) -> Self::Output { | |

let (high, low) = (self as $ty).wmul(x as $ty); | |

(high as usize, low as usize) | |

} | |

} | |

} | |

} | |

#[cfg(target_pointer_width = "32")] | |

wmul_impl_usize! { u32 } | |

#[cfg(target_pointer_width = "64")] | |

wmul_impl_usize! { u64 } | |

/// The back-end implementing [`UniformSampler`] for floating-point types. | |

/// | |

/// Unless you are implementing [`UniformSampler`] for your own type, this type | |

/// should not be used directly, use [`Uniform`] instead. | |

/// | |

/// # Implementation notes | |

/// | |

/// Instead of generating a float in the `[0, 1)` range using [`Standard`], the | |

/// `UniformFloat` implementation converts the output of an PRNG itself. This | |

/// way one or two steps can be optimized out. | |

/// | |

/// The floats are first converted to a value in the `[1, 2)` interval using a | |

/// transmute-based method, and then mapped to the expected range with a | |

/// multiply and addition. Values produced this way have what equals 22 bits of | |

/// random digits for an `f32`, and 52 for an `f64`. | |

/// | |

/// Currently there is no difference between [`new`] and [`new_inclusive`], | |

/// because the boundaries of a floats range are a bit of a fuzzy concept due to | |

/// rounding errors. | |

/// | |

/// [`UniformSampler`]: trait.UniformSampler.html | |

/// [`new`]: trait.UniformSampler.html#tymethod.new | |

/// [`new_inclusive`]: trait.UniformSampler.html#tymethod.new_inclusive | |

/// [`Uniform`]: struct.Uniform.html | |

/// [`Standard`]: ../struct.Standard.html | |

#[derive(Clone, Copy, Debug)] | |

pub struct UniformFloat<X> { | |

scale: X, | |

offset: X, | |

} | |

macro_rules! uniform_float_impl { | |

($ty:ty, $bits_to_discard:expr, $next_u:ident) => { | |

impl SampleUniform for $ty { | |

type Sampler = UniformFloat<$ty>; | |

} | |

impl UniformSampler for UniformFloat<$ty> { | |

type X = $ty; | |

fn new(low: Self::X, high: Self::X) -> Self { | |

assert!(low < high, "Uniform::new called with `low >= high`"); | |

let scale = high - low; | |

let offset = low - scale; | |

UniformFloat { | |

scale: scale, | |

offset: offset, | |

} | |

} | |

fn new_inclusive(low: Self::X, high: Self::X) -> Self { | |

assert!(low <= high, | |

"Uniform::new_inclusive called with `low > high`"); | |

let scale = high - low; | |

let offset = low - scale; | |

UniformFloat { | |

scale: scale, | |

offset: offset, | |

} | |

} | |

fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Self::X { | |

// Generate a value in the range [1, 2) | |

let value1_2 = (rng.$next_u() >> $bits_to_discard) | |

.into_float_with_exponent(0); | |

// We don't use `f64::mul_add`, because it is not available with | |

// `no_std`. Furthermore, it is slower for some targets (but | |

// faster for others). However, the order of multiplication and | |

// addition is important, because on some platforms (e.g. ARM) | |

// it will be optimized to a single (non-FMA) instruction. | |

value1_2 * self.scale + self.offset | |

} | |

fn sample_single<R: Rng + ?Sized>(low: Self::X, | |

high: Self::X, | |

rng: &mut R) -> Self::X { | |

assert!(low < high, | |

"Uniform::sample_single called with low >= high"); | |

let scale = high - low; | |

let offset = low - scale; | |

// Generate a value in the range [1, 2) | |

let value1_2 = (rng.$next_u() >> $bits_to_discard) | |

.into_float_with_exponent(0); | |

// Doing multiply before addition allows some architectures to | |

// use a single instruction. | |

value1_2 * scale + offset | |

} | |

} | |

} | |

} | |

uniform_float_impl! { f32, 32 - 23, next_u32 } | |

uniform_float_impl! { f64, 64 - 52, next_u64 } | |

/// The back-end implementing [`UniformSampler`] for `Duration`. | |

/// | |

/// Unless you are implementing [`UniformSampler`] for your own types, this type | |

/// should not be used directly, use [`Uniform`] instead. | |

/// | |

/// [`UniformSampler`]: trait.UniformSampler.html | |

/// [`Uniform`]: struct.Uniform.html | |

#[cfg(feature = "std")] | |

#[derive(Clone, Copy, Debug)] | |

pub struct UniformDuration { | |

offset: Duration, | |

mode: UniformDurationMode, | |

} | |

#[cfg(feature = "std")] | |

#[derive(Debug, Copy, Clone)] | |

enum UniformDurationMode { | |

Small { | |

nanos: Uniform<u64>, | |

}, | |

Large { | |

size: Duration, | |

secs: Uniform<u64>, | |

} | |

} | |

#[cfg(feature = "std")] | |

impl SampleUniform for Duration { | |

type Sampler = UniformDuration; | |

} | |

#[cfg(feature = "std")] | |

impl UniformSampler for UniformDuration { | |

type X = Duration; | |

#[inline] | |

fn new(low: Duration, high: Duration) -> UniformDuration { | |

assert!(low < high, "Uniform::new called with `low >= high`"); | |

UniformDuration::new_inclusive(low, high - Duration::new(0, 1)) | |

} | |

#[inline] | |

fn new_inclusive(low: Duration, high: Duration) -> UniformDuration { | |

assert!(low <= high, "Uniform::new_inclusive called with `low > high`"); | |

let size = high - low; | |

let nanos = size | |

.as_secs() | |

.checked_mul(1_000_000_000) | |

.and_then(|n| n.checked_add(size.subsec_nanos() as u64)); | |

let mode = match nanos { | |

Some(nanos) => { | |

UniformDurationMode::Small { | |

nanos: Uniform::new_inclusive(0, nanos), | |

} | |

} | |

None => { | |

UniformDurationMode::Large { | |

size: size, | |

secs: Uniform::new_inclusive(0, size.as_secs()), | |

} | |

} | |

}; | |

UniformDuration { | |

mode, | |

offset: low, | |

} | |

} | |

#[inline] | |

fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Duration { | |

let d = match self.mode { | |

UniformDurationMode::Small { nanos } => { | |

let nanos = nanos.sample(rng); | |

Duration::new(nanos / 1_000_000_000, (nanos % 1_000_000_000) as u32) | |

} | |

UniformDurationMode::Large { size, secs } => { | |

// constant folding means this is at least as fast as `gen_range` | |

let nano_range = Uniform::new(0, 1_000_000_000); | |

loop { | |

let d = Duration::new(secs.sample(rng), nano_range.sample(rng)); | |

if d <= size { | |

break d; | |

} | |

} | |

} | |

}; | |

self.offset + d | |

} | |

} | |

#[cfg(test)] | |

mod tests { | |

use Rng; | |

use distributions::uniform::{Uniform, UniformSampler, UniformFloat, SampleUniform}; | |

#[should_panic] | |

#[test] | |

fn test_uniform_bad_limits_equal_int() { | |

Uniform::new(10, 10); | |

} | |

#[should_panic] | |

#[test] | |

fn test_uniform_bad_limits_equal_float() { | |

Uniform::new(10., 10.); | |

} | |

#[test] | |

fn test_uniform_good_limits_equal_int() { | |

let mut rng = ::test::rng(804); | |

let dist = Uniform::new_inclusive(10, 10); | |

for _ in 0..20 { | |

assert_eq!(rng.sample(dist), 10); | |

} | |

} | |

#[test] | |

fn test_uniform_good_limits_equal_float() { | |

let mut rng = ::test::rng(805); | |

let dist = Uniform::new_inclusive(10., 10.); | |

for _ in 0..20 { | |

assert_eq!(rng.sample(dist), 10.); | |

} | |

} | |

#[should_panic] | |

#[test] | |

fn test_uniform_bad_limits_flipped_int() { | |

Uniform::new(10, 5); | |

} | |

#[should_panic] | |

#[test] | |

fn test_uniform_bad_limits_flipped_float() { | |

Uniform::new(10., 5.); | |

} | |

#[test] | |

fn test_integers() { | |

let mut rng = ::test::rng(251); | |

macro_rules! t { | |

($($ty:ident),*) => {{ | |

$( | |

let v: &[($ty, $ty)] = &[(0, 10), | |

(10, 127), | |

(::core::$ty::MIN, ::core::$ty::MAX)]; | |

for &(low, high) in v.iter() { | |

let my_uniform = Uniform::new(low, high); | |

for _ in 0..1000 { | |

let v: $ty = rng.sample(my_uniform); | |

assert!(low <= v && v < high); | |

} | |

let my_uniform = Uniform::new_inclusive(low, high); | |

for _ in 0..1000 { | |

let v: $ty = rng.sample(my_uniform); | |

assert!(low <= v && v <= high); | |

} | |

for _ in 0..1000 { | |

let v: $ty = rng.gen_range(low, high); | |

assert!(low <= v && v < high); | |

} | |

} | |

)* | |

}} | |

} | |

t!(i8, i16, i32, i64, isize, | |

u8, u16, u32, u64, usize); | |

#[cfg(feature = "i128_support")] | |

t!(i128, u128) | |

} | |

#[test] | |

fn test_floats() { | |

let mut rng = ::test::rng(252); | |

macro_rules! t { | |

($($ty:ty),*) => {{ | |

$( | |

let v: &[($ty, $ty)] = &[(0.0, 100.0), | |

(-1e35, -1e25), | |

(1e-35, 1e-25), | |

(-1e35, 1e35)]; | |

for &(low, high) in v.iter() { | |

let my_uniform = Uniform::new(low, high); | |

for _ in 0..1000 { | |

let v: $ty = rng.sample(my_uniform); | |

assert!(low <= v && v < high); | |

} | |

} | |

)* | |

}} | |

} | |

t!(f32, f64) | |

} | |

#[test] | |

#[cfg(feature = "std")] | |

fn test_durations() { | |

use std::time::Duration; | |

let mut rng = ::test::rng(253); | |

let v = &[(Duration::new(10, 50000), Duration::new(100, 1234)), | |

(Duration::new(0, 100), Duration::new(1, 50)), | |

(Duration::new(0, 0), Duration::new(u64::max_value(), 999_999_999))]; | |

for &(low, high) in v.iter() { | |

let my_uniform = Uniform::new(low, high); | |

for _ in 0..1000 { | |

let v = rng.sample(my_uniform); | |

assert!(low <= v && v < high); | |

} | |

} | |

} | |

#[test] | |

fn test_custom_uniform() { | |

#[derive(Clone, Copy, PartialEq, PartialOrd)] | |

struct MyF32 { | |

x: f32, | |

} | |

#[derive(Clone, Copy, Debug)] | |

struct UniformMyF32 { | |

inner: UniformFloat<f32>, | |

} | |

impl UniformSampler for UniformMyF32 { | |

type X = MyF32; | |

fn new(low: Self::X, high: Self::X) -> Self { | |

UniformMyF32 { | |

inner: UniformFloat::<f32>::new(low.x, high.x), | |

} | |

} | |

fn new_inclusive(low: Self::X, high: Self::X) -> Self { | |

UniformSampler::new(low, high) | |

} | |

fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Self::X { | |

MyF32 { x: self.inner.sample(rng) } | |

} | |

} | |

impl SampleUniform for MyF32 { | |

type Sampler = UniformMyF32; | |

} | |

let (low, high) = (MyF32{ x: 17.0f32 }, MyF32{ x: 22.0f32 }); | |

let uniform = Uniform::new(low, high); | |

let mut rng = ::test::rng(804); | |

for _ in 0..100 { | |

let x: MyF32 = rng.sample(uniform); | |

assert!(low <= x && x < high); | |

} | |

} | |

#[test] | |

fn test_uniform_from_std_range() { | |

let r = Uniform::from(2u32..7); | |

assert_eq!(r.inner.low, 2); | |

assert_eq!(r.inner.range, 5); | |

let r = Uniform::from(2.0f64..7.0); | |

assert_eq!(r.inner.offset, -3.0); | |

assert_eq!(r.inner.scale, 5.0); | |

} | |

} |