diff --git a/benches/misc.rs b/benches/misc.rs index 42517617662..0d76489e8a2 100644 --- a/benches/misc.rs +++ b/benches/misc.rs @@ -5,12 +5,12 @@ extern crate rand; use test::{black_box, Bencher}; -use rand::{Rng, weak_rng}; +use rand::{SeedableRng, SmallRng, Rng, thread_rng}; use rand::seq::*; #[bench] fn misc_shuffle_100(b: &mut Bencher) { - let mut rng = weak_rng(); + let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap(); let x : &mut [usize] = &mut [1; 100]; b.iter(|| { rng.shuffle(x); @@ -20,7 +20,7 @@ fn misc_shuffle_100(b: &mut Bencher) { #[bench] fn misc_sample_iter_10_of_100(b: &mut Bencher) { - let mut rng = weak_rng(); + let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap(); let x : &[usize] = &[1; 100]; b.iter(|| { black_box(sample_iter(&mut rng, x, 10).unwrap_or_else(|e| e)); @@ -29,7 +29,7 @@ fn misc_sample_iter_10_of_100(b: &mut Bencher) { #[bench] fn misc_sample_slice_10_of_100(b: &mut Bencher) { - let mut rng = weak_rng(); + let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap(); let x : &[usize] = &[1; 100]; b.iter(|| { black_box(sample_slice(&mut rng, x, 10)); @@ -38,7 +38,7 @@ fn misc_sample_slice_10_of_100(b: &mut Bencher) { #[bench] fn misc_sample_slice_ref_10_of_100(b: &mut Bencher) { - let mut rng = weak_rng(); + let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap(); let x : &[usize] = &[1; 100]; b.iter(|| { black_box(sample_slice_ref(&mut rng, x, 10)); @@ -49,7 +49,7 @@ macro_rules! sample_indices { ($name:ident, $amount:expr, $length:expr) => { #[bench] fn $name(b: &mut Bencher) { - let mut rng = weak_rng(); + let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap(); b.iter(|| { black_box(sample_indices(&mut rng, $length, $amount)); }) diff --git a/src/distributions/exponential.rs b/src/distributions/exponential.rs index b246c3502b1..55b0eb1f0a0 100644 --- a/src/distributions/exponential.rs +++ b/src/distributions/exponential.rs @@ -30,10 +30,10 @@ use distributions::{ziggurat, ziggurat_tables, Distribution}; /// /// # Example /// ```rust -/// use rand::{weak_rng, Rng}; +/// use rand::{NewRng, SmallRng, Rng}; /// use rand::distributions::Exp1; /// -/// let val: f64 = weak_rng().sample(Exp1); +/// let val: f64 = SmallRng::new().unwrap().sample(Exp1); /// println!("{}", val); /// ``` #[derive(Clone, Copy, Debug)] diff --git a/src/distributions/float.rs b/src/distributions/float.rs index 09b27e409bc..1646bfbfa96 100644 --- a/src/distributions/float.rs +++ b/src/distributions/float.rs @@ -49,10 +49,10 @@ macro_rules! float_impls { /// /// # Example /// ```rust - /// use rand::{weak_rng, Rng}; + /// use rand::{NewRng, SmallRng, Rng}; /// use rand::distributions::Uniform; /// - /// let val: f32 = weak_rng().sample(Uniform); + /// let val: f32 = SmallRng::new().unwrap().sample(Uniform); /// println!("f32 from (0,1): {}", val); /// ``` fn sample(&self, rng: &mut R) -> $ty { diff --git a/src/distributions/mod.rs b/src/distributions/mod.rs index f1054b03d74..1f31daa97b4 100644 --- a/src/distributions/mod.rs +++ b/src/distributions/mod.rs @@ -163,10 +163,10 @@ impl<'a, T, D: Distribution> Distribution for &'a D { /// /// # Example /// ```rust -/// use rand::{weak_rng, Rng}; +/// use rand::{NewRng, SmallRng, Rng}; /// use rand::distributions::Uniform; /// -/// let val: f32 = weak_rng().sample(Uniform); +/// let val: f32 = SmallRng::new().unwrap().sample(Uniform); /// println!("f32 from [0,1): {}", val); /// ``` /// diff --git a/src/distributions/normal.rs b/src/distributions/normal.rs index 95d7b29f587..b6f3e1b1904 100644 --- a/src/distributions/normal.rs +++ b/src/distributions/normal.rs @@ -28,10 +28,10 @@ use distributions::{ziggurat, ziggurat_tables, Distribution, Uniform}; /// /// # Example /// ```rust -/// use rand::{weak_rng, Rng}; +/// use rand::{NewRng, SmallRng, Rng}; /// use rand::distributions::StandardNormal; /// -/// let val: f64 = weak_rng().sample(StandardNormal); +/// let val: f64 = SmallRng::new().unwrap().sample(StandardNormal); /// println!("{}", val); /// ``` #[derive(Clone, Copy, Debug)] diff --git a/src/lib.rs b/src/lib.rs index eaacaabf330..7844894de5c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -10,12 +10,11 @@ //! Utilities for random number generation //! -//! The key functions are `random()` and `Rng::gen()`. These are polymorphic and -//! so can be used to generate any type supporting the [`Uniform`] distribution -//! (i.e. `T` where `Uniform`: `Distribution`). Type inference -//! means that often a simple call to `rand::random()` or `rng.gen()` will -//! suffice, but sometimes an annotation is required, e.g. -//! `rand::random::()`. +//! The key function is `Rng::gen()`. It is polymorphic and so can be used to +//! generate any type supporting the [`Uniform`] distribution (i.e. `T` where +//! `Uniform`: `Distribution`). Type inference means that often a simple call +//! to `rng.gen()` will suffice, but sometimes an annotation is required, e.g. +//! `rng.gen::()`. //! //! See the `distributions` submodule for sampling random numbers from //! distributions like normal and exponential. @@ -88,11 +87,6 @@ //! } //! ``` //! -//! ```rust -//! let tuple = rand::random::<(f64, char)>(); -//! println!("{:?}", tuple) -//! ``` -//! //! ## Monte Carlo estimation of π //! //! For this example, imagine we have a square with sides of length 2 and a unit @@ -289,7 +283,8 @@ pub use error::{ErrorKind, Error}; // convenience and derived rngs #[cfg(feature="std")] pub use entropy_rng::EntropyRng; -#[cfg(feature="std")] pub use thread_rng::{ThreadRng, thread_rng, random}; +#[cfg(feature="std")] pub use thread_rng::{ThreadRng, thread_rng}; +#[cfg(feature="std")] #[allow(deprecated)] pub use thread_rng::random; use distributions::{Distribution, Uniform, Range}; use distributions::range::SampleRange; @@ -1091,6 +1086,81 @@ 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 +/// efficient on the current platform, **without consideration for cryptography +/// or security**. The size of its state is much smaller than for `StdRng`. +/// +/// Reproducibility of output from this generator is however not required, thus +/// future library versions may use a different internal generator with +/// different output. Further, this generator may not be portable and can +/// produce different output depending on the architecture. If you require +/// reproducible output, use a named RNG, for example `XorShiftRng`. +/// +/// The current algorithm used on all platforms is [Xorshift]. +/// +/// # Examples +/// +/// Initializing `StdRng` with a random seed can be done using `NewRng`: +/// +/// ``` +/// use rand::{NewRng, SmallRng}; +/// +/// // Create small, cheap to initialize and fast RNG with a random seed. +/// // The randomness is supplied by the operating system. +/// let mut small_rng = SmallRng::new().unwrap(); +/// ``` +/// +/// When initializing a lot of `SmallRng`, using `thread_rng` can be more +/// efficient: +/// +/// ``` +/// use rand::{SeedableRng, SmallRng, thread_rng}; +/// +/// // Create a big, expensive to initialize and slower, but unpredictable RNG. +/// // This is cached and done only once per thread. +/// let mut thread_rng = thread_rng(); +/// // Create small, cheap to initialize and fast RNG with a random seed. +/// // This is very unlikely to fail. +/// let mut small_rng = SmallRng::from_rng(&mut thread_rng).unwrap(); +/// ``` +/// +/// [Xorshift]: struct.XorShiftRng.html +#[derive(Clone, Debug)] +pub struct SmallRng(XorShiftRng); + +impl RngCore for SmallRng { + fn next_u32(&mut self) -> u32 { + self.0.next_u32() + } + + fn next_u64(&mut self) -> u64 { + self.0.next_u64() + } + + fn fill_bytes(&mut self, dest: &mut [u8]) { + self.0.fill_bytes(dest); + } + + fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { + self.0.try_fill_bytes(dest) + } +} + +impl SeedableRng for SmallRng { + type Seed = ::Seed; + + fn from_seed(seed: Self::Seed) -> Self { + SmallRng(XorShiftRng::from_seed(seed)) + } + + fn from_rng(rng: &mut R) -> Result { + XorShiftRng::from_rng(rng).map(|rng| SmallRng(rng)) + } +} + +/// DEPRECATED: use `SmallRng` instead. +/// /// Create a weak random number generator with a default algorithm and seed. /// /// It returns the fastest `Rng` algorithm currently available in Rust without @@ -1099,13 +1169,13 @@ impl SeedableRng for StdRng { /// create the `Rng` yourself. /// /// This will seed the generator with randomness from thread_rng. +#[deprecated(since="0.5.0", note="removed in favor of SmallRng")] #[cfg(feature="std")] pub fn weak_rng() -> XorShiftRng { XorShiftRng::from_rng(&mut thread_rng()).unwrap_or_else(|err| panic!("weak_rng failed: {:?}", err)) } - /// DEPRECATED: use `seq::sample_iter` instead. /// /// Randomly sample up to `amount` elements from a finite iterator. diff --git a/src/thread_rng.rs b/src/thread_rng.rs index fc14cd7325a..70c21d9d98f 100644 --- a/src/thread_rng.rs +++ b/src/thread_rng.rs @@ -13,8 +13,8 @@ use std::cell::RefCell; use std::rc::Rc; -use {RngCore, CryptoRng, StdRng, SeedableRng, EntropyRng}; -use {Distribution, Uniform, Rng, Error}; +use {RngCore, CryptoRng, StdRng, SeedableRng, EntropyRng, Error}; +use {Distribution, Rng, Uniform}; use reseeding::ReseedingRng; // Number of generated bytes after which to reseed `TreadRng`. @@ -99,8 +99,10 @@ impl RngCore for ThreadRng { impl CryptoRng for ThreadRng {} +/// DEPRECATED: use `thread_rng().gen()` instead. +/// /// Generates a random value using the thread-local random number generator. -/// +/// /// This is simply a shortcut for `thread_rng().gen()`. See [`thread_rng`] for /// documentation of the entropy source and [`Rand`] for documentation of /// distributions and type-specific generation. @@ -139,9 +141,10 @@ impl CryptoRng for ThreadRng {} /// *x = rng.gen(); /// } /// ``` -/// +/// /// [`thread_rng`]: fn.thread_rng.html /// [`Rand`]: trait.Rand.html +#[deprecated(since="0.5.0", note="removed in favor of thread_rng().gen()")] #[inline] pub fn random() -> T where Uniform: Distribution { thread_rng().gen() @@ -149,7 +152,7 @@ pub fn random() -> T where Uniform: Distribution { #[cfg(test)] mod test { - use super::*; + use Rng; #[test] #[cfg(feature="std")] @@ -165,7 +168,9 @@ mod test { } #[test] + #[allow(deprecated)] fn test_random() { + use super::random; // not sure how to test this aside from just getting some values let _n : usize = random(); let _f : f32 = random();