| 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 | //! A distribution uniformly sampling numbers within a given range. |
| 11 | //! |
| 12 | //! [`Uniform`] is the standard distribution to sample uniformly from a range; |
| 13 | //! e.g. `Uniform::new_inclusive(1, 6).unwrap()` can sample integers from 1 to 6, like a |
| 14 | //! standard die. [`Rng::random_range`] is implemented over [`Uniform`]. |
| 15 | //! |
| 16 | //! # Example usage |
| 17 | //! |
| 18 | //! ``` |
| 19 | //! use rand::Rng; |
| 20 | //! use rand::distr::Uniform; |
| 21 | //! |
| 22 | //! let mut rng = rand::rng(); |
| 23 | //! let side = Uniform::new(-10.0, 10.0).unwrap(); |
| 24 | //! |
| 25 | //! // sample between 1 and 10 points |
| 26 | //! for _ in 0..rng.random_range(1..=10) { |
| 27 | //! // sample a point from the square with sides -10 - 10 in two dimensions |
| 28 | //! let (x, y) = (rng.sample(side), rng.sample(side)); |
| 29 | //! println!("Point: {}, {}" , x, y); |
| 30 | //! } |
| 31 | //! ``` |
| 32 | //! |
| 33 | //! # Extending `Uniform` to support a custom type |
| 34 | //! |
| 35 | //! To extend [`Uniform`] to support your own types, write a back-end which |
| 36 | //! implements the [`UniformSampler`] trait, then implement the [`SampleUniform`] |
| 37 | //! helper trait to "register" your back-end. See the `MyF32` example below. |
| 38 | //! |
| 39 | //! At a minimum, the back-end needs to store any parameters needed for sampling |
| 40 | //! (e.g. the target range) and implement `new`, `new_inclusive` and `sample`. |
| 41 | //! Those methods should include an assertion to check the range is valid (i.e. |
| 42 | //! `low < high`). The example below merely wraps another back-end. |
| 43 | //! |
| 44 | //! The `new`, `new_inclusive`, `sample_single` and `sample_single_inclusive` |
| 45 | //! functions use arguments of |
| 46 | //! type `SampleBorrow<X>` to support passing in values by reference or |
| 47 | //! by value. In the implementation of these functions, you can choose to |
| 48 | //! simply use the reference returned by [`SampleBorrow::borrow`], or you can choose |
| 49 | //! to copy or clone the value, whatever is appropriate for your type. |
| 50 | //! |
| 51 | //! ``` |
| 52 | //! use rand::prelude::*; |
| 53 | //! use rand::distr::uniform::{Uniform, SampleUniform, |
| 54 | //! UniformSampler, UniformFloat, SampleBorrow, Error}; |
| 55 | //! |
| 56 | //! struct MyF32(f32); |
| 57 | //! |
| 58 | //! #[derive(Clone, Copy, Debug)] |
| 59 | //! struct UniformMyF32(UniformFloat<f32>); |
| 60 | //! |
| 61 | //! impl UniformSampler for UniformMyF32 { |
| 62 | //! type X = MyF32; |
| 63 | //! |
| 64 | //! fn new<B1, B2>(low: B1, high: B2) -> Result<Self, Error> |
| 65 | //! where B1: SampleBorrow<Self::X> + Sized, |
| 66 | //! B2: SampleBorrow<Self::X> + Sized |
| 67 | //! { |
| 68 | //! UniformFloat::<f32>::new(low.borrow().0, high.borrow().0).map(UniformMyF32) |
| 69 | //! } |
| 70 | //! fn new_inclusive<B1, B2>(low: B1, high: B2) -> Result<Self, Error> |
| 71 | //! where B1: SampleBorrow<Self::X> + Sized, |
| 72 | //! B2: SampleBorrow<Self::X> + Sized |
| 73 | //! { |
| 74 | //! UniformFloat::<f32>::new_inclusive(low.borrow().0, high.borrow().0).map(UniformMyF32) |
| 75 | //! } |
| 76 | //! fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Self::X { |
| 77 | //! MyF32(self.0.sample(rng)) |
| 78 | //! } |
| 79 | //! } |
| 80 | //! |
| 81 | //! impl SampleUniform for MyF32 { |
| 82 | //! type Sampler = UniformMyF32; |
| 83 | //! } |
| 84 | //! |
| 85 | //! let (low, high) = (MyF32(17.0f32), MyF32(22.0f32)); |
| 86 | //! let uniform = Uniform::new(low, high).unwrap(); |
| 87 | //! let x = uniform.sample(&mut rand::rng()); |
| 88 | //! ``` |
| 89 | //! |
| 90 | //! [`SampleUniform`]: crate::distr::uniform::SampleUniform |
| 91 | //! [`UniformSampler`]: crate::distr::uniform::UniformSampler |
| 92 | //! [`UniformInt`]: crate::distr::uniform::UniformInt |
| 93 | //! [`UniformFloat`]: crate::distr::uniform::UniformFloat |
| 94 | //! [`UniformDuration`]: crate::distr::uniform::UniformDuration |
| 95 | //! [`SampleBorrow::borrow`]: crate::distr::uniform::SampleBorrow::borrow |
| 96 | |
| 97 | #[path = "uniform_float.rs" ] |
| 98 | mod float; |
| 99 | #[doc (inline)] |
| 100 | pub use float::UniformFloat; |
| 101 | |
| 102 | #[path = "uniform_int.rs" ] |
| 103 | mod int; |
| 104 | #[doc (inline)] |
| 105 | pub use int::{UniformInt, UniformUsize}; |
| 106 | |
| 107 | #[path = "uniform_other.rs" ] |
| 108 | mod other; |
| 109 | #[doc (inline)] |
| 110 | pub use other::{UniformChar, UniformDuration}; |
| 111 | |
| 112 | use core::fmt; |
| 113 | use core::ops::{Range, RangeInclusive, RangeTo, RangeToInclusive}; |
| 114 | |
| 115 | use crate::distr::Distribution; |
| 116 | use crate::{Rng, RngCore}; |
| 117 | |
| 118 | /// Error type returned from [`Uniform::new`] and `new_inclusive`. |
| 119 | #[derive (Clone, Copy, Debug, PartialEq, Eq)] |
| 120 | pub enum Error { |
| 121 | /// `low > high`, or equal in case of exclusive range. |
| 122 | EmptyRange, |
| 123 | /// Input or range `high - low` is non-finite. Not relevant to integer types. |
| 124 | NonFinite, |
| 125 | } |
| 126 | |
| 127 | impl fmt::Display for Error { |
| 128 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| 129 | f.write_str(data:match self { |
| 130 | Error::EmptyRange => "low > high (or equal if exclusive) in uniform distribution" , |
| 131 | Error::NonFinite => "Non-finite range in uniform distribution" , |
| 132 | }) |
| 133 | } |
| 134 | } |
| 135 | |
| 136 | #[cfg (feature = "std" )] |
| 137 | impl std::error::Error for Error {} |
| 138 | |
| 139 | #[cfg (feature = "serde" )] |
| 140 | use serde::{Deserialize, Serialize}; |
| 141 | |
| 142 | /// Sample values uniformly between two bounds. |
| 143 | /// |
| 144 | /// # Construction |
| 145 | /// |
| 146 | /// [`Uniform::new`] and [`Uniform::new_inclusive`] construct a uniform |
| 147 | /// distribution sampling from the given `low` and `high` limits. `Uniform` may |
| 148 | /// also be constructed via [`TryFrom`] as in `Uniform::try_from(1..=6).unwrap()`. |
| 149 | /// |
| 150 | /// Constructors may do extra work up front to allow faster sampling of multiple |
| 151 | /// values. Where only a single sample is required it is suggested to use |
| 152 | /// [`Rng::random_range`] or one of the `sample_single` methods instead. |
| 153 | /// |
| 154 | /// When sampling from a constant range, many calculations can happen at |
| 155 | /// compile-time and all methods should be fast; for floating-point ranges and |
| 156 | /// the full range of integer types, this should have comparable performance to |
| 157 | /// the [`StandardUniform`](super::StandardUniform) distribution. |
| 158 | /// |
| 159 | /// # Provided implementations |
| 160 | /// |
| 161 | /// - `char` ([`UniformChar`]): samples a range over the implementation for `u32` |
| 162 | /// - `f32`, `f64` ([`UniformFloat`]): samples approximately uniformly within a |
| 163 | /// range; bias may be present in the least-significant bit of the significand |
| 164 | /// and the limits of the input range may be sampled even when an open |
| 165 | /// (exclusive) range is used |
| 166 | /// - Integer types ([`UniformInt`]) may show a small bias relative to the |
| 167 | /// expected uniform distribution of output. In the worst case, bias affects |
| 168 | /// 1 in `2^n` samples where n is 56 (`i8` and `u8`), 48 (`i16` and `u16`), 96 |
| 169 | /// (`i32` and `u32`), 64 (`i64` and `u64`), 128 (`i128` and `u128`). |
| 170 | /// The `unbiased` feature flag fixes this bias. |
| 171 | /// - `usize` ([`UniformUsize`]) is handled specially, using the `u32` |
| 172 | /// implementation where possible to enable portable results across 32-bit and |
| 173 | /// 64-bit CPU architectures. |
| 174 | /// - `Duration` ([`UniformDuration`]): samples a range over the implementation |
| 175 | /// for `u32` or `u64` |
| 176 | /// - SIMD types (requires [`simd_support`] feature) like x86's [`__m128i`] |
| 177 | /// and `std::simd`'s [`u32x4`], [`f32x4`] and [`mask32x4`] types are |
| 178 | /// effectively arrays of integer or floating-point types. Each lane is |
| 179 | /// sampled independently from its own range, potentially with more efficient |
| 180 | /// random-bit-usage than would be achieved with sequential sampling. |
| 181 | /// |
| 182 | /// # Example |
| 183 | /// |
| 184 | /// ``` |
| 185 | /// use rand::distr::{Distribution, Uniform}; |
| 186 | /// |
| 187 | /// let between = Uniform::try_from(10..10000).unwrap(); |
| 188 | /// let mut rng = rand::rng(); |
| 189 | /// let mut sum = 0; |
| 190 | /// for _ in 0..1000 { |
| 191 | /// sum += between.sample(&mut rng); |
| 192 | /// } |
| 193 | /// println!("{}" , sum); |
| 194 | /// ``` |
| 195 | /// |
| 196 | /// For a single sample, [`Rng::random_range`] may be preferred: |
| 197 | /// |
| 198 | /// ``` |
| 199 | /// use rand::Rng; |
| 200 | /// |
| 201 | /// let mut rng = rand::rng(); |
| 202 | /// println!("{}" , rng.random_range(0..10)); |
| 203 | /// ``` |
| 204 | /// |
| 205 | /// [`new`]: Uniform::new |
| 206 | /// [`new_inclusive`]: Uniform::new_inclusive |
| 207 | /// [`Rng::random_range`]: Rng::random_range |
| 208 | /// [`__m128i`]: https://doc.rust-lang.org/core/arch/x86/struct.__m128i.html |
| 209 | /// [`u32x4`]: std::simd::u32x4 |
| 210 | /// [`f32x4`]: std::simd::f32x4 |
| 211 | /// [`mask32x4`]: std::simd::mask32x4 |
| 212 | /// [`simd_support`]: https://github.com/rust-random/rand#crate-features |
| 213 | #[derive (Clone, Copy, Debug, PartialEq, Eq)] |
| 214 | #[cfg_attr (feature = "serde" , derive(Serialize, Deserialize))] |
| 215 | #[cfg_attr (feature = "serde" , serde(bound(serialize = "X::Sampler: Serialize" )))] |
| 216 | #[cfg_attr ( |
| 217 | feature = "serde" , |
| 218 | serde(bound(deserialize = "X::Sampler: Deserialize<'de>" )) |
| 219 | )] |
| 220 | pub struct Uniform<X: SampleUniform>(X::Sampler); |
| 221 | |
| 222 | impl<X: SampleUniform> Uniform<X> { |
| 223 | /// Create a new `Uniform` instance, which samples uniformly from the half |
| 224 | /// open range `[low, high)` (excluding `high`). |
| 225 | /// |
| 226 | /// For discrete types (e.g. integers), samples will always be strictly less |
| 227 | /// than `high`. For (approximations of) continuous types (e.g. `f32`, `f64`), |
| 228 | /// samples may equal `high` due to loss of precision but may not be |
| 229 | /// greater than `high`. |
| 230 | /// |
| 231 | /// Fails if `low >= high`, or if `low`, `high` or the range `high - low` is |
| 232 | /// non-finite. In release mode, only the range is checked. |
| 233 | pub fn new<B1, B2>(low: B1, high: B2) -> Result<Uniform<X>, Error> |
| 234 | where |
| 235 | B1: SampleBorrow<X> + Sized, |
| 236 | B2: SampleBorrow<X> + Sized, |
| 237 | { |
| 238 | X::Sampler::new(low, high).map(Uniform) |
| 239 | } |
| 240 | |
| 241 | /// Create a new `Uniform` instance, which samples uniformly from the closed |
| 242 | /// range `[low, high]` (inclusive). |
| 243 | /// |
| 244 | /// Fails if `low > high`, or if `low`, `high` or the range `high - low` is |
| 245 | /// non-finite. In release mode, only the range is checked. |
| 246 | pub fn new_inclusive<B1, B2>(low: B1, high: B2) -> Result<Uniform<X>, Error> |
| 247 | where |
| 248 | B1: SampleBorrow<X> + Sized, |
| 249 | B2: SampleBorrow<X> + Sized, |
| 250 | { |
| 251 | X::Sampler::new_inclusive(low, high).map(Uniform) |
| 252 | } |
| 253 | } |
| 254 | |
| 255 | impl<X: SampleUniform> Distribution<X> for Uniform<X> { |
| 256 | fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> X { |
| 257 | self.0.sample(rng) |
| 258 | } |
| 259 | } |
| 260 | |
| 261 | /// Helper trait for creating objects using the correct implementation of |
| 262 | /// [`UniformSampler`] for the sampling type. |
| 263 | /// |
| 264 | /// See the [module documentation] on how to implement [`Uniform`] range |
| 265 | /// sampling for a custom type. |
| 266 | /// |
| 267 | /// [module documentation]: crate::distr::uniform |
| 268 | pub trait SampleUniform: Sized { |
| 269 | /// The `UniformSampler` implementation supporting type `X`. |
| 270 | type Sampler: UniformSampler<X = Self>; |
| 271 | } |
| 272 | |
| 273 | /// Helper trait handling actual uniform sampling. |
| 274 | /// |
| 275 | /// See the [module documentation] on how to implement [`Uniform`] range |
| 276 | /// sampling for a custom type. |
| 277 | /// |
| 278 | /// Implementation of [`sample_single`] is optional, and is only useful when |
| 279 | /// the implementation can be faster than `Self::new(low, high).sample(rng)`. |
| 280 | /// |
| 281 | /// [module documentation]: crate::distr::uniform |
| 282 | /// [`sample_single`]: UniformSampler::sample_single |
| 283 | pub trait UniformSampler: Sized { |
| 284 | /// The type sampled by this implementation. |
| 285 | type X; |
| 286 | |
| 287 | /// Construct self, with inclusive lower bound and exclusive upper bound `[low, high)`. |
| 288 | /// |
| 289 | /// For discrete types (e.g. integers), samples will always be strictly less |
| 290 | /// than `high`. For (approximations of) continuous types (e.g. `f32`, `f64`), |
| 291 | /// samples may equal `high` due to loss of precision but may not be |
| 292 | /// greater than `high`. |
| 293 | /// |
| 294 | /// Usually users should not call this directly but prefer to use |
| 295 | /// [`Uniform::new`]. |
| 296 | fn new<B1, B2>(low: B1, high: B2) -> Result<Self, Error> |
| 297 | where |
| 298 | B1: SampleBorrow<Self::X> + Sized, |
| 299 | B2: SampleBorrow<Self::X> + Sized; |
| 300 | |
| 301 | /// Construct self, with inclusive bounds `[low, high]`. |
| 302 | /// |
| 303 | /// Usually users should not call this directly but prefer to use |
| 304 | /// [`Uniform::new_inclusive`]. |
| 305 | fn new_inclusive<B1, B2>(low: B1, high: B2) -> Result<Self, Error> |
| 306 | where |
| 307 | B1: SampleBorrow<Self::X> + Sized, |
| 308 | B2: SampleBorrow<Self::X> + Sized; |
| 309 | |
| 310 | /// Sample a value. |
| 311 | fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Self::X; |
| 312 | |
| 313 | /// Sample a single value uniformly from a range with inclusive lower bound |
| 314 | /// and exclusive upper bound `[low, high)`. |
| 315 | /// |
| 316 | /// For discrete types (e.g. integers), samples will always be strictly less |
| 317 | /// than `high`. For (approximations of) continuous types (e.g. `f32`, `f64`), |
| 318 | /// samples may equal `high` due to loss of precision but may not be |
| 319 | /// greater than `high`. |
| 320 | /// |
| 321 | /// By default this is implemented using |
| 322 | /// `UniformSampler::new(low, high).sample(rng)`. However, for some types |
| 323 | /// more optimal implementations for single usage may be provided via this |
| 324 | /// method (which is the case for integers and floats). |
| 325 | /// Results may not be identical. |
| 326 | /// |
| 327 | /// Note that to use this method in a generic context, the type needs to be |
| 328 | /// retrieved via `SampleUniform::Sampler` as follows: |
| 329 | /// ``` |
| 330 | /// use rand::distr::uniform::{SampleUniform, UniformSampler}; |
| 331 | /// # #[allow (unused)] |
| 332 | /// fn sample_from_range<T: SampleUniform>(lb: T, ub: T) -> T { |
| 333 | /// let mut rng = rand::rng(); |
| 334 | /// <T as SampleUniform>::Sampler::sample_single(lb, ub, &mut rng).unwrap() |
| 335 | /// } |
| 336 | /// ``` |
| 337 | fn sample_single<R: Rng + ?Sized, B1, B2>( |
| 338 | low: B1, |
| 339 | high: B2, |
| 340 | rng: &mut R, |
| 341 | ) -> Result<Self::X, Error> |
| 342 | where |
| 343 | B1: SampleBorrow<Self::X> + Sized, |
| 344 | B2: SampleBorrow<Self::X> + Sized, |
| 345 | { |
| 346 | let uniform: Self = UniformSampler::new(low, high)?; |
| 347 | Ok(uniform.sample(rng)) |
| 348 | } |
| 349 | |
| 350 | /// Sample a single value uniformly from a range with inclusive lower bound |
| 351 | /// and inclusive upper bound `[low, high]`. |
| 352 | /// |
| 353 | /// By default this is implemented using |
| 354 | /// `UniformSampler::new_inclusive(low, high).sample(rng)`. However, for |
| 355 | /// some types more optimal implementations for single usage may be provided |
| 356 | /// via this method. |
| 357 | /// Results may not be identical. |
| 358 | fn sample_single_inclusive<R: Rng + ?Sized, B1, B2>( |
| 359 | low: B1, |
| 360 | high: B2, |
| 361 | rng: &mut R, |
| 362 | ) -> Result<Self::X, Error> |
| 363 | where |
| 364 | B1: SampleBorrow<Self::X> + Sized, |
| 365 | B2: SampleBorrow<Self::X> + Sized, |
| 366 | { |
| 367 | let uniform: Self = UniformSampler::new_inclusive(low, high)?; |
| 368 | Ok(uniform.sample(rng)) |
| 369 | } |
| 370 | } |
| 371 | |
| 372 | impl<X: SampleUniform> TryFrom<Range<X>> for Uniform<X> { |
| 373 | type Error = Error; |
| 374 | |
| 375 | fn try_from(r: Range<X>) -> Result<Uniform<X>, Error> { |
| 376 | Uniform::new(low:r.start, high:r.end) |
| 377 | } |
| 378 | } |
| 379 | |
| 380 | impl<X: SampleUniform> TryFrom<RangeInclusive<X>> for Uniform<X> { |
| 381 | type Error = Error; |
| 382 | |
| 383 | fn try_from(r: ::core::ops::RangeInclusive<X>) -> Result<Uniform<X>, Error> { |
| 384 | Uniform::new_inclusive(low:r.start(), high:r.end()) |
| 385 | } |
| 386 | } |
| 387 | |
| 388 | /// Helper trait similar to [`Borrow`] but implemented |
| 389 | /// only for [`SampleUniform`] and references to [`SampleUniform`] |
| 390 | /// in order to resolve ambiguity issues. |
| 391 | /// |
| 392 | /// [`Borrow`]: std::borrow::Borrow |
| 393 | pub trait SampleBorrow<Borrowed> { |
| 394 | /// Immutably borrows from an owned value. See [`Borrow::borrow`] |
| 395 | /// |
| 396 | /// [`Borrow::borrow`]: std::borrow::Borrow::borrow |
| 397 | fn borrow(&self) -> &Borrowed; |
| 398 | } |
| 399 | impl<Borrowed> SampleBorrow<Borrowed> for Borrowed |
| 400 | where |
| 401 | Borrowed: SampleUniform, |
| 402 | { |
| 403 | #[inline (always)] |
| 404 | fn borrow(&self) -> &Borrowed { |
| 405 | self |
| 406 | } |
| 407 | } |
| 408 | impl<Borrowed> SampleBorrow<Borrowed> for &Borrowed |
| 409 | where |
| 410 | Borrowed: SampleUniform, |
| 411 | { |
| 412 | #[inline (always)] |
| 413 | fn borrow(&self) -> &Borrowed { |
| 414 | self |
| 415 | } |
| 416 | } |
| 417 | |
| 418 | /// Range that supports generating a single sample efficiently. |
| 419 | /// |
| 420 | /// Any type implementing this trait can be used to specify the sampled range |
| 421 | /// for `Rng::random_range`. |
| 422 | pub trait SampleRange<T> { |
| 423 | /// Generate a sample from the given range. |
| 424 | fn sample_single<R: RngCore + ?Sized>(self, rng: &mut R) -> Result<T, Error>; |
| 425 | |
| 426 | /// Check whether the range is empty. |
| 427 | fn is_empty(&self) -> bool; |
| 428 | } |
| 429 | |
| 430 | impl<T: SampleUniform + PartialOrd> SampleRange<T> for Range<T> { |
| 431 | #[inline ] |
| 432 | fn sample_single<R: RngCore + ?Sized>(self, rng: &mut R) -> Result<T, Error> { |
| 433 | T::Sampler::sample_single(self.start, self.end, rng) |
| 434 | } |
| 435 | |
| 436 | #[inline ] |
| 437 | fn is_empty(&self) -> bool { |
| 438 | !(self.start < self.end) |
| 439 | } |
| 440 | } |
| 441 | |
| 442 | impl<T: SampleUniform + PartialOrd> SampleRange<T> for RangeInclusive<T> { |
| 443 | #[inline ] |
| 444 | fn sample_single<R: RngCore + ?Sized>(self, rng: &mut R) -> Result<T, Error> { |
| 445 | T::Sampler::sample_single_inclusive(self.start(), self.end(), rng) |
| 446 | } |
| 447 | |
| 448 | #[inline ] |
| 449 | fn is_empty(&self) -> bool { |
| 450 | !(self.start() <= self.end()) |
| 451 | } |
| 452 | } |
| 453 | |
| 454 | macro_rules! impl_sample_range_u { |
| 455 | ($t:ty) => { |
| 456 | impl SampleRange<$t> for RangeTo<$t> { |
| 457 | #[inline] |
| 458 | fn sample_single<R: RngCore + ?Sized>(self, rng: &mut R) -> Result<$t, Error> { |
| 459 | <$t as SampleUniform>::Sampler::sample_single(0, self.end, rng) |
| 460 | } |
| 461 | |
| 462 | #[inline] |
| 463 | fn is_empty(&self) -> bool { |
| 464 | 0 == self.end |
| 465 | } |
| 466 | } |
| 467 | |
| 468 | impl SampleRange<$t> for RangeToInclusive<$t> { |
| 469 | #[inline] |
| 470 | fn sample_single<R: RngCore + ?Sized>(self, rng: &mut R) -> Result<$t, Error> { |
| 471 | <$t as SampleUniform>::Sampler::sample_single_inclusive(0, self.end, rng) |
| 472 | } |
| 473 | |
| 474 | #[inline] |
| 475 | fn is_empty(&self) -> bool { |
| 476 | false |
| 477 | } |
| 478 | } |
| 479 | }; |
| 480 | } |
| 481 | |
| 482 | impl_sample_range_u!(u8); |
| 483 | impl_sample_range_u!(u16); |
| 484 | impl_sample_range_u!(u32); |
| 485 | impl_sample_range_u!(u64); |
| 486 | impl_sample_range_u!(u128); |
| 487 | impl_sample_range_u!(usize); |
| 488 | |
| 489 | #[cfg (test)] |
| 490 | mod tests { |
| 491 | use super::*; |
| 492 | use core::time::Duration; |
| 493 | |
| 494 | #[test ] |
| 495 | #[cfg (feature = "serde" )] |
| 496 | fn test_uniform_serialization() { |
| 497 | let unit_box: Uniform<i32> = Uniform::new(-1, 1).unwrap(); |
| 498 | let de_unit_box: Uniform<i32> = |
| 499 | bincode::deserialize(&bincode::serialize(&unit_box).unwrap()).unwrap(); |
| 500 | assert_eq!(unit_box.0, de_unit_box.0); |
| 501 | |
| 502 | let unit_box: Uniform<f32> = Uniform::new(-1., 1.).unwrap(); |
| 503 | let de_unit_box: Uniform<f32> = |
| 504 | bincode::deserialize(&bincode::serialize(&unit_box).unwrap()).unwrap(); |
| 505 | assert_eq!(unit_box.0, de_unit_box.0); |
| 506 | } |
| 507 | |
| 508 | #[test ] |
| 509 | fn test_custom_uniform() { |
| 510 | use crate::distr::uniform::{SampleBorrow, SampleUniform, UniformFloat, UniformSampler}; |
| 511 | #[derive (Clone, Copy, PartialEq, PartialOrd)] |
| 512 | struct MyF32 { |
| 513 | x: f32, |
| 514 | } |
| 515 | #[derive (Clone, Copy, Debug)] |
| 516 | struct UniformMyF32(UniformFloat<f32>); |
| 517 | impl UniformSampler for UniformMyF32 { |
| 518 | type X = MyF32; |
| 519 | |
| 520 | fn new<B1, B2>(low: B1, high: B2) -> Result<Self, Error> |
| 521 | where |
| 522 | B1: SampleBorrow<Self::X> + Sized, |
| 523 | B2: SampleBorrow<Self::X> + Sized, |
| 524 | { |
| 525 | UniformFloat::<f32>::new(low.borrow().x, high.borrow().x).map(UniformMyF32) |
| 526 | } |
| 527 | |
| 528 | fn new_inclusive<B1, B2>(low: B1, high: B2) -> Result<Self, Error> |
| 529 | where |
| 530 | B1: SampleBorrow<Self::X> + Sized, |
| 531 | B2: SampleBorrow<Self::X> + Sized, |
| 532 | { |
| 533 | UniformSampler::new(low, high) |
| 534 | } |
| 535 | |
| 536 | fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Self::X { |
| 537 | MyF32 { |
| 538 | x: self.0.sample(rng), |
| 539 | } |
| 540 | } |
| 541 | } |
| 542 | impl SampleUniform for MyF32 { |
| 543 | type Sampler = UniformMyF32; |
| 544 | } |
| 545 | |
| 546 | let (low, high) = (MyF32 { x: 17.0f32 }, MyF32 { x: 22.0f32 }); |
| 547 | let uniform = Uniform::new(low, high).unwrap(); |
| 548 | let mut rng = crate::test::rng(804); |
| 549 | for _ in 0..100 { |
| 550 | let x: MyF32 = rng.sample(uniform); |
| 551 | assert!(low <= x && x < high); |
| 552 | } |
| 553 | } |
| 554 | |
| 555 | #[test ] |
| 556 | fn value_stability() { |
| 557 | fn test_samples<T: SampleUniform + Copy + fmt::Debug + PartialEq>( |
| 558 | lb: T, |
| 559 | ub: T, |
| 560 | expected_single: &[T], |
| 561 | expected_multiple: &[T], |
| 562 | ) where |
| 563 | Uniform<T>: Distribution<T>, |
| 564 | { |
| 565 | let mut rng = crate::test::rng(897); |
| 566 | let mut buf = [lb; 3]; |
| 567 | |
| 568 | for x in &mut buf { |
| 569 | *x = T::Sampler::sample_single(lb, ub, &mut rng).unwrap(); |
| 570 | } |
| 571 | assert_eq!(&buf, expected_single); |
| 572 | |
| 573 | let distr = Uniform::new(lb, ub).unwrap(); |
| 574 | for x in &mut buf { |
| 575 | *x = rng.sample(&distr); |
| 576 | } |
| 577 | assert_eq!(&buf, expected_multiple); |
| 578 | } |
| 579 | |
| 580 | test_samples( |
| 581 | 0f32, |
| 582 | 1e-2f32, |
| 583 | &[0.0003070104, 0.0026630748, 0.00979833], |
| 584 | &[0.008194133, 0.00398172, 0.007428536], |
| 585 | ); |
| 586 | test_samples( |
| 587 | -1e10f64, |
| 588 | 1e10f64, |
| 589 | &[-4673848682.871551, 6388267422.932352, 4857075081.198343], |
| 590 | &[1173375212.1808167, 1917642852.109581, 2365076174.3153973], |
| 591 | ); |
| 592 | |
| 593 | test_samples( |
| 594 | Duration::new(2, 0), |
| 595 | Duration::new(4, 0), |
| 596 | &[ |
| 597 | Duration::new(2, 532615131), |
| 598 | Duration::new(3, 638826742), |
| 599 | Duration::new(3, 485707508), |
| 600 | ], |
| 601 | &[ |
| 602 | Duration::new(3, 117337521), |
| 603 | Duration::new(3, 191764285), |
| 604 | Duration::new(3, 236507617), |
| 605 | ], |
| 606 | ); |
| 607 | } |
| 608 | |
| 609 | #[test ] |
| 610 | fn uniform_distributions_can_be_compared() { |
| 611 | assert_eq!( |
| 612 | Uniform::new(1.0, 2.0).unwrap(), |
| 613 | Uniform::new(1.0, 2.0).unwrap() |
| 614 | ); |
| 615 | |
| 616 | // To cover UniformInt |
| 617 | assert_eq!( |
| 618 | Uniform::new(1_u32, 2_u32).unwrap(), |
| 619 | Uniform::new(1_u32, 2_u32).unwrap() |
| 620 | ); |
| 621 | } |
| 622 | } |
| 623 | |