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)` 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..=10) { |

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

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

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

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 | //! UniformMyF32(UniformFloat::<f32>::new_inclusive( |

84 | //! low.borrow().0, |

85 | //! high.borrow().0, |

86 | //! )) |

87 | //! } |

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

89 | //! MyF32(self.0.sample(rng)) |

90 | //! } |

91 | //! } |

92 | //! |

93 | //! impl SampleUniform for MyF32 { |

94 | //! type Sampler = UniformMyF32; |

95 | //! } |

96 | //! |

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

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

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

100 | //! ``` |

101 | //! |

102 | //! [`SampleUniform`]: crate::distributions::uniform::SampleUniform |

103 | //! [`UniformSampler`]: crate::distributions::uniform::UniformSampler |

104 | //! [`UniformInt`]: crate::distributions::uniform::UniformInt |

105 | //! [`UniformFloat`]: crate::distributions::uniform::UniformFloat |

106 | //! [`UniformDuration`]: crate::distributions::uniform::UniformDuration |

107 | //! [`SampleBorrow::borrow`]: crate::distributions::uniform::SampleBorrow::borrow |

108 | |

109 | use core::time::Duration; |

110 | use core::ops::{Range, RangeInclusive}; |

111 | |

112 | use crate::distributions::float::IntoFloat; |

113 | use crate::distributions::utils::{BoolAsSIMD, FloatAsSIMD, FloatSIMDUtils, WideningMultiply}; |

114 | use crate::distributions::Distribution; |

115 | use crate::{Rng, RngCore}; |

116 | |

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

118 | #[allow(unused_imports)] // rustc doesn't detect that this is actually used |

119 | use crate::distributions::utils::Float; |

120 | |

121 | #[cfg(feature = "simd_support")] use packed_simd::*; |

122 | |

123 | #[cfg(feature = "serde1")] |

124 | use serde::{Serialize, Deserialize}; |

125 | |

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

127 | /// |

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

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

130 | /// work up front to make sampling of multiple values faster. If only one sample |

131 | /// from the range is required, [`Rng::gen_range`] can be more efficient. |

132 | /// |

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

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

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

136 | /// the `Standard` distribution. |

137 | /// |

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

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

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

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

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

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

144 | /// |

145 | /// Implementations must sample in `[low, high)` range for |

146 | /// `Uniform::new(low, high)`, i.e., excluding `high`. In particular, care must |

147 | /// be taken to ensure that rounding never results values `< low` or `>= high`. |

148 | /// |

149 | /// # Example |

150 | /// |

151 | /// ``` |

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

153 | /// |

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

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

156 | /// let mut sum = 0; |

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

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

159 | /// } |

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

161 | /// ``` |

162 | /// |

163 | /// For a single sample, [`Rng::gen_range`] may be preferred: |

164 | /// |

165 | /// ``` |

166 | /// use rand::Rng; |

167 | /// |

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

169 | /// println!("{}", rng.gen_range( 0..10)); |

170 | /// ``` |

171 | /// |

172 | /// [`new`]: Uniform::new |

173 | /// [`new_inclusive`]: Uniform::new_inclusive |

174 | /// [`Rng::gen_range`]: Rng::gen_range |

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

176 | #[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] |

177 | #[cfg_attr(feature = "serde1", serde(bound(serialize = "X::Sampler: Serialize")))] |

178 | #[cfg_attr(feature = "serde1", serde(bound(deserialize = "X::Sampler: Deserialize<'de>")))] |

179 | pub struct Uniform<X: SampleUniform>(X::Sampler); |

180 | |

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

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

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

184 | pub fn new<B1, B2>(low: B1, high: B2) -> Uniform<X> |

185 | where |

186 | B1: SampleBorrow<X> + Sized, |

187 | B2: SampleBorrow<X> + Sized, |

188 | { |

189 | Uniform(X::Sampler::new(low, high)) |

190 | } |

191 | |

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

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

194 | pub fn new_inclusive<B1, B2>(low: B1, high: B2) -> Uniform<X> |

195 | where |

196 | B1: SampleBorrow<X> + Sized, |

197 | B2: SampleBorrow<X> + Sized, |

198 | { |

199 | Uniform(X::Sampler::new_inclusive(low, high)) |

200 | } |

201 | } |

202 | |

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

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

205 | self.0.sample(rng) |

206 | } |

207 | } |

208 | |

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

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

211 | /// |

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

213 | /// sampling for a custom type. |

214 | /// |

215 | /// [module documentation]: crate::distributions::uniform |

216 | pub trait SampleUniform: Sized { |

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

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

219 | } |

220 | |

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

222 | /// |

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

224 | /// sampling for a custom type. |

225 | /// |

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

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

228 | /// |

229 | /// [module documentation]: crate::distributions::uniform |

230 | /// [`sample_single`]: UniformSampler::sample_single |

231 | pub trait UniformSampler: Sized { |

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

233 | type X; |

234 | |

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

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

237 | /// |

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

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

240 | fn new<B1, B2>(low: B1, high: B2) -> Self |

241 | where |

242 | B1: SampleBorrow<Self::X> + Sized, |

243 | B2: SampleBorrow<Self::X> + Sized; |

244 | |

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

246 | /// |

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

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

249 | /// calling this. |

250 | fn new_inclusive<B1, B2>(low: B1, high: B2) -> Self |

251 | where |

252 | B1: SampleBorrow<Self::X> + Sized, |

253 | B2: SampleBorrow<Self::X> + Sized; |

254 | |

255 | /// Sample a value. |

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

257 | |

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

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

260 | /// |

261 | /// By default this is implemented using |

262 | /// `UniformSampler::new(low, high).sample(rng)`. However, for some types |

263 | /// more optimal implementations for single usage may be provided via this |

264 | /// method (which is the case for integers and floats). |

265 | /// Results may not be identical. |

266 | /// |

267 | /// Note that to use this method in a generic context, the type needs to be |

268 | /// retrieved via `SampleUniform::Sampler` as follows: |

269 | /// ``` |

270 | /// use rand::{thread_rng, distributions::uniform::{SampleUniform, UniformSampler}}; |

271 | /// # #[allow(unused)] |

272 | /// fn sample_from_range<T: SampleUniform>(lb: T, ub: T) -> T { |

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

274 | /// <T as SampleUniform>::Sampler::sample_single(lb, ub, &mut rng) |

275 | /// } |

276 | /// ``` |

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

278 | where |

279 | B1: SampleBorrow<Self::X> + Sized, |

280 | B2: SampleBorrow<Self::X> + Sized, |

281 | { |

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

283 | uniform.sample(rng) |

284 | } |

285 | |

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

287 | /// and inclusive upper bound `[low, high]`. |

288 | /// |

289 | /// By default this is implemented using |

290 | /// `UniformSampler::new_inclusive(low, high).sample(rng)`. However, for |

291 | /// some types more optimal implementations for single usage may be provided |

292 | /// via this method. |

293 | /// Results may not be identical. |

294 | fn sample_single_inclusive<R: Rng + ?Sized, B1, B2>(low: B1, high: B2, rng: &mut R) |

295 | -> Self::X |

296 | where B1: SampleBorrow<Self::X> + Sized, |

297 | B2: SampleBorrow<Self::X> + Sized |

298 | { |

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

300 | uniform.sample(rng) |

301 | } |

302 | } |

303 | |

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

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

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

307 | } |

308 | } |

309 | |

310 | impl<X: SampleUniform> From<RangeInclusive<X>> for Uniform<X> { |

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

312 | Uniform::new_inclusive(r.start(), r.end()) |

313 | } |

314 | } |

315 | |

316 | |

317 | /// Helper trait similar to [`Borrow`] but implemented |

318 | /// only for SampleUniform and references to SampleUniform in |

319 | /// order to resolve ambiguity issues. |

320 | /// |

321 | /// [`Borrow`]: std::borrow::Borrow |

322 | pub trait SampleBorrow<Borrowed> { |

323 | /// Immutably borrows from an owned value. See [`Borrow::borrow`] |

324 | /// |

325 | /// [`Borrow::borrow`]: std::borrow::Borrow::borrow |

326 | fn borrow(&self) -> &Borrowed; |

327 | } |

328 | impl<Borrowed> SampleBorrow<Borrowed> for Borrowed |

329 | where Borrowed: SampleUniform |

330 | { |

331 | #[inline(always)] |

332 | fn borrow(&self) -> &Borrowed { |

333 | self |

334 | } |

335 | } |

336 | impl<'a, Borrowed> SampleBorrow<Borrowed> for &'a Borrowed |

337 | where Borrowed: SampleUniform |

338 | { |

339 | #[inline(always)] |

340 | fn borrow(&self) -> &Borrowed { |

341 | *self |

342 | } |

343 | } |

344 | |

345 | /// Range that supports generating a single sample efficiently. |

346 | /// |

347 | /// Any type implementing this trait can be used to specify the sampled range |

348 | /// for `Rng::gen_range`. |

349 | pub trait SampleRange<T> { |

350 | /// Generate a sample from the given range. |

351 | fn sample_single<R: RngCore + ?Sized>(self, rng: &mut R) -> T; |

352 | |

353 | /// Check whether the range is empty. |

354 | fn is_empty(&self) -> bool; |

355 | } |

356 | |

357 | impl<T: SampleUniform + PartialOrd> SampleRange<T> for Range<T> { |

358 | #[inline] |

359 | fn sample_single<R: RngCore + ?Sized>(self, rng: &mut R) -> T { |

360 | T::Sampler::sample_single(self.start, self.end, rng) |

361 | } |

362 | |

363 | #[inline] |

364 | fn is_empty(&self) -> bool { |

365 | !(self.start < self.end) |

366 | } |

367 | } |

368 | |

369 | impl<T: SampleUniform + PartialOrd> SampleRange<T> for RangeInclusive<T> { |

370 | #[inline] |

371 | fn sample_single<R: RngCore + ?Sized>(self, rng: &mut R) -> T { |

372 | T::Sampler::sample_single_inclusive(self.start(), self.end(), rng) |

373 | } |

374 | |

375 | #[inline] |

376 | fn is_empty(&self) -> bool { |

377 | !(self.start() <= self.end()) |

378 | } |

379 | } |

380 | |

381 | |

382 | //////////////////////////////////////////////////////////////////////////////// |

383 | |

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

385 | |

386 | |

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

388 | /// |

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

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

391 | /// |

392 | /// # Implementation notes |

393 | /// |

394 | /// For simplicity, we use the same generic struct `UniformInt<X>` for all |

395 | /// integer types `X`. This gives us only one field type, `X`; to store unsigned |

396 | /// values of this size, we take use the fact that these conversions are no-ops. |

397 | /// |

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

399 | /// `range = (high - low + 1)`. To avoid bias, we must ensure that the size of |

400 | /// our sample space, `zone`, is a multiple of `range`; other values must be |

401 | /// rejected (by replacing with a new random sample). |

402 | /// |

403 | /// As a special case, we use `range = 0` to represent the full range of the |

404 | /// result type (i.e. for `new_inclusive($ty::MIN, $ty::MAX)`). |

405 | /// |

406 | /// The optimum `zone` is the largest product of `range` which fits in our |

407 | /// (unsigned) target type. We calculate this by calculating how many numbers we |

408 | /// must reject: `reject = (MAX + 1) % range = (MAX - range + 1) % range`. Any (large) |

409 | /// product of `range` will suffice, thus in `sample_single` we multiply by a |

410 | /// power of 2 via bit-shifting (faster but may cause more rejections). |

411 | /// |

412 | /// The smallest integer PRNGs generate is `u32`. For 8- and 16-bit outputs we |

413 | /// use `u32` for our `zone` and samples (because it's not slower and because |

414 | /// it reduces the chance of having to reject a sample). In this case we cannot |

415 | /// store `zone` in the target type since it is too large, however we know |

416 | /// `ints_to_reject < range <= $unsigned::MAX`. |

417 | /// |

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

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

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

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

422 | #[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] |

423 | pub struct UniformInt<X> { |

424 | low: X, |

425 | range: X, |

426 | z: X, // either ints_to_reject or zone depending on implementation |

427 | } |

428 | |

429 | macro_rules! uniform_int_impl { |

430 | ($ty:ty, $unsigned:ident, $u_large:ident) => { |

431 | impl SampleUniform for $ty { |

432 | type Sampler = UniformInt<$ty>; |

433 | } |

434 | |

435 | impl UniformSampler for UniformInt<$ty> { |

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

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

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

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

440 | |

441 | type X = $ty; |

442 | |

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

444 | // calculations at compile-time. |

445 | fn new<B1, B2>(low_b: B1, high_b: B2) -> Self |

446 | where |

447 | B1: SampleBorrow<Self::X> + Sized, |

448 | B2: SampleBorrow<Self::X> + Sized, |

449 | { |

450 | let low = *low_b.borrow(); |

451 | let high = *high_b.borrow(); |

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

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

454 | } |

455 | |

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

457 | // calculations at compile-time. |

458 | fn new_inclusive<B1, B2>(low_b: B1, high_b: B2) -> Self |

459 | where |

460 | B1: SampleBorrow<Self::X> + Sized, |

461 | B2: SampleBorrow<Self::X> + Sized, |

462 | { |

463 | let low = *low_b.borrow(); |

464 | let high = *high_b.borrow(); |

465 | assert!( |

466 | low <= high, |

467 | "Uniform::new_inclusive called with `low > high`" |

468 | ); |

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

470 | |

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

472 | let ints_to_reject = if range > 0 { |

473 | let range = $u_large::from(range); |

474 | (unsigned_max - range + 1) % range |

475 | } else { |

476 | 0 |

477 | }; |

478 | |

479 | UniformInt { |

480 | low, |

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

482 | range: range as $ty, |

483 | z: ints_to_reject as $unsigned as $ty, |

484 | } |

485 | } |

486 | |

487 | #[inline] |

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

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

490 | if range > 0 { |

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

492 | let zone = unsigned_max - (self.z as $unsigned as $u_large); |

493 | loop { |

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

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

496 | if lo <= zone { |

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

498 | } |

499 | } |

500 | } else { |

501 | // Sample from the entire integer range. |

502 | rng.gen() |

503 | } |

504 | } |

505 | |

506 | #[inline] |

507 | fn sample_single<R: Rng + ?Sized, B1, B2>(low_b: B1, high_b: B2, rng: &mut R) -> Self::X |

508 | where |

509 | B1: SampleBorrow<Self::X> + Sized, |

510 | B2: SampleBorrow<Self::X> + Sized, |

511 | { |

512 | let low = *low_b.borrow(); |

513 | let high = *high_b.borrow(); |

514 | assert!(low < high, "UniformSampler::sample_single: low >= high"); |

515 | Self::sample_single_inclusive(low, high - 1, rng) |

516 | } |

517 | |

518 | #[inline] |

519 | fn sample_single_inclusive<R: Rng + ?Sized, B1, B2>(low_b: B1, high_b: B2, rng: &mut R) -> Self::X |

520 | where |

521 | B1: SampleBorrow<Self::X> + Sized, |

522 | B2: SampleBorrow<Self::X> + Sized, |

523 | { |

524 | let low = *low_b.borrow(); |

525 | let high = *high_b.borrow(); |

526 | assert!(low <= high, "UniformSampler::sample_single_inclusive: low > high"); |

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

528 | // If the above resulted in wrap-around to 0, the range is $ty::MIN..=$ty::MAX, |

529 | // and any integer will do. |

530 | if range == 0 { |

531 | return rng.gen(); |

532 | } |

533 | |

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

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

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

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

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

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

540 | unsigned_max - ints_to_reject |

541 | } else { |

542 | // conservative but fast approximation. `- 1` is necessary to allow the |

543 | // same comparison without bias. |

544 | (range << range.leading_zeros()).wrapping_sub(1) |

545 | }; |

546 | |

547 | loop { |

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

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

550 | if lo <= zone { |

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

552 | } |

553 | } |

554 | } |

555 | } |

556 | }; |

557 | } |

558 | |

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

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

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

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

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

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

565 | uniform_int_impl! { u8, u8, u32 } |

566 | uniform_int_impl! { u16, u16, u32 } |

567 | uniform_int_impl! { u32, u32, u32 } |

568 | uniform_int_impl! { u64, u64, u64 } |

569 | uniform_int_impl! { usize, usize, usize } |

570 | uniform_int_impl! { u128, u128, u128 } |

571 | |

572 | #[cfg(feature = "simd_support")] |

573 | macro_rules! uniform_simd_int_impl { |

574 | ($ty:ident, $unsigned:ident, $u_scalar:ident) => { |

575 | // The "pick the largest zone that can fit in an `u32`" optimization |

576 | // is less useful here. Multiple lanes complicate things, we don't |

577 | // know the PRNG's minimal output size, and casting to a larger vector |

578 | // is generally a bad idea for SIMD performance. The user can still |

579 | // implement it manually. |

580 | |

581 | // TODO: look into `Uniform::<u32x4>::new(0u32, 100)` functionality |

582 | // perhaps `impl SampleUniform for $u_scalar`? |

583 | impl SampleUniform for $ty { |

584 | type Sampler = UniformInt<$ty>; |

585 | } |

586 | |

587 | impl UniformSampler for UniformInt<$ty> { |

588 | type X = $ty; |

589 | |

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

591 | // calculations at compile-time. |

592 | fn new<B1, B2>(low_b: B1, high_b: B2) -> Self |

593 | where B1: SampleBorrow<Self::X> + Sized, |

594 | B2: SampleBorrow<Self::X> + Sized |

595 | { |

596 | let low = *low_b.borrow(); |

597 | let high = *high_b.borrow(); |

598 | assert!(low.lt(high).all(), "Uniform::new called with `low >= high`"); |

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

600 | } |

601 | |

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

603 | // calculations at compile-time. |

604 | fn new_inclusive<B1, B2>(low_b: B1, high_b: B2) -> Self |

605 | where B1: SampleBorrow<Self::X> + Sized, |

606 | B2: SampleBorrow<Self::X> + Sized |

607 | { |

608 | let low = *low_b.borrow(); |

609 | let high = *high_b.borrow(); |

610 | assert!(low.le(high).all(), |

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

612 | let unsigned_max = ::core::$u_scalar::MAX; |

613 | |

614 | // NOTE: these may need to be replaced with explicitly |

615 | // wrapping operations if `packed_simd` changes |

616 | let range: $unsigned = ((high - low) + 1).cast(); |

617 | // `% 0` will panic at runtime. |

618 | let not_full_range = range.gt($unsigned::splat(0)); |

619 | // replacing 0 with `unsigned_max` allows a faster `select` |

620 | // with bitwise OR |

621 | let modulo = not_full_range.select(range, $unsigned::splat(unsigned_max)); |

622 | // wrapping addition |

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

624 | // When `range` is 0, `lo` of `v.wmul(range)` will always be |

625 | // zero which means only one sample is needed. |

626 | let zone = unsigned_max - ints_to_reject; |

627 | |

628 | UniformInt { |

629 | low, |

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

631 | range: range.cast(), |

632 | z: zone.cast(), |

633 | } |

634 | } |

635 | |

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

637 | let range: $unsigned = self.range.cast(); |

638 | let zone: $unsigned = self.z.cast(); |

639 | |

640 | // This might seem very slow, generating a whole new |

641 | // SIMD vector for every sample rejection. For most uses |

642 | // though, the chance of rejection is small and provides good |

643 | // general performance. With multiple lanes, that chance is |

644 | // multiplied. To mitigate this, we replace only the lanes of |

645 | // the vector which fail, iteratively reducing the chance of |

646 | // rejection. The replacement method does however add a little |

647 | // overhead. Benchmarking or calculating probabilities might |

648 | // reveal contexts where this replacement method is slower. |

649 | let mut v: $unsigned = rng.gen(); |

650 | loop { |

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

652 | let mask = lo.le(zone); |

653 | if mask.all() { |

654 | let hi: $ty = hi.cast(); |

655 | // wrapping addition |

656 | let result = self.low + hi; |

657 | // `select` here compiles to a blend operation |

658 | // When `range.eq(0).none()` the compare and blend |

659 | // operations are avoided. |

660 | let v: $ty = v.cast(); |

661 | return range.gt($unsigned::splat(0)).select(result, v); |

662 | } |

663 | // Replace only the failing lanes |

664 | v = mask.select(v, rng.gen()); |

665 | } |

666 | } |

667 | } |

668 | }; |

669 | |

670 | // bulk implementation |

671 | ($(($unsigned:ident, $signed:ident),)+ $u_scalar:ident) => { |

672 | $( |

673 | uniform_simd_int_impl!($unsigned, $unsigned, $u_scalar); |

674 | uniform_simd_int_impl!($signed, $unsigned, $u_scalar); |

675 | )+ |

676 | }; |

677 | } |

678 | |

679 | #[cfg(feature = "simd_support")] |

680 | uniform_simd_int_impl! { |

681 | (u64x2, i64x2), |

682 | (u64x4, i64x4), |

683 | (u64x8, i64x8), |

684 | u64 |

685 | } |

686 | |

687 | #[cfg(feature = "simd_support")] |

688 | uniform_simd_int_impl! { |

689 | (u32x2, i32x2), |

690 | (u32x4, i32x4), |

691 | (u32x8, i32x8), |

692 | (u32x16, i32x16), |

693 | u32 |

694 | } |

695 | |

696 | #[cfg(feature = "simd_support")] |

697 | uniform_simd_int_impl! { |

698 | (u16x2, i16x2), |

699 | (u16x4, i16x4), |

700 | (u16x8, i16x8), |

701 | (u16x16, i16x16), |

702 | (u16x32, i16x32), |

703 | u16 |

704 | } |

705 | |

706 | #[cfg(feature = "simd_support")] |

707 | uniform_simd_int_impl! { |

708 | (u8x2, i8x2), |

709 | (u8x4, i8x4), |

710 | (u8x8, i8x8), |

711 | (u8x16, i8x16), |

712 | (u8x32, i8x32), |

713 | (u8x64, i8x64), |

714 | u8 |

715 | } |

716 | |

717 | impl SampleUniform for char { |

718 | type Sampler = UniformChar; |

719 | } |

720 | |

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

722 | /// |

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

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

725 | /// |

726 | /// This differs from integer range sampling since the range `0xD800..=0xDFFF` |

727 | /// are used for surrogate pairs in UCS and UTF-16, and consequently are not |

728 | /// valid Unicode code points. We must therefore avoid sampling values in this |

729 | /// range. |

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

731 | #[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] |

732 | pub struct UniformChar { |

733 | sampler: UniformInt<u32>, |

734 | } |

735 | |

736 | /// UTF-16 surrogate range start |

737 | const CHAR_SURROGATE_START: u32 = 0xD800; |

738 | /// UTF-16 surrogate range size |

739 | const CHAR_SURROGATE_LEN: u32 = 0xE000 - CHAR_SURROGATE_START; |

740 | |

741 | /// Convert `char` to compressed `u32` |

742 | fn char_to_comp_u32(c: char) -> u32 { |

743 | match c as u32 { |

744 | c if c >= CHAR_SURROGATE_START => c - CHAR_SURROGATE_LEN, |

745 | c => c, |

746 | } |

747 | } |

748 | |

749 | impl UniformSampler for UniformChar { |

750 | type X = char; |

751 | |

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

753 | // calculations at compile-time. |

754 | fn new<B1, B2>(low_b: B1, high_b: B2) -> Self |

755 | where |

756 | B1: SampleBorrow<Self::X> + Sized, |

757 | B2: SampleBorrow<Self::X> + Sized, |

758 | { |

759 | let low = char_to_comp_u32(*low_b.borrow()); |

760 | let high = char_to_comp_u32(*high_b.borrow()); |

761 | let sampler = UniformInt::<u32>::new(low, high); |

762 | UniformChar { sampler } |

763 | } |

764 | |

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

766 | // calculations at compile-time. |

767 | fn new_inclusive<B1, B2>(low_b: B1, high_b: B2) -> Self |

768 | where |

769 | B1: SampleBorrow<Self::X> + Sized, |

770 | B2: SampleBorrow<Self::X> + Sized, |

771 | { |

772 | let low = char_to_comp_u32(*low_b.borrow()); |

773 | let high = char_to_comp_u32(*high_b.borrow()); |

774 | let sampler = UniformInt::<u32>::new_inclusive(low, high); |

775 | UniformChar { sampler } |

776 | } |

777 | |

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

779 | let mut x = self.sampler.sample(rng); |

780 | if x >= CHAR_SURROGATE_START { |

781 | x += CHAR_SURROGATE_LEN; |

782 | } |

783 | // SAFETY: x must not be in surrogate range or greater than char::MAX. |

784 | // This relies on range constructors which accept char arguments. |

785 | // Validity of input char values is assumed. |

786 | unsafe { core::char::from_u32_unchecked(x) } |

787 | } |

788 | } |

789 | |

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

791 | /// |

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

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

794 | /// |

795 | /// # Implementation notes |

796 | /// |

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

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

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

800 | /// |

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

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

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

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

805 | /// |

806 | /// [`new`]: UniformSampler::new |

807 | /// [`new_inclusive`]: UniformSampler::new_inclusive |

808 | /// [`Standard`]: crate::distributions::Standard |

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

810 | #[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] |

811 | pub struct UniformFloat<X> { |

812 | low: X, |

813 | scale: X, |

814 | } |

815 | |

816 | macro_rules! uniform_float_impl { |

817 | ($ty:ty, $uty:ident, $f_scalar:ident, $u_scalar:ident, $bits_to_discard:expr) => { |

818 | impl SampleUniform for $ty { |

819 | type Sampler = UniformFloat<$ty>; |

820 | } |

821 | |

822 | impl UniformSampler for UniformFloat<$ty> { |

823 | type X = $ty; |

824 | |

825 | fn new<B1, B2>(low_b: B1, high_b: B2) -> Self |

826 | where |

827 | B1: SampleBorrow<Self::X> + Sized, |

828 | B2: SampleBorrow<Self::X> + Sized, |

829 | { |

830 | let low = *low_b.borrow(); |

831 | let high = *high_b.borrow(); |

832 | debug_assert!( |

833 | low.all_finite(), |

834 | "Uniform::new called with `low` non-finite." |

835 | ); |

836 | debug_assert!( |

837 | high.all_finite(), |

838 | "Uniform::new called with `high` non-finite." |

839 | ); |

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

841 | let max_rand = <$ty>::splat( |

842 | (::core::$u_scalar::MAX >> $bits_to_discard).into_float_with_exponent(0) - 1.0, |

843 | ); |

844 | |

845 | let mut scale = high - low; |

846 | assert!(scale.all_finite(), "Uniform::new: range overflow"); |

847 | |

848 | loop { |

849 | let mask = (scale * max_rand + low).ge_mask(high); |

850 | if mask.none() { |

851 | break; |

852 | } |

853 | scale = scale.decrease_masked(mask); |

854 | } |

855 | |

856 | debug_assert!(<$ty>::splat(0.0).all_le(scale)); |

857 | |

858 | UniformFloat { low, scale } |

859 | } |

860 | |

861 | fn new_inclusive<B1, B2>(low_b: B1, high_b: B2) -> Self |

862 | where |

863 | B1: SampleBorrow<Self::X> + Sized, |

864 | B2: SampleBorrow<Self::X> + Sized, |

865 | { |

866 | let low = *low_b.borrow(); |

867 | let high = *high_b.borrow(); |

868 | debug_assert!( |

869 | low.all_finite(), |

870 | "Uniform::new_inclusive called with `low` non-finite." |

871 | ); |

872 | debug_assert!( |

873 | high.all_finite(), |

874 | "Uniform::new_inclusive called with `high` non-finite." |

875 | ); |

876 | assert!( |

877 | low.all_le(high), |

878 | "Uniform::new_inclusive called with `low > high`" |

879 | ); |

880 | let max_rand = <$ty>::splat( |

881 | (::core::$u_scalar::MAX >> $bits_to_discard).into_float_with_exponent(0) - 1.0, |

882 | ); |

883 | |

884 | let mut scale = (high - low) / max_rand; |

885 | assert!(scale.all_finite(), "Uniform::new_inclusive: range overflow"); |

886 | |

887 | loop { |

888 | let mask = (scale * max_rand + low).gt_mask(high); |

889 | if mask.none() { |

890 | break; |

891 | } |

892 | scale = scale.decrease_masked(mask); |

893 | } |

894 | |

895 | debug_assert!(<$ty>::splat(0.0).all_le(scale)); |

896 | |

897 | UniformFloat { low, scale } |

898 | } |

899 | |

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

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

902 | let value1_2 = (rng.gen::<$uty>() >> $bits_to_discard).into_float_with_exponent(0); |

903 | |

904 | // Get a value in the range [0, 1) in order to avoid |

905 | // overflowing into infinity when multiplying with scale |

906 | let value0_1 = value1_2 - 1.0; |

907 | |

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

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

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

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

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

913 | value0_1 * self.scale + self.low |

914 | } |

915 | |

916 | #[inline] |

917 | fn sample_single<R: Rng + ?Sized, B1, B2>(low_b: B1, high_b: B2, rng: &mut R) -> Self::X |

918 | where |

919 | B1: SampleBorrow<Self::X> + Sized, |

920 | B2: SampleBorrow<Self::X> + Sized, |

921 | { |

922 | let low = *low_b.borrow(); |

923 | let high = *high_b.borrow(); |

924 | debug_assert!( |

925 | low.all_finite(), |

926 | "UniformSampler::sample_single called with `low` non-finite." |

927 | ); |

928 | debug_assert!( |

929 | high.all_finite(), |

930 | "UniformSampler::sample_single called with `high` non-finite." |

931 | ); |

932 | assert!( |

933 | low.all_lt(high), |

934 | "UniformSampler::sample_single: low >= high" |

935 | ); |

936 | let mut scale = high - low; |

937 | assert!(scale.all_finite(), "UniformSampler::sample_single: range overflow"); |

938 | |

939 | loop { |

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

941 | let value1_2 = |

942 | (rng.gen::<$uty>() >> $bits_to_discard).into_float_with_exponent(0); |

943 | |

944 | // Get a value in the range [0, 1) in order to avoid |

945 | // overflowing into infinity when multiplying with scale |

946 | let value0_1 = value1_2 - 1.0; |

947 | |

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

949 | // to use a single instruction. |

950 | let res = value0_1 * scale + low; |

951 | |

952 | debug_assert!(low.all_le(res) || !scale.all_finite()); |

953 | if res.all_lt(high) { |

954 | return res; |

955 | } |

956 | |

957 | // This handles a number of edge cases. |

958 | // * `low` or `high` is NaN. In this case `scale` and |

959 | // `res` are going to end up as NaN. |

960 | // * `low` is negative infinity and `high` is finite. |

961 | // `scale` is going to be infinite and `res` will be |

962 | // NaN. |

963 | // * `high` is positive infinity and `low` is finite. |

964 | // `scale` is going to be infinite and `res` will |

965 | // be infinite or NaN (if value0_1 is 0). |

966 | // * `low` is negative infinity and `high` is positive |

967 | // infinity. `scale` will be infinite and `res` will |

968 | // be NaN. |

969 | // * `low` and `high` are finite, but `high - low` |

970 | // overflows to infinite. `scale` will be infinite |

971 | // and `res` will be infinite or NaN (if value0_1 is 0). |

972 | // So if `high` or `low` are non-finite, we are guaranteed |

973 | // to fail the `res < high` check above and end up here. |

974 | // |

975 | // While we technically should check for non-finite `low` |

976 | // and `high` before entering the loop, by doing the checks |

977 | // here instead, we allow the common case to avoid these |

978 | // checks. But we are still guaranteed that if `low` or |

979 | // `high` are non-finite we'll end up here and can do the |

980 | // appropriate checks. |

981 | // |

982 | // Likewise `high - low` overflowing to infinity is also |

983 | // rare, so handle it here after the common case. |

984 | let mask = !scale.finite_mask(); |

985 | if mask.any() { |

986 | assert!( |

987 | low.all_finite() && high.all_finite(), |

988 | "Uniform::sample_single: low and high must be finite" |

989 | ); |

990 | scale = scale.decrease_masked(mask); |

991 | } |

992 | } |

993 | } |

994 | } |

995 | }; |

996 | } |

997 | |

998 | uniform_float_impl! { f32, u32, f32, u32, 32 - 23 } |

999 | uniform_float_impl! { f64, u64, f64, u64, 64 - 52 } |

1000 | |

1001 | #[cfg(feature = "simd_support")] |

1002 | uniform_float_impl! { f32x2, u32x2, f32, u32, 32 - 23 } |

1003 | #[cfg(feature = "simd_support")] |

1004 | uniform_float_impl! { f32x4, u32x4, f32, u32, 32 - 23 } |

1005 | #[cfg(feature = "simd_support")] |

1006 | uniform_float_impl! { f32x8, u32x8, f32, u32, 32 - 23 } |

1007 | #[cfg(feature = "simd_support")] |

1008 | uniform_float_impl! { f32x16, u32x16, f32, u32, 32 - 23 } |

1009 | |

1010 | #[cfg(feature = "simd_support")] |

1011 | uniform_float_impl! { f64x2, u64x2, f64, u64, 64 - 52 } |

1012 | #[cfg(feature = "simd_support")] |

1013 | uniform_float_impl! { f64x4, u64x4, f64, u64, 64 - 52 } |

1014 | #[cfg(feature = "simd_support")] |

1015 | uniform_float_impl! { f64x8, u64x8, f64, u64, 64 - 52 } |

1016 | |

1017 | |

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

1019 | /// |

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

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

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

1023 | #[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] |

1024 | pub struct UniformDuration { |

1025 | mode: UniformDurationMode, |

1026 | offset: u32, |

1027 | } |

1028 | |

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

1030 | #[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] |

1031 | enum UniformDurationMode { |

1032 | Small { |

1033 | secs: u64, |

1034 | nanos: Uniform<u32>, |

1035 | }, |

1036 | Medium { |

1037 | nanos: Uniform<u64>, |

1038 | }, |

1039 | Large { |

1040 | max_secs: u64, |

1041 | max_nanos: u32, |

1042 | secs: Uniform<u64>, |

1043 | }, |

1044 | } |

1045 | |

1046 | impl SampleUniform for Duration { |

1047 | type Sampler = UniformDuration; |

1048 | } |

1049 | |

1050 | impl UniformSampler for UniformDuration { |

1051 | type X = Duration; |

1052 | |

1053 | #[inline] |

1054 | fn new<B1, B2>(low_b: B1, high_b: B2) -> Self |

1055 | where |

1056 | B1: SampleBorrow<Self::X> + Sized, |

1057 | B2: SampleBorrow<Self::X> + Sized, |

1058 | { |

1059 | let low = *low_b.borrow(); |

1060 | let high = *high_b.borrow(); |

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

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

1063 | } |

1064 | |

1065 | #[inline] |

1066 | fn new_inclusive<B1, B2>(low_b: B1, high_b: B2) -> Self |

1067 | where |

1068 | B1: SampleBorrow<Self::X> + Sized, |

1069 | B2: SampleBorrow<Self::X> + Sized, |

1070 | { |

1071 | let low = *low_b.borrow(); |

1072 | let high = *high_b.borrow(); |

1073 | assert!( |

1074 | low <= high, |

1075 | "Uniform::new_inclusive called with `low > high`" |

1076 | ); |

1077 | |

1078 | let low_s = low.as_secs(); |

1079 | let low_n = low.subsec_nanos(); |

1080 | let mut high_s = high.as_secs(); |

1081 | let mut high_n = high.subsec_nanos(); |

1082 | |

1083 | if high_n < low_n { |

1084 | high_s -= 1; |

1085 | high_n += 1_000_000_000; |

1086 | } |

1087 | |

1088 | let mode = if low_s == high_s { |

1089 | UniformDurationMode::Small { |

1090 | secs: low_s, |

1091 | nanos: Uniform::new_inclusive(low_n, high_n), |

1092 | } |

1093 | } else { |

1094 | let max = high_s |

1095 | .checked_mul(1_000_000_000) |

1096 | .and_then(|n| n.checked_add(u64::from(high_n))); |

1097 | |

1098 | if let Some(higher_bound) = max { |

1099 | let lower_bound = low_s * 1_000_000_000 + u64::from(low_n); |

1100 | UniformDurationMode::Medium { |

1101 | nanos: Uniform::new_inclusive(lower_bound, higher_bound), |

1102 | } |

1103 | } else { |

1104 | // An offset is applied to simplify generation of nanoseconds |

1105 | let max_nanos = high_n - low_n; |

1106 | UniformDurationMode::Large { |

1107 | max_secs: high_s, |

1108 | max_nanos, |

1109 | secs: Uniform::new_inclusive(low_s, high_s), |

1110 | } |

1111 | } |

1112 | }; |

1113 | UniformDuration { |

1114 | mode, |

1115 | offset: low_n, |

1116 | } |

1117 | } |

1118 | |

1119 | #[inline] |

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

1121 | match self.mode { |

1122 | UniformDurationMode::Small { secs, nanos } => { |

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

1124 | Duration::new(secs, n) |

1125 | } |

1126 | UniformDurationMode::Medium { nanos } => { |

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

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

1129 | } |

1130 | UniformDurationMode::Large { |

1131 | max_secs, |

1132 | max_nanos, |

1133 | secs, |

1134 | } => { |

1135 | // constant folding means this is at least as fast as `Rng::sample(Range)` |

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

1137 | loop { |

1138 | let s = secs.sample(rng); |

1139 | let n = nano_range.sample(rng); |

1140 | if !(s == max_secs && n > max_nanos) { |

1141 | let sum = n + self.offset; |

1142 | break Duration::new(s, sum); |

1143 | } |

1144 | } |

1145 | } |

1146 | } |

1147 | } |

1148 | } |

1149 | |

1150 | #[cfg(test)] |

1151 | mod tests { |

1152 | use super::*; |

1153 | use crate::rngs::mock::StepRng; |

1154 | |

1155 | #[test] |

1156 | #[cfg(feature = "serde1")] |

1157 | fn test_serialization_uniform_duration() { |

1158 | let distr = UniformDuration::new(Duration::from_secs(10), Duration::from_secs(60)); |

1159 | let de_distr: UniformDuration = bincode::deserialize(&bincode::serialize(&distr).unwrap()).unwrap(); |

1160 | assert_eq!( |

1161 | distr.offset, de_distr.offset |

1162 | ); |

1163 | match (distr.mode, de_distr.mode) { |

1164 | (UniformDurationMode::Small {secs: a_secs, nanos: a_nanos}, UniformDurationMode::Small {secs, nanos}) => { |

1165 | assert_eq!(a_secs, secs); |

1166 | |

1167 | assert_eq!(a_nanos.0.low, nanos.0.low); |

1168 | assert_eq!(a_nanos.0.range, nanos.0.range); |

1169 | assert_eq!(a_nanos.0.z, nanos.0.z); |

1170 | } |

1171 | (UniformDurationMode::Medium {nanos: a_nanos} , UniformDurationMode::Medium {nanos}) => { |

1172 | assert_eq!(a_nanos.0.low, nanos.0.low); |

1173 | assert_eq!(a_nanos.0.range, nanos.0.range); |

1174 | assert_eq!(a_nanos.0.z, nanos.0.z); |

1175 | } |

1176 | (UniformDurationMode::Large {max_secs:a_max_secs, max_nanos:a_max_nanos, secs:a_secs}, UniformDurationMode::Large {max_secs, max_nanos, secs} ) => { |

1177 | assert_eq!(a_max_secs, max_secs); |

1178 | assert_eq!(a_max_nanos, max_nanos); |

1179 | |

1180 | assert_eq!(a_secs.0.low, secs.0.low); |

1181 | assert_eq!(a_secs.0.range, secs.0.range); |

1182 | assert_eq!(a_secs.0.z, secs.0.z); |

1183 | } |

1184 | _ => panic!("`UniformDurationMode` was not serialized/deserialized correctly") |

1185 | } |

1186 | } |

1187 | |

1188 | #[test] |

1189 | #[cfg(feature = "serde1")] |

1190 | fn test_uniform_serialization() { |

1191 | let unit_box: Uniform<i32> = Uniform::new(-1, 1); |

1192 | let de_unit_box: Uniform<i32> = bincode::deserialize(&bincode::serialize(&unit_box).unwrap()).unwrap(); |

1193 | |

1194 | assert_eq!(unit_box.0.low, de_unit_box.0.low); |

1195 | assert_eq!(unit_box.0.range, de_unit_box.0.range); |

1196 | assert_eq!(unit_box.0.z, de_unit_box.0.z); |

1197 | |

1198 | let unit_box: Uniform<f32> = Uniform::new(-1., 1.); |

1199 | let de_unit_box: Uniform<f32> = bincode::deserialize(&bincode::serialize(&unit_box).unwrap()).unwrap(); |

1200 | |

1201 | assert_eq!(unit_box.0.low, de_unit_box.0.low); |

1202 | assert_eq!(unit_box.0.scale, de_unit_box.0.scale); |

1203 | } |

1204 | |

1205 | #[should_panic] |

1206 | #[test] |

1207 | fn test_uniform_bad_limits_equal_int() { |

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

1209 | } |

1210 | |

1211 | #[test] |

1212 | fn test_uniform_good_limits_equal_int() { |

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

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

1215 | for _ in 0..20 { |

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

1217 | } |

1218 | } |

1219 | |

1220 | #[should_panic] |

1221 | #[test] |

1222 | fn test_uniform_bad_limits_flipped_int() { |

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

1224 | } |

1225 | |

1226 | #[test] |

1227 | #[cfg_attr(miri, ignore)] // Miri is too slow |

1228 | fn test_integers() { |

1229 | use core::{i128, u128}; |

1230 | use core::{i16, i32, i64, i8, isize}; |

1231 | use core::{u16, u32, u64, u8, usize}; |

1232 | |

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

1234 | macro_rules! t { |

1235 | ($ty:ident, $v:expr, $le:expr, $lt:expr) => {{ |

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

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

1238 | for _ in 0..1000 { |

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

1240 | assert!($le(low, v) && $lt(v, high)); |

1241 | } |

1242 | |

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

1244 | for _ in 0..1000 { |

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

1246 | assert!($le(low, v) && $le(v, high)); |

1247 | } |

1248 | |

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

1250 | for _ in 0..1000 { |

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

1252 | assert!($le(low, v) && $lt(v, high)); |

1253 | } |

1254 | |

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

1256 | for _ in 0..1000 { |

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

1258 | assert!($le(low, v) && $le(v, high)); |

1259 | } |

1260 | |

1261 | for _ in 0..1000 { |

1262 | let v = <$ty as SampleUniform>::Sampler::sample_single(low, high, &mut rng); |

1263 | assert!($le(low, v) && $lt(v, high)); |

1264 | } |

1265 | |

1266 | for _ in 0..1000 { |

1267 | let v = <$ty as SampleUniform>::Sampler::sample_single_inclusive(low, high, &mut rng); |

1268 | assert!($le(low, v) && $le(v, high)); |

1269 | } |

1270 | } |

1271 | }}; |

1272 | |

1273 | // scalar bulk |

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

1275 | $(t!( |

1276 | $ty, |

1277 | [(0, 10), (10, 127), ($ty::MIN, $ty::MAX)], |

1278 | |x, y| x <= y, |

1279 | |x, y| x < y |

1280 | );)* |

1281 | }}; |

1282 | |

1283 | // simd bulk |

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

1285 | $(t!( |

1286 | $ty, |

1287 | [ |

1288 | ($ty::splat(0), $ty::splat(10)), |

1289 | ($ty::splat(10), $ty::splat(127)), |

1290 | ($ty::splat($scalar::MIN), $ty::splat($scalar::MAX)), |

1291 | ], |

1292 | |x: $ty, y| x.le(y).all(), |

1293 | |x: $ty, y| x.lt(y).all() |

1294 | );)* |

1295 | }}; |

1296 | } |

1297 | t!(i8, i16, i32, i64, isize, u8, u16, u32, u64, usize, i128, u128); |

1298 | |

1299 | #[cfg(feature = "simd_support")] |

1300 | { |

1301 | t!(u8x2, u8x4, u8x8, u8x16, u8x32, u8x64 => u8); |

1302 | t!(i8x2, i8x4, i8x8, i8x16, i8x32, i8x64 => i8); |

1303 | t!(u16x2, u16x4, u16x8, u16x16, u16x32 => u16); |

1304 | t!(i16x2, i16x4, i16x8, i16x16, i16x32 => i16); |

1305 | t!(u32x2, u32x4, u32x8, u32x16 => u32); |

1306 | t!(i32x2, i32x4, i32x8, i32x16 => i32); |

1307 | t!(u64x2, u64x4, u64x8 => u64); |

1308 | t!(i64x2, i64x4, i64x8 => i64); |

1309 | } |

1310 | } |

1311 | |

1312 | #[test] |

1313 | #[cfg_attr(miri, ignore)] // Miri is too slow |

1314 | fn test_char() { |

1315 | let mut rng = crate::test::rng(891); |

1316 | let mut max = core::char::from_u32(0).unwrap(); |

1317 | for _ in 0..100 { |

1318 | let c = rng.gen_range('A'..= 'Z'); |

1319 | assert!(('A'..= 'Z').contains(&c)); |

1320 | max = max.max(c); |

1321 | } |

1322 | assert_eq!(max, 'Z'); |

1323 | let d = Uniform::new( |

1324 | core::char::from_u32(0xD7F0).unwrap(), |

1325 | core::char::from_u32(0xE010).unwrap(), |

1326 | ); |

1327 | for _ in 0..100 { |

1328 | let c = d.sample(&mut rng); |

1329 | assert!((c as u32) < 0xD800 || (c as u32) > 0xDFFF); |

1330 | } |

1331 | } |

1332 | |

1333 | #[test] |

1334 | #[cfg_attr(miri, ignore)] // Miri is too slow |

1335 | fn test_floats() { |

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

1337 | let mut zero_rng = StepRng::new(0, 0); |

1338 | let mut max_rng = StepRng::new(0xffff_ffff_ffff_ffff, 0); |

1339 | macro_rules! t { |

1340 | ($ty:ty, $f_scalar:ident, $bits_shifted:expr) => {{ |

1341 | let v: &[($f_scalar, $f_scalar)] = &[ |

1342 | (0.0, 100.0), |

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

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

1345 | (-1e35, 1e35), |

1346 | (<$f_scalar>::from_bits(0), <$f_scalar>::from_bits(3)), |

1347 | (-<$f_scalar>::from_bits(10), -<$f_scalar>::from_bits(1)), |

1348 | (-<$f_scalar>::from_bits(5), 0.0), |

1349 | (-<$f_scalar>::from_bits(7), -0.0), |

1350 | (0.1 * ::core::$f_scalar::MAX, ::core::$f_scalar::MAX), |

1351 | (-::core::$f_scalar::MAX * 0.2, ::core::$f_scalar::MAX * 0.7), |

1352 | ]; |

1353 | for &(low_scalar, high_scalar) in v.iter() { |

1354 | for lane in 0..<$ty>::lanes() { |

1355 | let low = <$ty>::splat(0.0 as $f_scalar).replace(lane, low_scalar); |

1356 | let high = <$ty>::splat(1.0 as $f_scalar).replace(lane, high_scalar); |

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

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

1359 | for _ in 0..100 { |

1360 | let v = rng.sample(my_uniform).extract(lane); |

1361 | assert!(low_scalar <= v && v < high_scalar); |

1362 | let v = rng.sample(my_incl_uniform).extract(lane); |

1363 | assert!(low_scalar <= v && v <= high_scalar); |

1364 | let v = <$ty as SampleUniform>::Sampler |

1365 | ::sample_single(low, high, &mut rng).extract(lane); |

1366 | assert!(low_scalar <= v && v < high_scalar); |

1367 | } |

1368 | |

1369 | assert_eq!( |

1370 | rng.sample(Uniform::new_inclusive(low, low)).extract(lane), |

1371 | low_scalar |

1372 | ); |

1373 | |

1374 | assert_eq!(zero_rng.sample(my_uniform).extract(lane), low_scalar); |

1375 | assert_eq!(zero_rng.sample(my_incl_uniform).extract(lane), low_scalar); |

1376 | assert_eq!(<$ty as SampleUniform>::Sampler |

1377 | ::sample_single(low, high, &mut zero_rng) |

1378 | .extract(lane), low_scalar); |

1379 | assert!(max_rng.sample(my_uniform).extract(lane) < high_scalar); |

1380 | assert!(max_rng.sample(my_incl_uniform).extract(lane) <= high_scalar); |

1381 | |

1382 | // Don't run this test for really tiny differences between high and low |

1383 | // since for those rounding might result in selecting high for a very |

1384 | // long time. |

1385 | if (high_scalar - low_scalar) > 0.0001 { |

1386 | let mut lowering_max_rng = StepRng::new( |

1387 | 0xffff_ffff_ffff_ffff, |

1388 | (-1i64 << $bits_shifted) as u64, |

1389 | ); |

1390 | assert!( |

1391 | <$ty as SampleUniform>::Sampler |

1392 | ::sample_single(low, high, &mut lowering_max_rng) |

1393 | .extract(lane) < high_scalar |

1394 | ); |

1395 | } |

1396 | } |

1397 | } |

1398 | |

1399 | assert_eq!( |

1400 | rng.sample(Uniform::new_inclusive( |

1401 | ::core::$f_scalar::MAX, |

1402 | ::core::$f_scalar::MAX |

1403 | )), |

1404 | ::core::$f_scalar::MAX |

1405 | ); |

1406 | assert_eq!( |

1407 | rng.sample(Uniform::new_inclusive( |

1408 | -::core::$f_scalar::MAX, |

1409 | -::core::$f_scalar::MAX |

1410 | )), |

1411 | -::core::$f_scalar::MAX |

1412 | ); |

1413 | }}; |

1414 | } |

1415 | |

1416 | t!(f32, f32, 32 - 23); |

1417 | t!(f64, f64, 64 - 52); |

1418 | #[cfg(feature = "simd_support")] |

1419 | { |

1420 | t!(f32x2, f32, 32 - 23); |

1421 | t!(f32x4, f32, 32 - 23); |

1422 | t!(f32x8, f32, 32 - 23); |

1423 | t!(f32x16, f32, 32 - 23); |

1424 | t!(f64x2, f64, 64 - 52); |

1425 | t!(f64x4, f64, 64 - 52); |

1426 | t!(f64x8, f64, 64 - 52); |

1427 | } |

1428 | } |

1429 | |

1430 | #[test] |

1431 | #[should_panic] |

1432 | fn test_float_overflow() { |

1433 | let _ = Uniform::from(::core::f64::MIN..::core::f64::MAX); |

1434 | } |

1435 | |

1436 | #[test] |

1437 | #[should_panic] |

1438 | fn test_float_overflow_single() { |

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

1440 | rng.gen_range(::core::f64::MIN..::core::f64::MAX); |

1441 | } |

1442 | |

1443 | #[test] |

1444 | #[cfg(all( |

1445 | feature = "std", |

1446 | not(target_arch = "wasm32"), |

1447 | not(target_arch = "asmjs") |

1448 | ))] |

1449 | fn test_float_assertions() { |

1450 | use super::SampleUniform; |

1451 | use std::panic::catch_unwind; |

1452 | fn range<T: SampleUniform>(low: T, high: T) { |

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

1454 | T::Sampler::sample_single(low, high, &mut rng); |

1455 | } |

1456 | |

1457 | macro_rules! t { |

1458 | ($ty:ident, $f_scalar:ident) => {{ |

1459 | let v: &[($f_scalar, $f_scalar)] = &[ |

1460 | (::std::$f_scalar::NAN, 0.0), |

1461 | (1.0, ::std::$f_scalar::NAN), |

1462 | (::std::$f_scalar::NAN, ::std::$f_scalar::NAN), |

1463 | (1.0, 0.5), |

1464 | (::std::$f_scalar::MAX, -::std::$f_scalar::MAX), |

1465 | (::std::$f_scalar::INFINITY, ::std::$f_scalar::INFINITY), |

1466 | ( |

1467 | ::std::$f_scalar::NEG_INFINITY, |

1468 | ::std::$f_scalar::NEG_INFINITY, |

1469 | ), |

1470 | (::std::$f_scalar::NEG_INFINITY, 5.0), |

1471 | (5.0, ::std::$f_scalar::INFINITY), |

1472 | (::std::$f_scalar::NAN, ::std::$f_scalar::INFINITY), |

1473 | (::std::$f_scalar::NEG_INFINITY, ::std::$f_scalar::NAN), |

1474 | (::std::$f_scalar::NEG_INFINITY, ::std::$f_scalar::INFINITY), |

1475 | ]; |

1476 | for &(low_scalar, high_scalar) in v.iter() { |

1477 | for lane in 0..<$ty>::lanes() { |

1478 | let low = <$ty>::splat(0.0 as $f_scalar).replace(lane, low_scalar); |

1479 | let high = <$ty>::splat(1.0 as $f_scalar).replace(lane, high_scalar); |

1480 | assert!(catch_unwind(|| range(low, high)).is_err()); |

1481 | assert!(catch_unwind(|| Uniform::new(low, high)).is_err()); |

1482 | assert!(catch_unwind(|| Uniform::new_inclusive(low, high)).is_err()); |

1483 | assert!(catch_unwind(|| range(low, low)).is_err()); |

1484 | assert!(catch_unwind(|| Uniform::new(low, low)).is_err()); |

1485 | } |

1486 | } |

1487 | }}; |

1488 | } |

1489 | |

1490 | t!(f32, f32); |

1491 | t!(f64, f64); |

1492 | #[cfg(feature = "simd_support")] |

1493 | { |

1494 | t!(f32x2, f32); |

1495 | t!(f32x4, f32); |

1496 | t!(f32x8, f32); |

1497 | t!(f32x16, f32); |

1498 | t!(f64x2, f64); |

1499 | t!(f64x4, f64); |

1500 | t!(f64x8, f64); |

1501 | } |

1502 | } |

1503 | |

1504 | |

1505 | #[test] |

1506 | #[cfg_attr(miri, ignore)] // Miri is too slow |

1507 | fn test_durations() { |

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

1509 | |

1510 | let v = &[ |

1511 | (Duration::new(10, 50000), Duration::new(100, 1234)), |

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

1513 | ( |

1514 | Duration::new(0, 0), |

1515 | Duration::new(u64::max_value(), 999_999_999), |

1516 | ), |

1517 | ]; |

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

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

1520 | for _ in 0..1000 { |

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

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

1523 | } |

1524 | } |

1525 | } |

1526 | |

1527 | #[test] |

1528 | fn test_custom_uniform() { |

1529 | use crate::distributions::uniform::{ |

1530 | SampleBorrow, SampleUniform, UniformFloat, UniformSampler, |

1531 | }; |

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

1533 | struct MyF32 { |

1534 | x: f32, |

1535 | } |

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

1537 | struct UniformMyF32(UniformFloat<f32>); |

1538 | impl UniformSampler for UniformMyF32 { |

1539 | type X = MyF32; |

1540 | |

1541 | fn new<B1, B2>(low: B1, high: B2) -> Self |

1542 | where |

1543 | B1: SampleBorrow<Self::X> + Sized, |

1544 | B2: SampleBorrow<Self::X> + Sized, |

1545 | { |

1546 | UniformMyF32(UniformFloat::<f32>::new(low.borrow().x, high.borrow().x)) |

1547 | } |

1548 | |

1549 | fn new_inclusive<B1, B2>(low: B1, high: B2) -> Self |

1550 | where |

1551 | B1: SampleBorrow<Self::X> + Sized, |

1552 | B2: SampleBorrow<Self::X> + Sized, |

1553 | { |

1554 | UniformSampler::new(low, high) |

1555 | } |

1556 | |

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

1558 | MyF32 { |

1559 | x: self.0.sample(rng), |

1560 | } |

1561 | } |

1562 | } |

1563 | impl SampleUniform for MyF32 { |

1564 | type Sampler = UniformMyF32; |

1565 | } |

1566 | |

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

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

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

1570 | for _ in 0..100 { |

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

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

1573 | } |

1574 | } |

1575 | |

1576 | #[test] |

1577 | fn test_uniform_from_std_range() { |

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

1579 | assert_eq!(r.0.low, 2); |

1580 | assert_eq!(r.0.range, 5); |

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

1582 | assert_eq!(r.0.low, 2.0); |

1583 | assert_eq!(r.0.scale, 5.0); |

1584 | } |

1585 | |

1586 | #[test] |

1587 | fn test_uniform_from_std_range_inclusive() { |

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

1589 | assert_eq!(r.0.low, 2); |

1590 | assert_eq!(r.0.range, 5); |

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

1592 | assert_eq!(r.0.low, 2.0); |

1593 | assert!(r.0.scale > 5.0); |

1594 | assert!(r.0.scale < 5.0 + 1e-14); |

1595 | } |

1596 | |

1597 | #[test] |

1598 | fn value_stability() { |

1599 | fn test_samples<T: SampleUniform + Copy + core::fmt::Debug + PartialEq>( |

1600 | lb: T, ub: T, expected_single: &[T], expected_multiple: &[T], |

1601 | ) where Uniform<T>: Distribution<T> { |

1602 | let mut rng = crate::test::rng(897); |

1603 | let mut buf = [lb; 3]; |

1604 | |

1605 | for x in &mut buf { |

1606 | *x = T::Sampler::sample_single(lb, ub, &mut rng); |

1607 | } |

1608 | assert_eq!(&buf, expected_single); |

1609 | |

1610 | let distr = Uniform::new(lb, ub); |

1611 | for x in &mut buf { |

1612 | *x = rng.sample(&distr); |

1613 | } |

1614 | assert_eq!(&buf, expected_multiple); |

1615 | } |

1616 | |

1617 | // We test on a sub-set of types; possibly we should do more. |

1618 | // TODO: SIMD types |

1619 | |

1620 | test_samples(11u8, 219, &[17, 66, 214], &[181, 93, 165]); |

1621 | test_samples(11u32, 219, &[17, 66, 214], &[181, 93, 165]); |

1622 | |

1623 | test_samples(0f32, 1e-2f32, &[0.0003070104, 0.0026630748, 0.00979833], &[ |

1624 | 0.008194133, |

1625 | 0.00398172, |

1626 | 0.007428536, |

1627 | ]); |

1628 | test_samples( |

1629 | -1e10f64, |

1630 | 1e10f64, |

1631 | &[-4673848682.871551, 6388267422.932352, 4857075081.198343], |

1632 | &[1173375212.1808167, 1917642852.109581, 2365076174.3153973], |

1633 | ); |

1634 | |

1635 | test_samples( |

1636 | Duration::new(2, 0), |

1637 | Duration::new(4, 0), |

1638 | &[ |

1639 | Duration::new(2, 532615131), |

1640 | Duration::new(3, 638826742), |

1641 | Duration::new(3, 485707508), |

1642 | ], |

1643 | &[ |

1644 | Duration::new(3, 117337521), |

1645 | Duration::new(3, 191764285), |

1646 | Duration::new(3, 236507617), |

1647 | ], |

1648 | ); |

1649 | } |

1650 | |

1651 | #[test] |

1652 | fn uniform_distributions_can_be_compared() { |

1653 | assert_eq!(Uniform::new(1.0, 2.0), Uniform::new(1.0, 2.0)); |

1654 | |

1655 | // To cover UniformInt |

1656 | assert_eq!(Uniform::new(1 as u32, 2 as u32), Uniform::new(1 as u32, 2 as u32)); |

1657 | } |

1658 | } |

1659 |