Skip to main content

rand/distr/
uniform_int.rs

1// Copyright 2018-2020 Developers of the Rand project.
2// Copyright 2017 The Rust Project Developers.
3//
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.
9
10//! `UniformInt` implementation
11
12use 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/// The back-end implementing [`UniformSampler`] for integer types.
25///
26/// Unless you are implementing [`UniformSampler`] for your own type, this type
27/// should not be used directly, use [`Uniform`] instead.
28///
29/// # Implementation notes
30///
31/// For simplicity, we use the same generic struct `UniformInt<X>` for all
32/// integer types `X`. This gives us only one field type, `X`; to store unsigned
33/// values of this size, we take use the fact that these conversions are no-ops.
34///
35/// For a closed range, the number of possible numbers we should generate is
36/// `range = (high - low + 1)`. To avoid bias, we must ensure that the size of
37/// our sample space, `zone`, is a multiple of `range`; other values must be
38/// rejected (by replacing with a new random sample).
39///
40/// As a special case, we use `range = 0` to represent the full range of the
41/// result type (i.e. for `new_inclusive($ty::MIN, $ty::MAX)`).
42///
43/// The optimum `zone` is the largest product of `range` which fits in our
44/// (unsigned) target type. We calculate this by calculating how many numbers we
45/// must reject: `reject = (MAX + 1) % range = (MAX - range + 1) % range`. Any (large)
46/// product of `range` will suffice, thus in `sample_single` we multiply by a
47/// power of 2 via bit-shifting (faster but may cause more rejections).
48///
49/// The smallest integer PRNGs generate is `u32`. For 8- and 16-bit outputs we
50/// use `u32` for our `zone` and samples (because it's not slower and because
51/// it reduces the chance of having to reject a sample). In this case we cannot
52/// store `zone` in the target type since it is too large, however we know
53/// `ints_to_reject < range <= $uty::MAX`.
54///
55/// An alternative to using a modulus is widening multiply: After a widening
56/// multiply by `range`, the result is in the high word. Then comparing the low
57/// word against `zone` makes sure our distribution is uniform.
58///
59/// # Bias
60///
61/// Unless the `unbiased` feature flag is used, outputs may have a small bias.
62/// In the worst case, bias affects 1 in `2^n` samples where n is
63/// 56 (`i8` and `u8`), 48 (`i16` and `u16`), 96 (`i32` and `u32`), 64 (`i64`
64/// and `u64`), 128 (`i128` and `u128`).
65///
66/// [`Uniform`]: super::Uniform
67#[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, // effectively 2.pow(max(64, uty_bits)) % range
73}
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            // We play free and fast with unsigned vs signed here
83            // (when $ty is signed), but that's fine, since the
84            // contract of this macro is for $ty and $uty to be
85            // "bit-equal", so casting between them is a no-op.
86
87            type X = $ty;
88
89            #[inline] // if the range is constant, this helps LLVM to do the
90            // calculations at compile-time.
91            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] // if the range is constant, this helps LLVM to do the
105            // calculations at compile-time.
106            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,           // type: $uty
128                    thresh: thresh as $uty as $ty, // type: $sample_ty
129                })
130            }
131
132            /// Sample from distribution, Lemire's method, unbiased
133            #[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            /// Sample single value, Canon's method, biased
169            ///
170            /// In the worst case, bias affects 1 in `2^n` samples where n is
171            /// 56 (`i8`), 48 (`i16`), 96 (`i32`), 64 (`i64`), 128 (`i128`).
172            #[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                    // Range is MAX+1 (unrepresentable), so we need a special case
191                    return Ok(rng.random());
192                }
193
194                // generate a sample using a sensible integer type
195                let (mut result, lo_order) = rng.random::<$sample_ty>().wmul(range);
196
197                // if the sample is biased...
198                if lo_order > range.wrapping_neg() {
199                    // ...generate a new sample to reduce bias...
200                    let (new_hi_order, _) = (rng.random::<$sample_ty>()).wmul(range as $sample_ty);
201                    // ... incrementing result on overflow
202                    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            /// Sample single value, Canon's method, unbiased
210            #[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                    // Range is MAX+1 (unrepresentable), so we need a special case
229                    return Ok(rng.random());
230                }
231
232                let (mut result, mut lo) = rng.random::<$sample_ty>().wmul(range);
233
234                // In contrast to the biased sampler, we use a loop:
235                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                            // Anything less than MAX: last term is 0
240                            break;
241                        }
242                        None => {
243                            // Overflow: last term is 1
244                            result += 1;
245                            break;
246                        }
247                        _ => {
248                            // Unlikely case: must check next sample
249                            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 })
    }
    /// Sample from distribution, Lemire's method, unbiased
    #[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)
    }
    /// Sample single value, Canon's method, biased
    ///
    /// In the worst case, bias affects 1 in `2^n` samples where n is
    /// 56 (`i8`), 48 (`i16`), 96 (`i32`), 64 (`i64`), 128 (`i128`).
    #[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,
            })
    }
    /// Sample from distribution, Lemire's method, unbiased
    #[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)
    }
    /// Sample single value, Canon's method, biased
    ///
    /// In the worst case, bias affects 1 in `2^n` samples where n is
    /// 56 (`i8`), 48 (`i16`), 96 (`i32`), 64 (`i64`), 128 (`i128`).
    #[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,
            })
    }
    /// Sample from distribution, Lemire's method, unbiased
    #[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)
    }
    /// Sample single value, Canon's method, biased
    ///
    /// In the worst case, bias affects 1 in `2^n` samples where n is
    /// 56 (`i8`), 48 (`i16`), 96 (`i32`), 64 (`i64`), 128 (`i128`).
    #[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,
            })
    }
    /// Sample from distribution, Lemire's method, unbiased
    #[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)
    }
    /// Sample single value, Canon's method, biased
    ///
    /// In the worst case, bias affects 1 in `2^n` samples where n is
    /// 56 (`i8`), 48 (`i16`), 96 (`i32`), 64 (`i64`), 128 (`i128`).
    #[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,
            })
    }
    /// Sample from distribution, Lemire's method, unbiased
    #[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)
    }
    /// Sample single value, Canon's method, biased
    ///
    /// In the worst case, bias affects 1 in `2^n` samples where n is
    /// 56 (`i8`), 48 (`i16`), 96 (`i32`), 64 (`i64`), 128 (`i128`).
    #[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 })
    }
    /// Sample from distribution, Lemire's method, unbiased
    #[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)
    }
    /// Sample single value, Canon's method, biased
    ///
    /// In the worst case, bias affects 1 in `2^n` samples where n is
    /// 56 (`i8`), 48 (`i16`), 96 (`i32`), 64 (`i64`), 128 (`i128`).
    #[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,
            })
    }
    /// Sample from distribution, Lemire's method, unbiased
    #[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)
    }
    /// Sample single value, Canon's method, biased
    ///
    /// In the worst case, bias affects 1 in `2^n` samples where n is
    /// 56 (`i8`), 48 (`i16`), 96 (`i32`), 64 (`i64`), 128 (`i128`).
    #[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,
            })
    }
    /// Sample from distribution, Lemire's method, unbiased
    #[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)
    }
    /// Sample single value, Canon's method, biased
    ///
    /// In the worst case, bias affects 1 in `2^n` samples where n is
    /// 56 (`i8`), 48 (`i16`), 96 (`i32`), 64 (`i64`), 128 (`i128`).
    #[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,
            })
    }
    /// Sample from distribution, Lemire's method, unbiased
    #[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)
    }
    /// Sample single value, Canon's method, biased
    ///
    /// In the worst case, bias affects 1 in `2^n` samples where n is
    /// 56 (`i8`), 48 (`i16`), 96 (`i32`), 64 (`i64`), 128 (`i128`).
    #[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,
            })
    }
    /// Sample from distribution, Lemire's method, unbiased
    #[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)
    }
    /// Sample single value, Canon's method, biased
    ///
    /// In the worst case, bias affects 1 in `2^n` samples where n is
    /// 56 (`i8`), 48 (`i16`), 96 (`i32`), 64 (`i64`), 128 (`i128`).
    #[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        // The "pick the largest zone that can fit in an `u32`" optimization
276        // is less useful here. Multiple lanes complicate things, we don't
277        // know the PRNG's minimal output size, and casting to a larger vector
278        // is generally a bad idea for SIMD performance. The user can still
279        // implement it manually.
280
281        #[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] // if the range is constant, this helps LLVM to do the
301                      // calculations at compile-time.
302            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] // if the range is constant, this helps LLVM to do the
315                      // calculations at compile-time.
316            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                // NOTE: all `Simd` operations are inherently wrapping,
327                //       see https://doc.rust-lang.org/std/simd/struct.Simd.html
328                let range: Simd<$unsigned, LANES> = ((high - low) + Simd::splat(1)).cast();
329
330                // We must avoid divide-by-zero by using 0 % 1 == 0.
331                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                    // These are really $unsigned values, but store as $ty:
338                    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                // This might seem very slow, generating a whole new
348                // SIMD vector for every sample rejection. For most uses
349                // though, the chance of rejection is small and provides good
350                // general performance. With multiple lanes, that chance is
351                // multiplied. To mitigate this, we replace only the lanes of
352                // the vector which fail, iteratively reducing the chance of
353                // rejection. The replacement method does however add a little
354                // overhead. Benchmarking or calculating probabilities might
355                // reveal contexts where this replacement method is slower.
356                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                        // wrapping addition
363                        let result = self.low + hi;
364                        // `select` here compiles to a blend operation
365                        // When `range.eq(0).none()` the compare and blend
366                        // operations are avoided.
367                        let v: Simd<$ty, LANES> = v.cast();
368                        return range.simd_gt(Simd::splat(0)).select(result, v);
369                    }
370                    // Replace only the failing lanes
371                    v = mask.select(v, rng.random());
372                }
373            }
374        }
375    };
376
377    // bulk implementation
378    ($(($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/// The back-end implementing [`UniformSampler`] for `usize`.
390///
391/// # Implementation notes
392///
393/// Sampling a `usize` value is usually used in relation to the length of an
394/// array or other memory structure, thus it is reasonable to assume that the
395/// vast majority of use-cases will have a maximum size under [`u32::MAX`].
396/// In part to optimise for this use-case, but mostly to ensure that results
397/// are portable across 32-bit and 64-bit architectures (as far as is possible),
398/// this implementation will use 32-bit sampling when possible.
399#[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// To be able to deserialize on 32-bit we need to replace this with a custom
403// implementation of the Deserialize trait, to be able to:
404// - panic when `mode64` is `true` on 32-bit,
405// - assign the default value to `mode64` when it's missing on 64-bit,
406// - panic when the `usize` fields are greater than `u32::MAX` on 32-bit.
407#[cfg_attr(
408    all(feature = "serde", target_pointer_width = "64"),
409    derive(Deserialize)
410)]
411pub struct UniformUsize {
412    /// The lowest possible value.
413    low: usize,
414    /// The number of possible values. `0` has a special meaning: all.
415    range: usize,
416    /// Threshold used when sampling to obtain a uniform distribution.
417    thresh: usize,
418    /// Whether the largest possible value is greater than `u32::MAX`.
419    #[cfg(target_pointer_width = "64")]
420    // Handle missing field when deserializing on 64-bit an object serialized
421    // on 32-bit. Can be removed when switching to a custom deserializer.
422    #[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] // if the range is constant, this helps LLVM to do the
436    // calculations at compile-time.
437    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] // if the range is constant, this helps LLVM to do the
452    // calculations at compile-time.
453    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)] // Miri is too slow
611    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            // scalar bulk
653            ($($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            // simd bulk
663            ($($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    // This could be run also on 32-bit when deserialization is implemented.
864    #[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}