1 // Copyright 2018 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)` can sample integers from 1 to 6, like a 14 //! standard die. [`Rng::gen_range`] supports any type supported by 15 //! [`Uniform`]. 16 //! 17 //! This distribution is provided with support for several primitive types 18 //! (all integer and floating-point types) as well as [`std::time::Duration`], 19 //! and supports extension to user-defined types via a type-specific *back-end* 20 //! implementation. 21 //! 22 //! The types [`UniformInt`], [`UniformFloat`] and [`UniformDuration`] are the 23 //! back-ends supporting sampling from primitive integer and floating-point 24 //! ranges as well as from [`std::time::Duration`]; these types do not normally 25 //! need to be used directly (unless implementing a derived back-end). 26 //! 27 //! # Example usage 28 //! 29 //! ``` 30 //! use rand::{Rng, thread_rng}; 31 //! use rand::distributions::Uniform; 32 //! 33 //! let mut rng = thread_rng(); 34 //! let side = Uniform::new(-10.0, 10.0); 35 //! 36 //! // sample between 1 and 10 points 37 //! for _ in 0..rng.gen_range(1, 11) { 38 //! // sample a point from the square with sides -10 - 10 in two dimensions 39 //! let (x, y) = (rng.sample(side), rng.sample(side)); 40 //! println!("Point: {}, {}", x, y); 41 //! } 42 //! ``` 43 //! 44 //! # Extending `Uniform` to support a custom type 45 //! 46 //! To extend [`Uniform`] to support your own types, write a back-end which 47 //! implements the [`UniformSampler`] trait, then implement the [`SampleUniform`] 48 //! helper trait to "register" your back-end. See the `MyF32` example below. 49 //! 50 //! At a minimum, the back-end needs to store any parameters needed for sampling 51 //! (e.g. the target range) and implement `new`, `new_inclusive` and `sample`. 52 //! Those methods should include an assert to check the range is valid (i.e. 53 //! `low < high`). The example below merely wraps another back-end. 54 //! 55 //! The `new`, `new_inclusive` and `sample_single` functions use arguments of 56 //! type SampleBorrow<X> in order to support passing in values by reference or 57 //! by value. In the implementation of these functions, you can choose to 58 //! simply use the reference returned by [`SampleBorrow::borrow`], or you can choose 59 //! to copy or clone the value, whatever is appropriate for your type. 60 //! 61 //! ``` 62 //! use rand::prelude::*; 63 //! use rand::distributions::uniform::{Uniform, SampleUniform, 64 //! UniformSampler, UniformFloat, SampleBorrow}; 65 //! 66 //! struct MyF32(f32); 67 //! 68 //! #[derive(Clone, Copy, Debug)] 69 //! struct UniformMyF32(UniformFloat<f32>); 70 //! 71 //! impl UniformSampler for UniformMyF32 { 72 //! type X = MyF32; 73 //! fn new<B1, B2>(low: B1, high: B2) -> Self 74 //! where B1: SampleBorrow<Self::X> + Sized, 75 //! B2: SampleBorrow<Self::X> + Sized 76 //! { 77 //! UniformMyF32(UniformFloat::<f32>::new(low.borrow().0, high.borrow().0)) 78 //! } 79 //! fn new_inclusive<B1, B2>(low: B1, high: B2) -> Self 80 //! where B1: SampleBorrow<Self::X> + Sized, 81 //! B2: SampleBorrow<Self::X> + Sized 82 //! { 83 //! UniformSampler::new(low, high) 84 //! } 85 //! fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Self::X { 86 //! MyF32(self.0.sample(rng)) 87 //! } 88 //! } 89 //! 90 //! impl SampleUniform for MyF32 { 91 //! type Sampler = UniformMyF32; 92 //! } 93 //! 94 //! let (low, high) = (MyF32(17.0f32), MyF32(22.0f32)); 95 //! let uniform = Uniform::new(low, high); 96 //! let x = uniform.sample(&mut thread_rng()); 97 //! ``` 98 //! 99 //! [`SampleUniform`]: crate::distributions::uniform::SampleUniform 100 //! [`UniformSampler`]: crate::distributions::uniform::UniformSampler 101 //! [`UniformInt`]: crate::distributions::uniform::UniformInt 102 //! [`UniformFloat`]: crate::distributions::uniform::UniformFloat 103 //! [`UniformDuration`]: crate::distributions::uniform::UniformDuration 104 //! [`SampleBorrow::borrow`]: crate::distributions::uniform::SampleBorrow::borrow 105 106 #[cfg(not(feature = "std"))] use core::time::Duration; 107 #[cfg(feature = "std")] use std::time::Duration; 108 109 use crate::distributions::float::IntoFloat; 110 use crate::distributions::utils::{BoolAsSIMD, FloatAsSIMD, FloatSIMDUtils, WideningMultiply}; 111 use crate::distributions::Distribution; 112 use crate::Rng; 113 114 #[cfg(not(feature = "std"))] 115 #[allow(unused_imports)] // rustc doesn't detect that this is actually used 116 use crate::distributions::utils::Float; 117 118 119 #[cfg(feature = "simd_support")] use packed_simd::*; 120 121 /// Sample values uniformly between two bounds. 122 /// 123 /// [`Uniform::new`] and [`Uniform::new_inclusive`] construct a uniform 124 /// distribution sampling from the given range; these functions may do extra 125 /// work up front to make sampling of multiple values faster. 126 /// 127 /// When sampling from a constant range, many calculations can happen at 128 /// compile-time and all methods should be fast; for floating-point ranges and 129 /// the full range of integer types this should have comparable performance to 130 /// the `Standard` distribution. 131 /// 132 /// Steps are taken to avoid bias which might be present in naive 133 /// implementations; for example `rng.gen::<u8>() % 170` samples from the range 134 /// `[0, 169]` but is twice as likely to select numbers less than 85 than other 135 /// values. Further, the implementations here give more weight to the high-bits 136 /// generated by the RNG than the low bits, since with some RNGs the low-bits 137 /// are of lower quality than the high bits. 138 /// 139 /// Implementations must sample in `[low, high)` range for 140 /// `Uniform::new(low, high)`, i.e., excluding `high`. In particular care must 141 /// be taken to ensure that rounding never results values `< low` or `>= high`. 142 /// 143 /// # Example 144 /// 145 /// ``` 146 /// use rand::distributions::{Distribution, Uniform}; 147 /// 148 /// fn main() { 149 /// let between = Uniform::from(10..10000); 150 /// let mut rng = rand::thread_rng(); 151 /// let mut sum = 0; 152 /// for _ in 0..1000 { 153 /// sum += between.sample(&mut rng); 154 /// } 155 /// println!("{}", sum); 156 /// } 157 /// ``` 158 /// 159 /// [`new`]: Uniform::new 160 /// [`new_inclusive`]: Uniform::new_inclusive 161 #[derive(Clone, Copy, Debug)] 162 pub struct Uniform<X: SampleUniform>(X::Sampler); 163 164 impl<X: SampleUniform> Uniform<X> { 165 /// Create a new `Uniform` instance which samples uniformly from the half 166 /// open range `[low, high)` (excluding `high`). Panics if `low >= high`. new<B1, B2>(low: B1, high: B2) -> Uniform<X> where B1: SampleBorrow<X> + Sized, B2: SampleBorrow<X> + Sized,167 pub fn new<B1, B2>(low: B1, high: B2) -> Uniform<X> 168 where 169 B1: SampleBorrow<X> + Sized, 170 B2: SampleBorrow<X> + Sized, 171 { 172 Uniform(X::Sampler::new(low, high)) 173 } 174 175 /// Create a new `Uniform` instance which samples uniformly from the closed 176 /// range `[low, high]` (inclusive). Panics if `low > high`. new_inclusive<B1, B2>(low: B1, high: B2) -> Uniform<X> where B1: SampleBorrow<X> + Sized, B2: SampleBorrow<X> + Sized,177 pub fn new_inclusive<B1, B2>(low: B1, high: B2) -> Uniform<X> 178 where 179 B1: SampleBorrow<X> + Sized, 180 B2: SampleBorrow<X> + Sized, 181 { 182 Uniform(X::Sampler::new_inclusive(low, high)) 183 } 184 } 185 186 impl<X: SampleUniform> Distribution<X> for Uniform<X> { sample<R: Rng + ?Sized>(&self, rng: &mut R) -> X187 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> X { 188 self.0.sample(rng) 189 } 190 } 191 192 /// Helper trait for creating objects using the correct implementation of 193 /// [`UniformSampler`] for the sampling type. 194 /// 195 /// See the [module documentation] on how to implement [`Uniform`] range 196 /// sampling for a custom type. 197 /// 198 /// [module documentation]: crate::distributions::uniform 199 pub trait SampleUniform: Sized { 200 /// The `UniformSampler` implementation supporting type `X`. 201 type Sampler: UniformSampler<X = Self>; 202 } 203 204 /// Helper trait handling actual uniform sampling. 205 /// 206 /// See the [module documentation] on how to implement [`Uniform`] range 207 /// sampling for a custom type. 208 /// 209 /// Implementation of [`sample_single`] is optional, and is only useful when 210 /// the implementation can be faster than `Self::new(low, high).sample(rng)`. 211 /// 212 /// [module documentation]: crate::distributions::uniform 213 /// [`sample_single`]: UniformSampler::sample_single 214 pub trait UniformSampler: Sized { 215 /// The type sampled by this implementation. 216 type X; 217 218 /// Construct self, with inclusive lower bound and exclusive upper bound 219 /// `[low, high)`. 220 /// 221 /// Usually users should not call this directly but instead use 222 /// `Uniform::new`, which asserts that `low < high` before calling this. new<B1, B2>(low: B1, high: B2) -> Self where B1: SampleBorrow<Self::X> + Sized, B2: SampleBorrow<Self::X> + Sized223 fn new<B1, B2>(low: B1, high: B2) -> Self 224 where 225 B1: SampleBorrow<Self::X> + Sized, 226 B2: SampleBorrow<Self::X> + Sized; 227 228 /// Construct self, with inclusive bounds `[low, high]`. 229 /// 230 /// Usually users should not call this directly but instead use 231 /// `Uniform::new_inclusive`, which asserts that `low <= high` before 232 /// calling this. new_inclusive<B1, B2>(low: B1, high: B2) -> Self where B1: SampleBorrow<Self::X> + Sized, B2: SampleBorrow<Self::X> + Sized233 fn new_inclusive<B1, B2>(low: B1, high: B2) -> Self 234 where 235 B1: SampleBorrow<Self::X> + Sized, 236 B2: SampleBorrow<Self::X> + Sized; 237 238 /// Sample a value. sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Self::X239 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Self::X; 240 241 /// Sample a single value uniformly from a range with inclusive lower bound 242 /// and exclusive upper bound `[low, high)`. 243 /// 244 /// By default this is implemented using 245 /// `UniformSampler::new(low, high).sample(rng)`. However, for some types 246 /// more optimal implementations for single usage may be provided via this 247 /// method (which is the case for integers and floats). 248 /// Results may not be identical. 249 /// 250 /// Note that to use this method in a generic context, the type needs to be 251 /// retrieved via `SampleUniform::Sampler` as follows: 252 /// ``` 253 /// use rand::{thread_rng, distributions::uniform::{SampleUniform, UniformSampler}}; 254 /// # #[allow(unused)] 255 /// fn sample_from_range<T: SampleUniform>(lb: T, ub: T) -> T { 256 /// let mut rng = thread_rng(); 257 /// <T as SampleUniform>::Sampler::sample_single(lb, ub, &mut rng) 258 /// } 259 /// ``` sample_single<R: Rng + ?Sized, B1, B2>(low: B1, high: B2, rng: &mut R) -> Self::X where B1: SampleBorrow<Self::X> + Sized, B2: SampleBorrow<Self::X> + Sized,260 fn sample_single<R: Rng + ?Sized, B1, B2>(low: B1, high: B2, rng: &mut R) -> Self::X 261 where 262 B1: SampleBorrow<Self::X> + Sized, 263 B2: SampleBorrow<Self::X> + Sized, 264 { 265 let uniform: Self = UniformSampler::new(low, high); 266 uniform.sample(rng) 267 } 268 } 269 270 impl<X: SampleUniform> From<::core::ops::Range<X>> for Uniform<X> { from(r: ::core::ops::Range<X>) -> Uniform<X>271 fn from(r: ::core::ops::Range<X>) -> Uniform<X> { 272 Uniform::new(r.start, r.end) 273 } 274 } 275 276 impl<X: SampleUniform> From<::core::ops::RangeInclusive<X>> for Uniform<X> { from(r: ::core::ops::RangeInclusive<X>) -> Uniform<X>277 fn from(r: ::core::ops::RangeInclusive<X>) -> Uniform<X> { 278 Uniform::new_inclusive(r.start(), r.end()) 279 } 280 } 281 282 /// Helper trait similar to [`Borrow`] but implemented 283 /// only for SampleUniform and references to SampleUniform in 284 /// order to resolve ambiguity issues. 285 /// 286 /// [`Borrow`]: std::borrow::Borrow 287 pub trait SampleBorrow<Borrowed> { 288 /// Immutably borrows from an owned value. See [`Borrow::borrow`] 289 /// 290 /// [`Borrow::borrow`]: std::borrow::Borrow::borrow borrow(&self) -> &Borrowed291 fn borrow(&self) -> &Borrowed; 292 } 293 impl<Borrowed> SampleBorrow<Borrowed> for Borrowed 294 where Borrowed: SampleUniform 295 { 296 #[inline(always)] borrow(&self) -> &Borrowed297 fn borrow(&self) -> &Borrowed { 298 self 299 } 300 } 301 impl<'a, Borrowed> SampleBorrow<Borrowed> for &'a Borrowed 302 where Borrowed: SampleUniform 303 { 304 #[inline(always)] borrow(&self) -> &Borrowed305 fn borrow(&self) -> &Borrowed { 306 *self 307 } 308 } 309 310 //////////////////////////////////////////////////////////////////////////////// 311 312 // What follows are all back-ends. 313 314 315 /// The back-end implementing [`UniformSampler`] for integer types. 316 /// 317 /// Unless you are implementing [`UniformSampler`] for your own type, this type 318 /// should not be used directly, use [`Uniform`] instead. 319 /// 320 /// # Implementation notes 321 /// 322 /// For simplicity, we use the same generic struct `UniformInt<X>` for all 323 /// integer types `X`. This gives us only one field type, `X`; to store unsigned 324 /// values of this size, we take use the fact that these conversions are no-ops. 325 /// 326 /// For a closed range, the number of possible numbers we should generate is 327 /// `range = (high - low + 1)`. To avoid bias, we must ensure that the size of 328 /// our sample space, `zone`, is a multiple of `range`; other values must be 329 /// rejected (by replacing with a new random sample). 330 /// 331 /// As a special case, we use `range = 0` to represent the full range of the 332 /// result type (i.e. for `new_inclusive($ty::MIN, $ty::MAX)`). 333 /// 334 /// The optimum `zone` is the largest product of `range` which fits in our 335 /// (unsigned) target type. We calculate this by calculating how many numbers we 336 /// must reject: `reject = (MAX + 1) % range = (MAX - range + 1) % range`. Any (large) 337 /// product of `range` will suffice, thus in `sample_single` we multiply by a 338 /// power of 2 via bit-shifting (faster but may cause more rejections). 339 /// 340 /// The smallest integer PRNGs generate is `u32`. For 8- and 16-bit outputs we 341 /// use `u32` for our `zone` and samples (because it's not slower and because 342 /// it reduces the chance of having to reject a sample). In this case we cannot 343 /// store `zone` in the target type since it is too large, however we know 344 /// `ints_to_reject < range <= $unsigned::MAX`. 345 /// 346 /// An alternative to using a modulus is widening multiply: After a widening 347 /// multiply by `range`, the result is in the high word. Then comparing the low 348 /// word against `zone` makes sure our distribution is uniform. 349 #[derive(Clone, Copy, Debug)] 350 pub struct UniformInt<X> { 351 low: X, 352 range: X, 353 z: X, // either ints_to_reject or zone depending on implementation 354 } 355 356 macro_rules! uniform_int_impl { 357 ($ty:ty, $unsigned:ident, $u_large:ident) => { 358 impl SampleUniform for $ty { 359 type Sampler = UniformInt<$ty>; 360 } 361 362 impl UniformSampler for UniformInt<$ty> { 363 // We play free and fast with unsigned vs signed here 364 // (when $ty is signed), but that's fine, since the 365 // contract of this macro is for $ty and $unsigned to be 366 // "bit-equal", so casting between them is a no-op. 367 368 type X = $ty; 369 370 #[inline] // if the range is constant, this helps LLVM to do the 371 // calculations at compile-time. 372 fn new<B1, B2>(low_b: B1, high_b: B2) -> Self 373 where 374 B1: SampleBorrow<Self::X> + Sized, 375 B2: SampleBorrow<Self::X> + Sized, 376 { 377 let low = *low_b.borrow(); 378 let high = *high_b.borrow(); 379 assert!(low < high, "Uniform::new called with `low >= high`"); 380 UniformSampler::new_inclusive(low, high - 1) 381 } 382 383 #[inline] // if the range is constant, this helps LLVM to do the 384 // calculations at compile-time. 385 fn new_inclusive<B1, B2>(low_b: B1, high_b: B2) -> Self 386 where 387 B1: SampleBorrow<Self::X> + Sized, 388 B2: SampleBorrow<Self::X> + Sized, 389 { 390 let low = *low_b.borrow(); 391 let high = *high_b.borrow(); 392 assert!( 393 low <= high, 394 "Uniform::new_inclusive called with `low > high`" 395 ); 396 let unsigned_max = ::core::$u_large::MAX; 397 398 let range = high.wrapping_sub(low).wrapping_add(1) as $unsigned; 399 let ints_to_reject = if range > 0 { 400 let range = $u_large::from(range); 401 (unsigned_max - range + 1) % range 402 } else { 403 0 404 }; 405 406 UniformInt { 407 low: low, 408 // These are really $unsigned values, but store as $ty: 409 range: range as $ty, 410 z: ints_to_reject as $unsigned as $ty, 411 } 412 } 413 414 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Self::X { 415 let range = self.range as $unsigned as $u_large; 416 if range > 0 { 417 let unsigned_max = ::core::$u_large::MAX; 418 let zone = unsigned_max - (self.z as $unsigned as $u_large); 419 loop { 420 let v: $u_large = rng.gen(); 421 let (hi, lo) = v.wmul(range); 422 if lo <= zone { 423 return self.low.wrapping_add(hi as $ty); 424 } 425 } 426 } else { 427 // Sample from the entire integer range. 428 rng.gen() 429 } 430 } 431 432 fn sample_single<R: Rng + ?Sized, B1, B2>(low_b: B1, high_b: B2, rng: &mut R) -> Self::X 433 where 434 B1: SampleBorrow<Self::X> + Sized, 435 B2: SampleBorrow<Self::X> + Sized, 436 { 437 let low = *low_b.borrow(); 438 let high = *high_b.borrow(); 439 assert!(low < high, "UniformSampler::sample_single: low >= high"); 440 let range = high.wrapping_sub(low) as $unsigned as $u_large; 441 let zone = if ::core::$unsigned::MAX <= ::core::u16::MAX as $unsigned { 442 // Using a modulus is faster than the approximation for 443 // i8 and i16. I suppose we trade the cost of one 444 // modulus for near-perfect branch prediction. 445 let unsigned_max: $u_large = ::core::$u_large::MAX; 446 let ints_to_reject = (unsigned_max - range + 1) % range; 447 unsigned_max - ints_to_reject 448 } else { 449 // conservative but fast approximation. `- 1` is necessary to allow the 450 // same comparison without bias. 451 (range << range.leading_zeros()).wrapping_sub(1) 452 }; 453 454 loop { 455 let v: $u_large = rng.gen(); 456 let (hi, lo) = v.wmul(range); 457 if lo <= zone { 458 return low.wrapping_add(hi as $ty); 459 } 460 } 461 } 462 } 463 }; 464 } 465 466 uniform_int_impl! { i8, u8, u32 } 467 uniform_int_impl! { i16, u16, u32 } 468 uniform_int_impl! { i32, u32, u32 } 469 uniform_int_impl! { i64, u64, u64 } 470 #[cfg(not(target_os = "emscripten"))] 471 uniform_int_impl! { i128, u128, u128 } 472 uniform_int_impl! { isize, usize, usize } 473 uniform_int_impl! { u8, u8, u32 } 474 uniform_int_impl! { u16, u16, u32 } 475 uniform_int_impl! { u32, u32, u32 } 476 uniform_int_impl! { u64, u64, u64 } 477 uniform_int_impl! { usize, usize, usize } 478 #[cfg(not(target_os = "emscripten"))] 479 uniform_int_impl! { u128, u128, u128 } 480 481 #[cfg(all(feature = "simd_support", feature = "nightly"))] 482 macro_rules! uniform_simd_int_impl { 483 ($ty:ident, $unsigned:ident, $u_scalar:ident) => { 484 // The "pick the largest zone that can fit in an `u32`" optimization 485 // is less useful here. Multiple lanes complicate things, we don't 486 // know the PRNG's minimal output size, and casting to a larger vector 487 // is generally a bad idea for SIMD performance. The user can still 488 // implement it manually. 489 490 // TODO: look into `Uniform::<u32x4>::new(0u32, 100)` functionality 491 // perhaps `impl SampleUniform for $u_scalar`? 492 impl SampleUniform for $ty { 493 type Sampler = UniformInt<$ty>; 494 } 495 496 impl UniformSampler for UniformInt<$ty> { 497 type X = $ty; 498 499 #[inline] // if the range is constant, this helps LLVM to do the 500 // calculations at compile-time. 501 fn new<B1, B2>(low_b: B1, high_b: B2) -> Self 502 where B1: SampleBorrow<Self::X> + Sized, 503 B2: SampleBorrow<Self::X> + Sized 504 { 505 let low = *low_b.borrow(); 506 let high = *high_b.borrow(); 507 assert!(low.lt(high).all(), "Uniform::new called with `low >= high`"); 508 UniformSampler::new_inclusive(low, high - 1) 509 } 510 511 #[inline] // if the range is constant, this helps LLVM to do the 512 // calculations at compile-time. 513 fn new_inclusive<B1, B2>(low_b: B1, high_b: B2) -> Self 514 where B1: SampleBorrow<Self::X> + Sized, 515 B2: SampleBorrow<Self::X> + Sized 516 { 517 let low = *low_b.borrow(); 518 let high = *high_b.borrow(); 519 assert!(low.le(high).all(), 520 "Uniform::new_inclusive called with `low > high`"); 521 let unsigned_max = ::core::$u_scalar::MAX; 522 523 // NOTE: these may need to be replaced with explicitly 524 // wrapping operations if `packed_simd` changes 525 let range: $unsigned = ((high - low) + 1).cast(); 526 // `% 0` will panic at runtime. 527 let not_full_range = range.gt($unsigned::splat(0)); 528 // replacing 0 with `unsigned_max` allows a faster `select` 529 // with bitwise OR 530 let modulo = not_full_range.select(range, $unsigned::splat(unsigned_max)); 531 // wrapping addition 532 let ints_to_reject = (unsigned_max - range + 1) % modulo; 533 // When `range` is 0, `lo` of `v.wmul(range)` will always be 534 // zero which means only one sample is needed. 535 let zone = unsigned_max - ints_to_reject; 536 537 UniformInt { 538 low: low, 539 // These are really $unsigned values, but store as $ty: 540 range: range.cast(), 541 z: zone.cast(), 542 } 543 } 544 545 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Self::X { 546 let range: $unsigned = self.range.cast(); 547 let zone: $unsigned = self.z.cast(); 548 549 // This might seem very slow, generating a whole new 550 // SIMD vector for every sample rejection. For most uses 551 // though, the chance of rejection is small and provides good 552 // general performance. With multiple lanes, that chance is 553 // multiplied. To mitigate this, we replace only the lanes of 554 // the vector which fail, iteratively reducing the chance of 555 // rejection. The replacement method does however add a little 556 // overhead. Benchmarking or calculating probabilities might 557 // reveal contexts where this replacement method is slower. 558 let mut v: $unsigned = rng.gen(); 559 loop { 560 let (hi, lo) = v.wmul(range); 561 let mask = lo.le(zone); 562 if mask.all() { 563 let hi: $ty = hi.cast(); 564 // wrapping addition 565 let result = self.low + hi; 566 // `select` here compiles to a blend operation 567 // When `range.eq(0).none()` the compare and blend 568 // operations are avoided. 569 let v: $ty = v.cast(); 570 return range.gt($unsigned::splat(0)).select(result, v); 571 } 572 // Replace only the failing lanes 573 v = mask.select(v, rng.gen()); 574 } 575 } 576 } 577 }; 578 579 // bulk implementation 580 ($(($unsigned:ident, $signed:ident),)+ $u_scalar:ident) => { 581 $( 582 uniform_simd_int_impl!($unsigned, $unsigned, $u_scalar); 583 uniform_simd_int_impl!($signed, $unsigned, $u_scalar); 584 )+ 585 }; 586 } 587 588 #[cfg(all(feature = "simd_support", feature = "nightly"))] 589 uniform_simd_int_impl! { 590 (u64x2, i64x2), 591 (u64x4, i64x4), 592 (u64x8, i64x8), 593 u64 594 } 595 596 #[cfg(all(feature = "simd_support", feature = "nightly"))] 597 uniform_simd_int_impl! { 598 (u32x2, i32x2), 599 (u32x4, i32x4), 600 (u32x8, i32x8), 601 (u32x16, i32x16), 602 u32 603 } 604 605 #[cfg(all(feature = "simd_support", feature = "nightly"))] 606 uniform_simd_int_impl! { 607 (u16x2, i16x2), 608 (u16x4, i16x4), 609 (u16x8, i16x8), 610 (u16x16, i16x16), 611 (u16x32, i16x32), 612 u16 613 } 614 615 #[cfg(all(feature = "simd_support", feature = "nightly"))] 616 uniform_simd_int_impl! { 617 (u8x2, i8x2), 618 (u8x4, i8x4), 619 (u8x8, i8x8), 620 (u8x16, i8x16), 621 (u8x32, i8x32), 622 (u8x64, i8x64), 623 u8 624 } 625 626 627 /// The back-end implementing [`UniformSampler`] for floating-point types. 628 /// 629 /// Unless you are implementing [`UniformSampler`] for your own type, this type 630 /// should not be used directly, use [`Uniform`] instead. 631 /// 632 /// # Implementation notes 633 /// 634 /// Instead of generating a float in the `[0, 1)` range using [`Standard`], the 635 /// `UniformFloat` implementation converts the output of an PRNG itself. This 636 /// way one or two steps can be optimized out. 637 /// 638 /// The floats are first converted to a value in the `[1, 2)` interval using a 639 /// transmute-based method, and then mapped to the expected range with a 640 /// multiply and addition. Values produced this way have what equals 23 bits of 641 /// random digits for an `f32`, and 52 for an `f64`. 642 /// 643 /// [`new`]: UniformSampler::new 644 /// [`new_inclusive`]: UniformSampler::new_inclusive 645 /// [`Standard`]: crate::distributions::Standard 646 #[derive(Clone, Copy, Debug)] 647 pub struct UniformFloat<X> { 648 low: X, 649 scale: X, 650 } 651 652 macro_rules! uniform_float_impl { 653 ($ty:ty, $uty:ident, $f_scalar:ident, $u_scalar:ident, $bits_to_discard:expr) => { 654 impl SampleUniform for $ty { 655 type Sampler = UniformFloat<$ty>; 656 } 657 658 impl UniformSampler for UniformFloat<$ty> { 659 type X = $ty; 660 661 fn new<B1, B2>(low_b: B1, high_b: B2) -> Self 662 where 663 B1: SampleBorrow<Self::X> + Sized, 664 B2: SampleBorrow<Self::X> + Sized, 665 { 666 let low = *low_b.borrow(); 667 let high = *high_b.borrow(); 668 assert!(low.all_lt(high), "Uniform::new called with `low >= high`"); 669 assert!( 670 low.all_finite() && high.all_finite(), 671 "Uniform::new called with non-finite boundaries" 672 ); 673 let max_rand = <$ty>::splat( 674 (::core::$u_scalar::MAX >> $bits_to_discard).into_float_with_exponent(0) - 1.0, 675 ); 676 677 let mut scale = high - low; 678 679 loop { 680 let mask = (scale * max_rand + low).ge_mask(high); 681 if mask.none() { 682 break; 683 } 684 scale = scale.decrease_masked(mask); 685 } 686 687 debug_assert!(<$ty>::splat(0.0).all_le(scale)); 688 689 UniformFloat { low, scale } 690 } 691 692 fn new_inclusive<B1, B2>(low_b: B1, high_b: B2) -> Self 693 where 694 B1: SampleBorrow<Self::X> + Sized, 695 B2: SampleBorrow<Self::X> + Sized, 696 { 697 let low = *low_b.borrow(); 698 let high = *high_b.borrow(); 699 assert!( 700 low.all_le(high), 701 "Uniform::new_inclusive called with `low > high`" 702 ); 703 assert!( 704 low.all_finite() && high.all_finite(), 705 "Uniform::new_inclusive called with non-finite boundaries" 706 ); 707 let max_rand = <$ty>::splat( 708 (::core::$u_scalar::MAX >> $bits_to_discard).into_float_with_exponent(0) - 1.0, 709 ); 710 711 let mut scale = (high - low) / max_rand; 712 713 loop { 714 let mask = (scale * max_rand + low).gt_mask(high); 715 if mask.none() { 716 break; 717 } 718 scale = scale.decrease_masked(mask); 719 } 720 721 debug_assert!(<$ty>::splat(0.0).all_le(scale)); 722 723 UniformFloat { low, scale } 724 } 725 726 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Self::X { 727 // Generate a value in the range [1, 2) 728 let value1_2 = (rng.gen::<$uty>() >> $bits_to_discard).into_float_with_exponent(0); 729 730 // Get a value in the range [0, 1) in order to avoid 731 // overflowing into infinity when multiplying with scale 732 let value0_1 = value1_2 - 1.0; 733 734 // We don't use `f64::mul_add`, because it is not available with 735 // `no_std`. Furthermore, it is slower for some targets (but 736 // faster for others). However, the order of multiplication and 737 // addition is important, because on some platforms (e.g. ARM) 738 // it will be optimized to a single (non-FMA) instruction. 739 value0_1 * self.scale + self.low 740 } 741 742 #[inline] 743 fn sample_single<R: Rng + ?Sized, B1, B2>(low_b: B1, high_b: B2, rng: &mut R) -> Self::X 744 where 745 B1: SampleBorrow<Self::X> + Sized, 746 B2: SampleBorrow<Self::X> + Sized, 747 { 748 let low = *low_b.borrow(); 749 let high = *high_b.borrow(); 750 assert!( 751 low.all_lt(high), 752 "UniformSampler::sample_single: low >= high" 753 ); 754 let mut scale = high - low; 755 756 loop { 757 // Generate a value in the range [1, 2) 758 let value1_2 = 759 (rng.gen::<$uty>() >> $bits_to_discard).into_float_with_exponent(0); 760 761 // Get a value in the range [0, 1) in order to avoid 762 // overflowing into infinity when multiplying with scale 763 let value0_1 = value1_2 - 1.0; 764 765 // Doing multiply before addition allows some architectures 766 // to use a single instruction. 767 let res = value0_1 * scale + low; 768 769 debug_assert!(low.all_le(res) || !scale.all_finite()); 770 if res.all_lt(high) { 771 return res; 772 } 773 774 // This handles a number of edge cases. 775 // * `low` or `high` is NaN. In this case `scale` and 776 // `res` are going to end up as NaN. 777 // * `low` is negative infinity and `high` is finite. 778 // `scale` is going to be infinite and `res` will be 779 // NaN. 780 // * `high` is positive infinity and `low` is finite. 781 // `scale` is going to be infinite and `res` will 782 // be infinite or NaN (if value0_1 is 0). 783 // * `low` is negative infinity and `high` is positive 784 // infinity. `scale` will be infinite and `res` will 785 // be NaN. 786 // * `low` and `high` are finite, but `high - low` 787 // overflows to infinite. `scale` will be infinite 788 // and `res` will be infinite or NaN (if value0_1 is 0). 789 // So if `high` or `low` are non-finite, we are guaranteed 790 // to fail the `res < high` check above and end up here. 791 // 792 // While we technically should check for non-finite `low` 793 // and `high` before entering the loop, by doing the checks 794 // here instead, we allow the common case to avoid these 795 // checks. But we are still guaranteed that if `low` or 796 // `high` are non-finite we'll end up here and can do the 797 // appropriate checks. 798 // 799 // Likewise `high - low` overflowing to infinity is also 800 // rare, so handle it here after the common case. 801 let mask = !scale.finite_mask(); 802 if mask.any() { 803 assert!( 804 low.all_finite() && high.all_finite(), 805 "Uniform::sample_single: low and high must be finite" 806 ); 807 scale = scale.decrease_masked(mask); 808 } 809 } 810 } 811 } 812 }; 813 } 814 815 uniform_float_impl! { f32, u32, f32, u32, 32 - 23 } 816 uniform_float_impl! { f64, u64, f64, u64, 64 - 52 } 817 818 #[cfg(feature = "simd_support")] 819 uniform_float_impl! { f32x2, u32x2, f32, u32, 32 - 23 } 820 #[cfg(feature = "simd_support")] 821 uniform_float_impl! { f32x4, u32x4, f32, u32, 32 - 23 } 822 #[cfg(feature = "simd_support")] 823 uniform_float_impl! { f32x8, u32x8, f32, u32, 32 - 23 } 824 #[cfg(feature = "simd_support")] 825 uniform_float_impl! { f32x16, u32x16, f32, u32, 32 - 23 } 826 827 #[cfg(feature = "simd_support")] 828 uniform_float_impl! { f64x2, u64x2, f64, u64, 64 - 52 } 829 #[cfg(feature = "simd_support")] 830 uniform_float_impl! { f64x4, u64x4, f64, u64, 64 - 52 } 831 #[cfg(feature = "simd_support")] 832 uniform_float_impl! { f64x8, u64x8, f64, u64, 64 - 52 } 833 834 835 /// The back-end implementing [`UniformSampler`] for `Duration`. 836 /// 837 /// Unless you are implementing [`UniformSampler`] for your own types, this type 838 /// should not be used directly, use [`Uniform`] instead. 839 #[derive(Clone, Copy, Debug)] 840 pub struct UniformDuration { 841 mode: UniformDurationMode, 842 offset: u32, 843 } 844 845 #[derive(Debug, Copy, Clone)] 846 enum UniformDurationMode { 847 Small { 848 secs: u64, 849 nanos: Uniform<u32>, 850 }, 851 Medium { 852 nanos: Uniform<u64>, 853 }, 854 Large { 855 max_secs: u64, 856 max_nanos: u32, 857 secs: Uniform<u64>, 858 }, 859 } 860 861 impl SampleUniform for Duration { 862 type Sampler = UniformDuration; 863 } 864 865 impl UniformSampler for UniformDuration { 866 type X = Duration; 867 868 #[inline] new<B1, B2>(low_b: B1, high_b: B2) -> Self where B1: SampleBorrow<Self::X> + Sized, B2: SampleBorrow<Self::X> + Sized,869 fn new<B1, B2>(low_b: B1, high_b: B2) -> Self 870 where 871 B1: SampleBorrow<Self::X> + Sized, 872 B2: SampleBorrow<Self::X> + Sized, 873 { 874 let low = *low_b.borrow(); 875 let high = *high_b.borrow(); 876 assert!(low < high, "Uniform::new called with `low >= high`"); 877 UniformDuration::new_inclusive(low, high - Duration::new(0, 1)) 878 } 879 880 #[inline] new_inclusive<B1, B2>(low_b: B1, high_b: B2) -> Self where B1: SampleBorrow<Self::X> + Sized, B2: SampleBorrow<Self::X> + Sized,881 fn new_inclusive<B1, B2>(low_b: B1, high_b: B2) -> Self 882 where 883 B1: SampleBorrow<Self::X> + Sized, 884 B2: SampleBorrow<Self::X> + Sized, 885 { 886 let low = *low_b.borrow(); 887 let high = *high_b.borrow(); 888 assert!( 889 low <= high, 890 "Uniform::new_inclusive called with `low > high`" 891 ); 892 893 let low_s = low.as_secs(); 894 let low_n = low.subsec_nanos(); 895 let mut high_s = high.as_secs(); 896 let mut high_n = high.subsec_nanos(); 897 898 if high_n < low_n { 899 high_s -= 1; 900 high_n += 1_000_000_000; 901 } 902 903 let mode = if low_s == high_s { 904 UniformDurationMode::Small { 905 secs: low_s, 906 nanos: Uniform::new_inclusive(low_n, high_n), 907 } 908 } else { 909 let max = high_s 910 .checked_mul(1_000_000_000) 911 .and_then(|n| n.checked_add(u64::from(high_n))); 912 913 if let Some(higher_bound) = max { 914 let lower_bound = low_s * 1_000_000_000 + u64::from(low_n); 915 UniformDurationMode::Medium { 916 nanos: Uniform::new_inclusive(lower_bound, higher_bound), 917 } 918 } else { 919 // An offset is applied to simplify generation of nanoseconds 920 let max_nanos = high_n - low_n; 921 UniformDurationMode::Large { 922 max_secs: high_s, 923 max_nanos, 924 secs: Uniform::new_inclusive(low_s, high_s), 925 } 926 } 927 }; 928 UniformDuration { 929 mode, 930 offset: low_n, 931 } 932 } 933 934 #[inline] sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Duration935 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Duration { 936 match self.mode { 937 UniformDurationMode::Small { secs, nanos } => { 938 let n = nanos.sample(rng); 939 Duration::new(secs, n) 940 } 941 UniformDurationMode::Medium { nanos } => { 942 let nanos = nanos.sample(rng); 943 Duration::new(nanos / 1_000_000_000, (nanos % 1_000_000_000) as u32) 944 } 945 UniformDurationMode::Large { 946 max_secs, 947 max_nanos, 948 secs, 949 } => { 950 // constant folding means this is at least as fast as `gen_range` 951 let nano_range = Uniform::new(0, 1_000_000_000); 952 loop { 953 let s = secs.sample(rng); 954 let n = nano_range.sample(rng); 955 if !(s == max_secs && n > max_nanos) { 956 let sum = n + self.offset; 957 break Duration::new(s, sum); 958 } 959 } 960 } 961 } 962 } 963 } 964 965 #[cfg(test)] 966 mod tests { 967 use super::*; 968 use crate::rngs::mock::StepRng; 969 970 #[should_panic] 971 #[test] test_uniform_bad_limits_equal_int()972 fn test_uniform_bad_limits_equal_int() { 973 Uniform::new(10, 10); 974 } 975 976 #[test] test_uniform_good_limits_equal_int()977 fn test_uniform_good_limits_equal_int() { 978 let mut rng = crate::test::rng(804); 979 let dist = Uniform::new_inclusive(10, 10); 980 for _ in 0..20 { 981 assert_eq!(rng.sample(dist), 10); 982 } 983 } 984 985 #[should_panic] 986 #[test] test_uniform_bad_limits_flipped_int()987 fn test_uniform_bad_limits_flipped_int() { 988 Uniform::new(10, 5); 989 } 990 991 #[test] 992 #[cfg_attr(miri, ignore)] // Miri is too slow test_integers()993 fn test_integers() { 994 #[cfg(not(target_os = "emscripten"))] use core::{i128, u128}; 995 use core::{i16, i32, i64, i8, isize}; 996 use core::{u16, u32, u64, u8, usize}; 997 998 let mut rng = crate::test::rng(251); 999 macro_rules! t { 1000 ($ty:ident, $v:expr, $le:expr, $lt:expr) => {{ 1001 for &(low, high) in $v.iter() { 1002 let my_uniform = Uniform::new(low, high); 1003 for _ in 0..1000 { 1004 let v: $ty = rng.sample(my_uniform); 1005 assert!($le(low, v) && $lt(v, high)); 1006 } 1007 1008 let my_uniform = Uniform::new_inclusive(low, high); 1009 for _ in 0..1000 { 1010 let v: $ty = rng.sample(my_uniform); 1011 assert!($le(low, v) && $le(v, high)); 1012 } 1013 1014 let my_uniform = Uniform::new(&low, high); 1015 for _ in 0..1000 { 1016 let v: $ty = rng.sample(my_uniform); 1017 assert!($le(low, v) && $lt(v, high)); 1018 } 1019 1020 let my_uniform = Uniform::new_inclusive(&low, &high); 1021 for _ in 0..1000 { 1022 let v: $ty = rng.sample(my_uniform); 1023 assert!($le(low, v) && $le(v, high)); 1024 } 1025 1026 for _ in 0..1000 { 1027 let v: $ty = rng.gen_range(low, high); 1028 assert!($le(low, v) && $lt(v, high)); 1029 } 1030 } 1031 }}; 1032 1033 // scalar bulk 1034 ($($ty:ident),*) => {{ 1035 $(t!( 1036 $ty, 1037 [(0, 10), (10, 127), ($ty::MIN, $ty::MAX)], 1038 |x, y| x <= y, 1039 |x, y| x < y 1040 );)* 1041 }}; 1042 1043 // simd bulk 1044 ($($ty:ident),* => $scalar:ident) => {{ 1045 $(t!( 1046 $ty, 1047 [ 1048 ($ty::splat(0), $ty::splat(10)), 1049 ($ty::splat(10), $ty::splat(127)), 1050 ($ty::splat($scalar::MIN), $ty::splat($scalar::MAX)), 1051 ], 1052 |x: $ty, y| x.le(y).all(), 1053 |x: $ty, y| x.lt(y).all() 1054 );)* 1055 }}; 1056 } 1057 t!(i8, i16, i32, i64, isize, u8, u16, u32, u64, usize); 1058 #[cfg(not(target_os = "emscripten"))] 1059 t!(i128, u128); 1060 1061 #[cfg(all(feature = "simd_support", feature = "nightly"))] 1062 { 1063 t!(u8x2, u8x4, u8x8, u8x16, u8x32, u8x64 => u8); 1064 t!(i8x2, i8x4, i8x8, i8x16, i8x32, i8x64 => i8); 1065 t!(u16x2, u16x4, u16x8, u16x16, u16x32 => u16); 1066 t!(i16x2, i16x4, i16x8, i16x16, i16x32 => i16); 1067 t!(u32x2, u32x4, u32x8, u32x16 => u32); 1068 t!(i32x2, i32x4, i32x8, i32x16 => i32); 1069 t!(u64x2, u64x4, u64x8 => u64); 1070 t!(i64x2, i64x4, i64x8 => i64); 1071 } 1072 } 1073 1074 #[test] 1075 #[cfg_attr(miri, ignore)] // Miri is too slow test_floats()1076 fn test_floats() { 1077 let mut rng = crate::test::rng(252); 1078 let mut zero_rng = StepRng::new(0, 0); 1079 let mut max_rng = StepRng::new(0xffff_ffff_ffff_ffff, 0); 1080 macro_rules! t { 1081 ($ty:ty, $f_scalar:ident, $bits_shifted:expr) => {{ 1082 let v: &[($f_scalar, $f_scalar)] = &[ 1083 (0.0, 100.0), 1084 (-1e35, -1e25), 1085 (1e-35, 1e-25), 1086 (-1e35, 1e35), 1087 (<$f_scalar>::from_bits(0), <$f_scalar>::from_bits(3)), 1088 (-<$f_scalar>::from_bits(10), -<$f_scalar>::from_bits(1)), 1089 (-<$f_scalar>::from_bits(5), 0.0), 1090 (-<$f_scalar>::from_bits(7), -0.0), 1091 (10.0, ::core::$f_scalar::MAX), 1092 (-100.0, ::core::$f_scalar::MAX), 1093 (-::core::$f_scalar::MAX / 5.0, ::core::$f_scalar::MAX), 1094 (-::core::$f_scalar::MAX, ::core::$f_scalar::MAX / 5.0), 1095 (-::core::$f_scalar::MAX * 0.8, ::core::$f_scalar::MAX * 0.7), 1096 (-::core::$f_scalar::MAX, ::core::$f_scalar::MAX), 1097 ]; 1098 for &(low_scalar, high_scalar) in v.iter() { 1099 for lane in 0..<$ty>::lanes() { 1100 let low = <$ty>::splat(0.0 as $f_scalar).replace(lane, low_scalar); 1101 let high = <$ty>::splat(1.0 as $f_scalar).replace(lane, high_scalar); 1102 let my_uniform = Uniform::new(low, high); 1103 let my_incl_uniform = Uniform::new_inclusive(low, high); 1104 for _ in 0..100 { 1105 let v = rng.sample(my_uniform).extract(lane); 1106 assert!(low_scalar <= v && v < high_scalar); 1107 let v = rng.sample(my_incl_uniform).extract(lane); 1108 assert!(low_scalar <= v && v <= high_scalar); 1109 let v = rng.gen_range(low, high).extract(lane); 1110 assert!(low_scalar <= v && v < high_scalar); 1111 } 1112 1113 assert_eq!( 1114 rng.sample(Uniform::new_inclusive(low, low)).extract(lane), 1115 low_scalar 1116 ); 1117 1118 assert_eq!(zero_rng.sample(my_uniform).extract(lane), low_scalar); 1119 assert_eq!(zero_rng.sample(my_incl_uniform).extract(lane), low_scalar); 1120 assert_eq!(zero_rng.gen_range(low, high).extract(lane), low_scalar); 1121 assert!(max_rng.sample(my_uniform).extract(lane) < high_scalar); 1122 assert!(max_rng.sample(my_incl_uniform).extract(lane) <= high_scalar); 1123 1124 // Don't run this test for really tiny differences between high and low 1125 // since for those rounding might result in selecting high for a very 1126 // long time. 1127 if (high_scalar - low_scalar) > 0.0001 { 1128 let mut lowering_max_rng = StepRng::new( 1129 0xffff_ffff_ffff_ffff, 1130 (-1i64 << $bits_shifted) as u64, 1131 ); 1132 assert!( 1133 lowering_max_rng.gen_range(low, high).extract(lane) < high_scalar 1134 ); 1135 } 1136 } 1137 } 1138 1139 assert_eq!( 1140 rng.sample(Uniform::new_inclusive( 1141 ::core::$f_scalar::MAX, 1142 ::core::$f_scalar::MAX 1143 )), 1144 ::core::$f_scalar::MAX 1145 ); 1146 assert_eq!( 1147 rng.sample(Uniform::new_inclusive( 1148 -::core::$f_scalar::MAX, 1149 -::core::$f_scalar::MAX 1150 )), 1151 -::core::$f_scalar::MAX 1152 ); 1153 }}; 1154 } 1155 1156 t!(f32, f32, 32 - 23); 1157 t!(f64, f64, 64 - 52); 1158 #[cfg(feature = "simd_support")] 1159 { 1160 t!(f32x2, f32, 32 - 23); 1161 t!(f32x4, f32, 32 - 23); 1162 t!(f32x8, f32, 32 - 23); 1163 t!(f32x16, f32, 32 - 23); 1164 t!(f64x2, f64, 64 - 52); 1165 t!(f64x4, f64, 64 - 52); 1166 t!(f64x8, f64, 64 - 52); 1167 } 1168 } 1169 1170 #[test] 1171 #[cfg(all( 1172 feature = "std", 1173 not(target_arch = "wasm32"), 1174 not(target_arch = "asmjs") 1175 ))] test_float_assertions()1176 fn test_float_assertions() { 1177 use super::SampleUniform; 1178 use std::panic::catch_unwind; 1179 fn range<T: SampleUniform>(low: T, high: T) { 1180 let mut rng = crate::test::rng(253); 1181 rng.gen_range(low, high); 1182 } 1183 1184 macro_rules! t { 1185 ($ty:ident, $f_scalar:ident) => {{ 1186 let v: &[($f_scalar, $f_scalar)] = &[ 1187 (::std::$f_scalar::NAN, 0.0), 1188 (1.0, ::std::$f_scalar::NAN), 1189 (::std::$f_scalar::NAN, ::std::$f_scalar::NAN), 1190 (1.0, 0.5), 1191 (::std::$f_scalar::MAX, -::std::$f_scalar::MAX), 1192 (::std::$f_scalar::INFINITY, ::std::$f_scalar::INFINITY), 1193 ( 1194 ::std::$f_scalar::NEG_INFINITY, 1195 ::std::$f_scalar::NEG_INFINITY, 1196 ), 1197 (::std::$f_scalar::NEG_INFINITY, 5.0), 1198 (5.0, ::std::$f_scalar::INFINITY), 1199 (::std::$f_scalar::NAN, ::std::$f_scalar::INFINITY), 1200 (::std::$f_scalar::NEG_INFINITY, ::std::$f_scalar::NAN), 1201 (::std::$f_scalar::NEG_INFINITY, ::std::$f_scalar::INFINITY), 1202 ]; 1203 for &(low_scalar, high_scalar) in v.iter() { 1204 for lane in 0..<$ty>::lanes() { 1205 let low = <$ty>::splat(0.0 as $f_scalar).replace(lane, low_scalar); 1206 let high = <$ty>::splat(1.0 as $f_scalar).replace(lane, high_scalar); 1207 assert!(catch_unwind(|| range(low, high)).is_err()); 1208 assert!(catch_unwind(|| Uniform::new(low, high)).is_err()); 1209 assert!(catch_unwind(|| Uniform::new_inclusive(low, high)).is_err()); 1210 assert!(catch_unwind(|| range(low, low)).is_err()); 1211 assert!(catch_unwind(|| Uniform::new(low, low)).is_err()); 1212 } 1213 } 1214 }}; 1215 } 1216 1217 t!(f32, f32); 1218 t!(f64, f64); 1219 #[cfg(feature = "simd_support")] 1220 { 1221 t!(f32x2, f32); 1222 t!(f32x4, f32); 1223 t!(f32x8, f32); 1224 t!(f32x16, f32); 1225 t!(f64x2, f64); 1226 t!(f64x4, f64); 1227 t!(f64x8, f64); 1228 } 1229 } 1230 1231 1232 #[test] 1233 #[cfg_attr(miri, ignore)] // Miri is too slow test_durations()1234 fn test_durations() { 1235 #[cfg(not(feature = "std"))] use core::time::Duration; 1236 #[cfg(feature = "std")] use std::time::Duration; 1237 1238 let mut rng = crate::test::rng(253); 1239 1240 let v = &[ 1241 (Duration::new(10, 50000), Duration::new(100, 1234)), 1242 (Duration::new(0, 100), Duration::new(1, 50)), 1243 ( 1244 Duration::new(0, 0), 1245 Duration::new(u64::max_value(), 999_999_999), 1246 ), 1247 ]; 1248 for &(low, high) in v.iter() { 1249 let my_uniform = Uniform::new(low, high); 1250 for _ in 0..1000 { 1251 let v = rng.sample(my_uniform); 1252 assert!(low <= v && v < high); 1253 } 1254 } 1255 } 1256 1257 #[test] test_custom_uniform()1258 fn test_custom_uniform() { 1259 use crate::distributions::uniform::{ 1260 SampleBorrow, SampleUniform, UniformFloat, UniformSampler, 1261 }; 1262 #[derive(Clone, Copy, PartialEq, PartialOrd)] 1263 struct MyF32 { 1264 x: f32, 1265 } 1266 #[derive(Clone, Copy, Debug)] 1267 struct UniformMyF32(UniformFloat<f32>); 1268 impl UniformSampler for UniformMyF32 { 1269 type X = MyF32; 1270 1271 fn new<B1, B2>(low: B1, high: B2) -> Self 1272 where 1273 B1: SampleBorrow<Self::X> + Sized, 1274 B2: SampleBorrow<Self::X> + Sized, 1275 { 1276 UniformMyF32(UniformFloat::<f32>::new(low.borrow().x, high.borrow().x)) 1277 } 1278 1279 fn new_inclusive<B1, B2>(low: B1, high: B2) -> Self 1280 where 1281 B1: SampleBorrow<Self::X> + Sized, 1282 B2: SampleBorrow<Self::X> + Sized, 1283 { 1284 UniformSampler::new(low, high) 1285 } 1286 1287 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Self::X { 1288 MyF32 { 1289 x: self.0.sample(rng), 1290 } 1291 } 1292 } 1293 impl SampleUniform for MyF32 { 1294 type Sampler = UniformMyF32; 1295 } 1296 1297 let (low, high) = (MyF32 { x: 17.0f32 }, MyF32 { x: 22.0f32 }); 1298 let uniform = Uniform::new(low, high); 1299 let mut rng = crate::test::rng(804); 1300 for _ in 0..100 { 1301 let x: MyF32 = rng.sample(uniform); 1302 assert!(low <= x && x < high); 1303 } 1304 } 1305 1306 #[test] test_uniform_from_std_range()1307 fn test_uniform_from_std_range() { 1308 let r = Uniform::from(2u32..7); 1309 assert_eq!(r.0.low, 2); 1310 assert_eq!(r.0.range, 5); 1311 let r = Uniform::from(2.0f64..7.0); 1312 assert_eq!(r.0.low, 2.0); 1313 assert_eq!(r.0.scale, 5.0); 1314 } 1315 1316 #[test] test_uniform_from_std_range_inclusive()1317 fn test_uniform_from_std_range_inclusive() { 1318 let r = Uniform::from(2u32..=6); 1319 assert_eq!(r.0.low, 2); 1320 assert_eq!(r.0.range, 5); 1321 let r = Uniform::from(2.0f64..=7.0); 1322 assert_eq!(r.0.low, 2.0); 1323 assert!(r.0.scale > 5.0); 1324 assert!(r.0.scale < 5.0 + 1e-14); 1325 } 1326 1327 #[test] value_stability()1328 fn value_stability() { 1329 fn test_samples<T: SampleUniform + Copy + core::fmt::Debug + PartialEq>( 1330 lb: T, ub: T, expected_single: &[T], expected_multiple: &[T], 1331 ) where Uniform<T>: Distribution<T> { 1332 let mut rng = crate::test::rng(897); 1333 let mut buf = [lb; 3]; 1334 1335 for x in &mut buf { 1336 *x = T::Sampler::sample_single(lb, ub, &mut rng); 1337 } 1338 assert_eq!(&buf, expected_single); 1339 1340 let distr = Uniform::new(lb, ub); 1341 for x in &mut buf { 1342 *x = rng.sample(&distr); 1343 } 1344 assert_eq!(&buf, expected_multiple); 1345 } 1346 1347 // We test on a sub-set of types; possibly we should do more. 1348 // TODO: SIMD types 1349 1350 test_samples(11u8, 219, &[17, 66, 214], &[181, 93, 165]); 1351 test_samples(11u32, 219, &[17, 66, 214], &[181, 93, 165]); 1352 1353 test_samples(0f32, 1e-2f32, &[0.0003070104, 0.0026630748, 0.00979833], &[ 1354 0.008194133, 1355 0.00398172, 1356 0.007428536, 1357 ]); 1358 test_samples( 1359 -1e10f64, 1360 1e10f64, 1361 &[-4673848682.871551, 6388267422.932352, 4857075081.198343], 1362 &[1173375212.1808167, 1917642852.109581, 2365076174.3153973], 1363 ); 1364 1365 test_samples( 1366 Duration::new(2, 0), 1367 Duration::new(4, 0), 1368 &[ 1369 Duration::new(2, 532615131), 1370 Duration::new(3, 638826742), 1371 Duration::new(3, 485707508), 1372 ], 1373 &[ 1374 Duration::new(3, 117337521), 1375 Duration::new(3, 191764285), 1376 Duration::new(3, 236507617), 1377 ], 1378 ); 1379 } 1380 } 1381