diff --git a/benches/generators.rs b/benches/generators.rs index 525831376e6..16bd6d56af9 100644 --- a/benches/generators.rs +++ b/benches/generators.rs @@ -9,7 +9,8 @@ const BYTES_LEN: usize = 1024; use std::mem::size_of; use test::{black_box, Bencher}; -use rand::{RngCore, Rng, SeedableRng, NewRng, StdRng, OsRng, JitterRng, EntropyRng}; +use rand::{RngCore, Rng, SeedableRng, NewRng}; +use rand::{StdRng, SmallRng, OsRng, JitterRng, EntropyRng}; use rand::{XorShiftRng, Hc128Rng, IsaacRng, Isaac64Rng, ChaChaRng}; use rand::reseeding::ReseedingRng; use rand::prng::hc128::Hc128Core; @@ -37,6 +38,7 @@ gen_bytes!(gen_bytes_hc128, Hc128Rng::new()); gen_bytes!(gen_bytes_isaac, IsaacRng::new()); gen_bytes!(gen_bytes_isaac64, Isaac64Rng::new()); gen_bytes!(gen_bytes_std, StdRng::new()); +gen_bytes!(gen_bytes_small, SmallRng::new()); gen_bytes!(gen_bytes_os, OsRng::new().unwrap()); macro_rules! gen_uint { @@ -61,6 +63,7 @@ gen_uint!(gen_u32_hc128, u32, Hc128Rng::new()); gen_uint!(gen_u32_isaac, u32, IsaacRng::new()); gen_uint!(gen_u32_isaac64, u32, Isaac64Rng::new()); gen_uint!(gen_u32_std, u32, StdRng::new()); +gen_uint!(gen_u32_small, u32, SmallRng::new()); gen_uint!(gen_u32_os, u32, OsRng::new().unwrap()); gen_uint!(gen_u64_xorshift, u64, XorShiftRng::new()); @@ -68,6 +71,7 @@ gen_uint!(gen_u64_hc128, u64, Hc128Rng::new()); gen_uint!(gen_u64_isaac, u64, IsaacRng::new()); gen_uint!(gen_u64_isaac64, u64, Isaac64Rng::new()); gen_uint!(gen_u64_std, u64, StdRng::new()); +gen_uint!(gen_u64_small, u64, SmallRng::new()); gen_uint!(gen_u64_os, u64, OsRng::new().unwrap()); // Do not test JitterRng like the others by running it RAND_BENCH_N times per, diff --git a/benches/misc.rs b/benches/misc.rs index 0d76489e8a2..ccb10fdb9bb 100644 --- a/benches/misc.rs +++ b/benches/misc.rs @@ -3,11 +3,39 @@ extern crate test; extern crate rand; +const RAND_BENCH_N: u64 = 1000; + use test::{black_box, Bencher}; use rand::{SeedableRng, SmallRng, Rng, thread_rng}; use rand::seq::*; +#[bench] +fn misc_gen_bool(b: &mut Bencher) { + let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap(); + b.iter(|| { + let mut accum = true; + for _ in 0..::RAND_BENCH_N { + accum ^= rng.gen_bool(0.18); + } + black_box(accum); + }) +} + +#[bench] +fn misc_gen_bool_var(b: &mut Bencher) { + let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap(); + b.iter(|| { + let mut p = 0.18; + let mut accum = true; + for _ in 0..::RAND_BENCH_N { + accum ^= rng.gen_bool(p); + p += 0.0001; + } + black_box(accum); + }) +} + #[bench] fn misc_shuffle_100(b: &mut Bencher) { let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap(); diff --git a/src/distributions/binomial.rs b/src/distributions/binomial.rs index 8599be03bfd..1b4d2194dca 100644 --- a/src/distributions/binomial.rs +++ b/src/distributions/binomial.rs @@ -64,7 +64,7 @@ impl Distribution for Binomial { if expected < 25.0 { let mut lresult = 0.0; for _ in 0 .. self.n { - if rng.gen::() < p { + if rng.gen_bool(p) { lresult += 1.0; } } diff --git a/src/lib.rs b/src/lib.rs index e7df3f414b3..651a44d2082 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -521,6 +521,7 @@ pub trait Rng: RngCore { /// # Example /// /// ```rust + /// #[allow(deprecated)] /// use rand::{thread_rng, Rng}; /// /// let mut rng = thread_rng(); @@ -532,11 +533,29 @@ pub trait Rng: RngCore { /// // First meaningful use of `gen_weighted_bool`. /// println!("{}", rng.gen_weighted_bool(3)); /// ``` + #[deprecated(since="0.5.0", note="use gen_bool instead")] fn gen_weighted_bool(&mut self, n: u32) -> bool { // Short-circuit after `n <= 1` to avoid panic in `gen_range` n <= 1 || self.gen_range(0, n) == 0 } + /// Return a bool with a probability `p` of being true. + /// + /// # Example + /// + /// ```rust + /// use rand::{thread_rng, Rng}; + /// + /// let mut rng = thread_rng(); + /// println!("{}", rng.gen_bool(1.0 / 3.0)); + /// ``` + fn gen_bool(&mut self, p: f64) -> bool { + assert!(p >= 0.0 && p <= 1.0); + // If `p` is constant, this will be evaluated at compile-time. + let p_int = (p * core::u32::MAX as f64) as u32; + self.gen::() <= p_int + } + /// Return an iterator of random characters from the set A-Z,a-z,0-9. /// /// # Example @@ -798,7 +817,7 @@ impl NewRng for R { } } -/// The standard RNG. The PRNG algorithm in `StdRng` is choosen to be efficient +/// The standard RNG. The PRNG algorithm in `StdRng` is chosen to be efficient /// on the current platform, to be statistically strong and unpredictable /// (meaning a cryptographically secure PRNG). /// @@ -847,7 +866,7 @@ impl SeedableRng for StdRng { } /// An RNG recommended when small state, cheap initialization and good -/// performance are required. The PRNG algorithm in `SmallRng` is choosen to be +/// performance are required. The PRNG algorithm in `SmallRng` is chosen to be /// efficient on the current platform, **without consideration for cryptography /// or security**. The size of its state is much smaller than for `StdRng`. /// @@ -890,10 +909,12 @@ impl SeedableRng for StdRng { pub struct SmallRng(XorShiftRng); impl RngCore for SmallRng { + #[inline(always)] fn next_u32(&mut self) -> u32 { self.0.next_u32() } + #[inline(always)] fn next_u64(&mut self) -> u64 { self.0.next_u64() } @@ -1076,12 +1097,22 @@ mod test { } #[test] + #[allow(deprecated)] fn test_gen_weighted_bool() { let mut r = rng(104); assert_eq!(r.gen_weighted_bool(0), true); assert_eq!(r.gen_weighted_bool(1), true); } + #[test] + fn test_gen_bool() { + let mut r = rng(105); + for _ in 0..5 { + assert_eq!(r.gen_bool(0.0), false); + assert_eq!(r.gen_bool(1.0), true); + } + } + #[test] fn test_choose() { let mut r = rng(107);