1 // Copyright 2018 Developers of the Rand project. 2 // Copyright 2013-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 //! Generating random samples from probability distributions. 11 //! 12 //! This module is the home of the [`Distribution`] trait and several of its 13 //! implementations. It is the workhorse behind some of the convenient 14 //! functionality of the [`Rng`] trait, including [`gen`], [`gen_range`] and 15 //! of course [`sample`]. 16 //! 17 //! Abstractly, a [probability distribution] describes the probability of 18 //! occurance of each value in its sample space. 19 //! 20 //! More concretely, an implementation of `Distribution<T>` for type `X` is an 21 //! algorithm for choosing values from the sample space (a subset of `T`) 22 //! according to the distribution `X` represents, using an external source of 23 //! randomness (an RNG supplied to the `sample` function). 24 //! 25 //! A type `X` may implement `Distribution<T>` for multiple types `T`. 26 //! Any type implementing [`Distribution`] is stateless (i.e. immutable), 27 //! but it may have internal parameters set at construction time (for example, 28 //! [`Uniform`] allows specification of its sample space as a range within `T`). 29 //! 30 //! 31 //! # The `Standard` distribution 32 //! 33 //! The [`Standard`] distribution is important to mention. This is the 34 //! distribution used by [`Rng::gen()`] and represents the "default" way to 35 //! produce a random value for many different types, including most primitive 36 //! types, tuples, arrays, and a few derived types. See the documentation of 37 //! [`Standard`] for more details. 38 //! 39 //! Implementing `Distribution<T>` for [`Standard`] for user types `T` makes it 40 //! possible to generate type `T` with [`Rng::gen()`], and by extension also 41 //! with the [`random()`] function. 42 //! 43 //! 44 //! # Distribution to sample from a `Uniform` range 45 //! 46 //! The [`Uniform`] distribution is more flexible than [`Standard`], but also 47 //! more specialised: it supports fewer target types, but allows the sample 48 //! space to be specified as an arbitrary range within its target type `T`. 49 //! Both [`Standard`] and [`Uniform`] are in some sense uniform distributions. 50 //! 51 //! Values may be sampled from this distribution using [`Rng::gen_range`] or 52 //! by creating a distribution object with [`Uniform::new`], 53 //! [`Uniform::new_inclusive`] or `From<Range>`. When the range limits are not 54 //! known at compile time it is typically faster to reuse an existing 55 //! distribution object than to call [`Rng::gen_range`]. 56 //! 57 //! User types `T` may also implement `Distribution<T>` for [`Uniform`], 58 //! although this is less straightforward than for [`Standard`] (see the 59 //! documentation in the [`uniform`] module. Doing so enables generation of 60 //! values of type `T` with [`Rng::gen_range`]. 61 //! 62 //! 63 //! # Other distributions 64 //! 65 //! There are surprisingly many ways to uniformly generate random floats. A 66 //! range between 0 and 1 is standard, but the exact bounds (open vs closed) 67 //! and accuracy differ. In addition to the [`Standard`] distribution Rand offers 68 //! [`Open01`] and [`OpenClosed01`]. See "Floating point implementation" section of 69 //! [`Standard`] documentation for more details. 70 //! 71 //! [`Alphanumeric`] is a simple distribution to sample random letters and 72 //! numbers of the `char` type; in contrast [`Standard`] may sample any valid 73 //! `char`. 74 //! 75 //! [`WeightedIndex`] can be used to do weighted sampling from a set of items, 76 //! such as from an array. 77 //! 78 //! # Non-uniform probability distributions 79 //! 80 //! Rand currently provides the following probability distributions: 81 //! 82 //! - Related to real-valued quantities that grow linearly 83 //! (e.g. errors, offsets): 84 //! - [`Normal`] distribution, and [`StandardNormal`] as a primitive 85 //! - [`Cauchy`] distribution 86 //! - Related to Bernoulli trials (yes/no events, with a given probability): 87 //! - [`Binomial`] distribution 88 //! - [`Bernoulli`] distribution, similar to [`Rng::gen_bool`]. 89 //! - Related to positive real-valued quantities that grow exponentially 90 //! (e.g. prices, incomes, populations): 91 //! - [`LogNormal`] distribution 92 //! - Related to the occurrence of independent events at a given rate: 93 //! - [`Pareto`] distribution 94 //! - [`Poisson`] distribution 95 //! - [`Exp`]onential distribution, and [`Exp1`] as a primitive 96 //! - [`Weibull`] distribution 97 //! - Gamma and derived distributions: 98 //! - [`Gamma`] distribution 99 //! - [`ChiSquared`] distribution 100 //! - [`StudentT`] distribution 101 //! - [`FisherF`] distribution 102 //! - Triangular distribution: 103 //! - [`Beta`] distribution 104 //! - [`Triangular`] distribution 105 //! - Multivariate probability distributions 106 //! - [`Dirichlet`] distribution 107 //! - [`UnitSphereSurface`] distribution 108 //! - [`UnitCircle`] distribution 109 //! 110 //! # Examples 111 //! 112 //! Sampling from a distribution: 113 //! 114 //! ``` 115 //! use rand::{thread_rng, Rng}; 116 //! use rand::distributions::Exp; 117 //! 118 //! let exp = Exp::new(2.0); 119 //! let v = thread_rng().sample(exp); 120 //! println!("{} is from an Exp(2) distribution", v); 121 //! ``` 122 //! 123 //! Implementing the [`Standard`] distribution for a user type: 124 //! 125 //! ``` 126 //! # #![allow(dead_code)] 127 //! use rand::Rng; 128 //! use rand::distributions::{Distribution, Standard}; 129 //! 130 //! struct MyF32 { 131 //! x: f32, 132 //! } 133 //! 134 //! impl Distribution<MyF32> for Standard { 135 //! fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> MyF32 { 136 //! MyF32 { x: rng.gen() } 137 //! } 138 //! } 139 //! ``` 140 //! 141 //! 142 //! [probability distribution]: https://en.wikipedia.org/wiki/Probability_distribution 143 //! [`gen_range`]: Rng::gen_range 144 //! [`gen`]: Rng::gen 145 //! [`sample`]: Rng::sample 146 //! [`new_inclusive`]: Uniform::new_inclusive 147 //! [`Alphanumeric`]: distributions::Alphanumeric 148 //! [`Bernoulli`]: distributions::Bernoulli 149 //! [`Beta`]: distributions::Beta 150 //! [`Binomial`]: distributions::Binomial 151 //! [`Cauchy`]: distributions::Cauchy 152 //! [`ChiSquared`]: distributions::ChiSquared 153 //! [`Dirichlet`]: distributions::Dirichlet 154 //! [`Exp`]: distributions::Exp 155 //! [`Exp1`]: distributions::Exp1 156 //! [`FisherF`]: distributions::FisherF 157 //! [`Gamma`]: distributions::Gamma 158 //! [`LogNormal`]: distributions::LogNormal 159 //! [`Normal`]: distributions::Normal 160 //! [`Open01`]: distributions::Open01 161 //! [`OpenClosed01`]: distributions::OpenClosed01 162 //! [`Pareto`]: distributions::Pareto 163 //! [`Poisson`]: distributions::Poisson 164 //! [`Standard`]: distributions::Standard 165 //! [`StandardNormal`]: distributions::StandardNormal 166 //! [`StudentT`]: distributions::StudentT 167 //! [`Triangular`]: distributions::Triangular 168 //! [`Uniform`]: distributions::Uniform 169 //! [`Uniform::new`]: distributions::Uniform::new 170 //! [`Uniform::new_inclusive`]: distributions::Uniform::new_inclusive 171 //! [`UnitSphereSurface`]: distributions::UnitSphereSurface 172 //! [`UnitCircle`]: distributions::UnitCircle 173 //! [`Weibull`]: distributions::Weibull 174 //! [`WeightedIndex`]: distributions::WeightedIndex 175 176 #[cfg(any(rustc_1_26, features="nightly"))] 177 use core::iter; 178 use Rng; 179 180 pub use self::other::Alphanumeric; 181 #[doc(inline)] pub use self::uniform::Uniform; 182 pub use self::float::{OpenClosed01, Open01}; 183 pub use self::bernoulli::Bernoulli; 184 #[cfg(feature="alloc")] pub use self::weighted::{WeightedIndex, WeightedError}; 185 #[cfg(feature="std")] pub use self::unit_sphere::UnitSphereSurface; 186 #[cfg(feature="std")] pub use self::unit_circle::UnitCircle; 187 #[cfg(feature="std")] pub use self::gamma::{Gamma, ChiSquared, FisherF, 188 StudentT, Beta}; 189 #[cfg(feature="std")] pub use self::normal::{Normal, LogNormal, StandardNormal}; 190 #[cfg(feature="std")] pub use self::exponential::{Exp, Exp1}; 191 #[cfg(feature="std")] pub use self::pareto::Pareto; 192 #[cfg(feature="std")] pub use self::poisson::Poisson; 193 #[cfg(feature="std")] pub use self::binomial::Binomial; 194 #[cfg(feature="std")] pub use self::cauchy::Cauchy; 195 #[cfg(feature="std")] pub use self::dirichlet::Dirichlet; 196 #[cfg(feature="std")] pub use self::triangular::Triangular; 197 #[cfg(feature="std")] pub use self::weibull::Weibull; 198 199 pub mod uniform; 200 mod bernoulli; 201 #[cfg(feature="alloc")] mod weighted; 202 #[cfg(feature="std")] mod unit_sphere; 203 #[cfg(feature="std")] mod unit_circle; 204 #[cfg(feature="std")] mod gamma; 205 #[cfg(feature="std")] mod normal; 206 #[cfg(feature="std")] mod exponential; 207 #[cfg(feature="std")] mod pareto; 208 #[cfg(feature="std")] mod poisson; 209 #[cfg(feature="std")] mod binomial; 210 #[cfg(feature="std")] mod cauchy; 211 #[cfg(feature="std")] mod dirichlet; 212 #[cfg(feature="std")] mod triangular; 213 #[cfg(feature="std")] mod weibull; 214 215 mod float; 216 mod integer; 217 mod other; 218 mod utils; 219 #[cfg(feature="std")] mod ziggurat_tables; 220 221 /// Types (distributions) that can be used to create a random instance of `T`. 222 /// 223 /// It is possible to sample from a distribution through both the 224 /// `Distribution` and [`Rng`] traits, via `distr.sample(&mut rng)` and 225 /// `rng.sample(distr)`. They also both offer the [`sample_iter`] method, which 226 /// produces an iterator that samples from the distribution. 227 /// 228 /// All implementations are expected to be immutable; this has the significant 229 /// advantage of not needing to consider thread safety, and for most 230 /// distributions efficient state-less sampling algorithms are available. 231 /// 232 /// [`sample_iter`]: Distribution::method.sample_iter 233 pub trait Distribution<T> { 234 /// Generate a random value of `T`, using `rng` as the source of randomness. sample<R: Rng + ?Sized>(&self, rng: &mut R) -> T235 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> T; 236 237 /// Create an iterator that generates random values of `T`, using `rng` as 238 /// the source of randomness. 239 /// 240 /// # Example 241 /// 242 /// ``` 243 /// use rand::thread_rng; 244 /// use rand::distributions::{Distribution, Alphanumeric, Uniform, Standard}; 245 /// 246 /// let mut rng = thread_rng(); 247 /// 248 /// // Vec of 16 x f32: 249 /// let v: Vec<f32> = Standard.sample_iter(&mut rng).take(16).collect(); 250 /// 251 /// // String: 252 /// let s: String = Alphanumeric.sample_iter(&mut rng).take(7).collect(); 253 /// 254 /// // Dice-rolling: 255 /// let die_range = Uniform::new_inclusive(1, 6); 256 /// let mut roll_die = die_range.sample_iter(&mut rng); 257 /// while roll_die.next().unwrap() != 6 { 258 /// println!("Not a 6; rolling again!"); 259 /// } 260 /// ``` sample_iter<'a, R>(&'a self, rng: &'a mut R) -> DistIter<'a, Self, R, T> where Self: Sized, R: Rng261 fn sample_iter<'a, R>(&'a self, rng: &'a mut R) -> DistIter<'a, Self, R, T> 262 where Self: Sized, R: Rng 263 { 264 DistIter { 265 distr: self, 266 rng: rng, 267 phantom: ::core::marker::PhantomData, 268 } 269 } 270 } 271 272 impl<'a, T, D: Distribution<T>> Distribution<T> for &'a D { sample<R: Rng + ?Sized>(&self, rng: &mut R) -> T273 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> T { 274 (*self).sample(rng) 275 } 276 } 277 278 279 /// An iterator that generates random values of `T` with distribution `D`, 280 /// using `R` as the source of randomness. 281 /// 282 /// This `struct` is created by the [`sample_iter`] method on [`Distribution`]. 283 /// See its documentation for more. 284 /// 285 /// [`sample_iter`]: Distribution::sample_iter 286 #[derive(Debug)] 287 pub struct DistIter<'a, D: 'a, R: 'a, T> { 288 distr: &'a D, 289 rng: &'a mut R, 290 phantom: ::core::marker::PhantomData<T>, 291 } 292 293 impl<'a, D, R, T> Iterator for DistIter<'a, D, R, T> 294 where D: Distribution<T>, R: Rng + 'a 295 { 296 type Item = T; 297 298 #[inline(always)] next(&mut self) -> Option<T>299 fn next(&mut self) -> Option<T> { 300 Some(self.distr.sample(self.rng)) 301 } 302 size_hint(&self) -> (usize, Option<usize>)303 fn size_hint(&self) -> (usize, Option<usize>) { 304 (usize::max_value(), None) 305 } 306 } 307 308 #[cfg(rustc_1_26)] 309 impl<'a, D, R, T> iter::FusedIterator for DistIter<'a, D, R, T> 310 where D: Distribution<T>, R: Rng + 'a {} 311 312 #[cfg(features = "nightly")] 313 impl<'a, D, R, T> iter::TrustedLen for DistIter<'a, D, R, T> 314 where D: Distribution<T>, R: Rng + 'a {} 315 316 317 /// A generic random value distribution, implemented for many primitive types. 318 /// Usually generates values with a numerically uniform distribution, and with a 319 /// range appropriate to the type. 320 /// 321 /// ## Built-in Implementations 322 /// 323 /// Assuming the provided `Rng` is well-behaved, these implementations 324 /// generate values with the following ranges and distributions: 325 /// 326 /// * Integers (`i32`, `u32`, `isize`, `usize`, etc.): Uniformly distributed 327 /// over all values of the type. 328 /// * `char`: Uniformly distributed over all Unicode scalar values, i.e. all 329 /// code points in the range `0...0x10_FFFF`, except for the range 330 /// `0xD800...0xDFFF` (the surrogate code points). This includes 331 /// unassigned/reserved code points. 332 /// * `bool`: Generates `false` or `true`, each with probability 0.5. 333 /// * Floating point types (`f32` and `f64`): Uniformly distributed in the 334 /// half-open range `[0, 1)`. See notes below. 335 /// * Wrapping integers (`Wrapping<T>`), besides the type identical to their 336 /// normal integer variants. 337 /// 338 /// The following aggregate types also implement the distribution `Standard` as 339 /// long as their component types implement it: 340 /// 341 /// * Tuples and arrays: Each element of the tuple or array is generated 342 /// independently, using the `Standard` distribution recursively. 343 /// * `Option<T>` where `Standard` is implemented for `T`: Returns `None` with 344 /// probability 0.5; otherwise generates a random `x: T` and returns `Some(x)`. 345 /// 346 /// # Example 347 /// ``` 348 /// use rand::prelude::*; 349 /// use rand::distributions::Standard; 350 /// 351 /// let val: f32 = SmallRng::from_entropy().sample(Standard); 352 /// println!("f32 from [0, 1): {}", val); 353 /// ``` 354 /// 355 /// # Floating point implementation 356 /// The floating point implementations for `Standard` generate a random value in 357 /// the half-open interval `[0, 1)`, i.e. including 0 but not 1. 358 /// 359 /// All values that can be generated are of the form `n * ε/2`. For `f32` 360 /// the 23 most significant random bits of a `u32` are used and for `f64` the 361 /// 53 most significant bits of a `u64` are used. The conversion uses the 362 /// multiplicative method: `(rng.gen::<$uty>() >> N) as $ty * (ε/2)`. 363 /// 364 /// See also: [`Open01`] which samples from `(0, 1)`, [`OpenClosed01`] which 365 /// samples from `(0, 1]` and `Rng::gen_range(0, 1)` which also samples from 366 /// `[0, 1)`. Note that `Open01` and `gen_range` (which uses [`Uniform`]) use 367 /// transmute-based methods which yield 1 bit less precision but may perform 368 /// faster on some architectures (on modern Intel CPUs all methods have 369 /// approximately equal performance). 370 /// 371 /// [`Uniform`]: uniform::Uniform 372 #[derive(Clone, Copy, Debug)] 373 pub struct Standard; 374 375 376 /// A value with a particular weight for use with `WeightedChoice`. 377 #[deprecated(since="0.6.0", note="use WeightedIndex instead")] 378 #[allow(deprecated)] 379 #[derive(Copy, Clone, Debug)] 380 pub struct Weighted<T> { 381 /// The numerical weight of this item 382 pub weight: u32, 383 /// The actual item which is being weighted 384 pub item: T, 385 } 386 387 /// A distribution that selects from a finite collection of weighted items. 388 /// 389 /// Deprecated: use [`WeightedIndex`] instead. 390 /// 391 /// [`WeightedIndex`]: WeightedIndex 392 #[deprecated(since="0.6.0", note="use WeightedIndex instead")] 393 #[allow(deprecated)] 394 #[derive(Debug)] 395 pub struct WeightedChoice<'a, T:'a> { 396 items: &'a mut [Weighted<T>], 397 weight_range: Uniform<u32>, 398 } 399 400 #[deprecated(since="0.6.0", note="use WeightedIndex instead")] 401 #[allow(deprecated)] 402 impl<'a, T: Clone> WeightedChoice<'a, T> { 403 /// Create a new `WeightedChoice`. 404 /// 405 /// Panics if: 406 /// 407 /// - `items` is empty 408 /// - the total weight is 0 409 /// - the total weight is larger than a `u32` can contain. new(items: &'a mut [Weighted<T>]) -> WeightedChoice<'a, T>410 pub fn new(items: &'a mut [Weighted<T>]) -> WeightedChoice<'a, T> { 411 // strictly speaking, this is subsumed by the total weight == 0 case 412 assert!(!items.is_empty(), "WeightedChoice::new called with no items"); 413 414 let mut running_total: u32 = 0; 415 416 // we convert the list from individual weights to cumulative 417 // weights so we can binary search. This *could* drop elements 418 // with weight == 0 as an optimisation. 419 for item in items.iter_mut() { 420 running_total = match running_total.checked_add(item.weight) { 421 Some(n) => n, 422 None => panic!("WeightedChoice::new called with a total weight \ 423 larger than a u32 can contain") 424 }; 425 426 item.weight = running_total; 427 } 428 assert!(running_total != 0, "WeightedChoice::new called with a total weight of 0"); 429 430 WeightedChoice { 431 items, 432 // we're likely to be generating numbers in this range 433 // relatively often, so might as well cache it 434 weight_range: Uniform::new(0, running_total) 435 } 436 } 437 } 438 439 #[deprecated(since="0.6.0", note="use WeightedIndex instead")] 440 #[allow(deprecated)] 441 impl<'a, T: Clone> Distribution<T> for WeightedChoice<'a, T> { sample<R: Rng + ?Sized>(&self, rng: &mut R) -> T442 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> T { 443 // we want to find the first element that has cumulative 444 // weight > sample_weight, which we do by binary since the 445 // cumulative weights of self.items are sorted. 446 447 // choose a weight in [0, total_weight) 448 let sample_weight = self.weight_range.sample(rng); 449 450 // short circuit when it's the first item 451 if sample_weight < self.items[0].weight { 452 return self.items[0].item.clone(); 453 } 454 455 let mut idx = 0; 456 let mut modifier = self.items.len(); 457 458 // now we know that every possibility has an element to the 459 // left, so we can just search for the last element that has 460 // cumulative weight <= sample_weight, then the next one will 461 // be "it". (Note that this greatest element will never be the 462 // last element of the vector, since sample_weight is chosen 463 // in [0, total_weight) and the cumulative weight of the last 464 // one is exactly the total weight.) 465 while modifier > 1 { 466 let i = idx + modifier / 2; 467 if self.items[i].weight <= sample_weight { 468 // we're small, so look to the right, but allow this 469 // exact element still. 470 idx = i; 471 // we need the `/ 2` to round up otherwise we'll drop 472 // the trailing elements when `modifier` is odd. 473 modifier += 1; 474 } else { 475 // otherwise we're too big, so go left. (i.e. do 476 // nothing) 477 } 478 modifier /= 2; 479 } 480 self.items[idx + 1].item.clone() 481 } 482 } 483 484 #[cfg(test)] 485 mod tests { 486 use rngs::mock::StepRng; 487 #[allow(deprecated)] 488 use super::{WeightedChoice, Weighted, Distribution}; 489 490 #[test] 491 #[allow(deprecated)] test_weighted_choice()492 fn test_weighted_choice() { 493 // this makes assumptions about the internal implementation of 494 // WeightedChoice. It may fail when the implementation in 495 // `distributions::uniform::UniformInt` changes. 496 497 macro_rules! t { 498 ($items:expr, $expected:expr) => {{ 499 let mut items = $items; 500 let mut total_weight = 0; 501 for item in &items { total_weight += item.weight; } 502 503 let wc = WeightedChoice::new(&mut items); 504 let expected = $expected; 505 506 // Use extremely large steps between the random numbers, because 507 // we test with small ranges and `UniformInt` is designed to prefer 508 // the most significant bits. 509 let mut rng = StepRng::new(0, !0 / (total_weight as u64)); 510 511 for &val in expected.iter() { 512 assert_eq!(wc.sample(&mut rng), val) 513 } 514 }} 515 } 516 517 t!([Weighted { weight: 1, item: 10}], [10]); 518 519 // skip some 520 t!([Weighted { weight: 0, item: 20}, 521 Weighted { weight: 2, item: 21}, 522 Weighted { weight: 0, item: 22}, 523 Weighted { weight: 1, item: 23}], 524 [21, 21, 23]); 525 526 // different weights 527 t!([Weighted { weight: 4, item: 30}, 528 Weighted { weight: 3, item: 31}], 529 [30, 31, 30, 31, 30, 31, 30]); 530 531 // check that we're binary searching 532 // correctly with some vectors of odd 533 // length. 534 t!([Weighted { weight: 1, item: 40}, 535 Weighted { weight: 1, item: 41}, 536 Weighted { weight: 1, item: 42}, 537 Weighted { weight: 1, item: 43}, 538 Weighted { weight: 1, item: 44}], 539 [40, 41, 42, 43, 44]); 540 t!([Weighted { weight: 1, item: 50}, 541 Weighted { weight: 1, item: 51}, 542 Weighted { weight: 1, item: 52}, 543 Weighted { weight: 1, item: 53}, 544 Weighted { weight: 1, item: 54}, 545 Weighted { weight: 1, item: 55}, 546 Weighted { weight: 1, item: 56}], 547 [50, 54, 51, 55, 52, 56, 53]); 548 } 549 550 #[test] 551 #[allow(deprecated)] test_weighted_clone_initialization()552 fn test_weighted_clone_initialization() { 553 let initial : Weighted<u32> = Weighted {weight: 1, item: 1}; 554 let clone = initial.clone(); 555 assert_eq!(initial.weight, clone.weight); 556 assert_eq!(initial.item, clone.item); 557 } 558 559 #[test] #[should_panic] 560 #[allow(deprecated)] test_weighted_clone_change_weight()561 fn test_weighted_clone_change_weight() { 562 let initial : Weighted<u32> = Weighted {weight: 1, item: 1}; 563 let mut clone = initial.clone(); 564 clone.weight = 5; 565 assert_eq!(initial.weight, clone.weight); 566 } 567 568 #[test] #[should_panic] 569 #[allow(deprecated)] test_weighted_clone_change_item()570 fn test_weighted_clone_change_item() { 571 let initial : Weighted<u32> = Weighted {weight: 1, item: 1}; 572 let mut clone = initial.clone(); 573 clone.item = 5; 574 assert_eq!(initial.item, clone.item); 575 576 } 577 578 #[test] #[should_panic] 579 #[allow(deprecated)] test_weighted_choice_no_items()580 fn test_weighted_choice_no_items() { 581 WeightedChoice::<isize>::new(&mut []); 582 } 583 #[test] #[should_panic] 584 #[allow(deprecated)] test_weighted_choice_zero_weight()585 fn test_weighted_choice_zero_weight() { 586 WeightedChoice::new(&mut [Weighted { weight: 0, item: 0}, 587 Weighted { weight: 0, item: 1}]); 588 } 589 #[test] #[should_panic] 590 #[allow(deprecated)] test_weighted_choice_weight_overflows()591 fn test_weighted_choice_weight_overflows() { 592 let x = ::core::u32::MAX / 2; // x + x + 2 is the overflow 593 WeightedChoice::new(&mut [Weighted { weight: x, item: 0 }, 594 Weighted { weight: 1, item: 1 }, 595 Weighted { weight: x, item: 2 }, 596 Weighted { weight: 1, item: 3 }]); 597 } 598 599 #[cfg(feature="std")] 600 #[test] test_distributions_iter()601 fn test_distributions_iter() { 602 use distributions::Normal; 603 let mut rng = ::test::rng(210); 604 let distr = Normal::new(10.0, 10.0); 605 let results: Vec<_> = distr.sample_iter(&mut rng).take(100).collect(); 606 println!("{:?}", results); 607 } 608 } 609