Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion benches/generators.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const BYTES_LEN: usize = 1024;
use std::mem::size_of;
use test::{black_box, Bencher};

use rand::{Rng, NewRng, StdRng, OsRng, JitterRng};
use rand::{Rng, SampleRng, NewRng, StdRng, OsRng, JitterRng};
use rand::{XorShiftRng, Hc128Rng, IsaacRng, Isaac64Rng, ChaChaRng};

macro_rules! gen_bytes {
Expand Down
2 changes: 1 addition & 1 deletion benches/misc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ extern crate rand;

use test::{black_box, Bencher};

use rand::{Rng, weak_rng};
use rand::{SampleRng, weak_rng};
use rand::seq::*;

#[bench]
Expand Down
2 changes: 1 addition & 1 deletion rand-derive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ fn impl_rand_derive(ast: &syn::MacroInput) -> quote::Tokens {
quote! {
impl #impl_generics ::rand::Rand for #name #ty_generics #where_clause {
#[inline]
fn rand<__R: ::rand::Rng>(__rng: &mut __R) -> Self {
fn rand<__R: ::rand::SampleRng>(__rng: &mut __R) -> Self {
#rand
}
}
Expand Down
2 changes: 1 addition & 1 deletion rand-derive/tests/rand_macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ extern crate rand;
#[macro_use]
extern crate rand_derive;

use rand::Rng;
use rand::SampleRng;

#[derive(Rand)]
struct Struct {
Expand Down
2 changes: 1 addition & 1 deletion src/distributions/exponential.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

//! The exponential distribution.

use {Rng, Rand};
use {Rng, SampleRng, Rand};
use distributions::{ziggurat, ziggurat_tables, Sample, IndependentSample};

/// A wrapper around an `f64` to generate Exp(1) random numbers.
Expand Down
2 changes: 1 addition & 1 deletion src/distributions/gamma.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
use self::GammaRepr::*;
use self::ChiSquaredRepr::*;

use {Rng, Open01};
use {Rng, SampleRng, Open01};
use super::normal::StandardNormal;
use super::{IndependentSample, Sample, Exp};

Expand Down
2 changes: 1 addition & 1 deletion src/distributions/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

use core::marker;

use {Rng, Rand};
use {Rng, SampleRng, Rand};

pub use self::range::Range;
#[cfg(feature="std")]
Expand Down
2 changes: 1 addition & 1 deletion src/distributions/normal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

//! The normal and derived distributions.

use {Rng, Rand, Open01};
use {Rng, SampleRng, Rand, Open01};
use distributions::{ziggurat, ziggurat_tables, Sample, IndependentSample};

/// A wrapper around an `f64` to generate N(0, 1) random numbers
Expand Down
2 changes: 1 addition & 1 deletion src/distributions/range.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

use core::num::Wrapping as w;

use Rng;
use {Rng, SampleRng};
use distributions::{Sample, IndependentSample};

/// Sample values uniformly between two bounds.
Expand Down
100 changes: 72 additions & 28 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@
//! # Examples
//!
//! ```rust
//! use rand::Rng;
//! use rand::SampleRng;
//!
//! let mut rng = rand::thread_rng();
//! if rng.gen() { // random bool
Expand Down Expand Up @@ -152,7 +152,7 @@
//! [Monty Hall Problem]: https://en.wikipedia.org/wiki/Monty_Hall_problem
//!
//! ```
//! use rand::Rng;
//! use rand::SampleRng;
//! use rand::distributions::{IndependentSample, Range};
//!
//! struct SimulationResult {
Expand All @@ -161,7 +161,7 @@
//! }
//!
//! // Run a single simulation of the Monty Hall problem.
//! fn simulate<R: Rng>(random_door: &Range<u32>, rng: &mut R)
//! fn simulate<R: SampleRng>(random_door: &Range<u32>, rng: &mut R)
//! -> SimulationResult {
//! let car = random_door.ind_sample(rng);
//!
Expand All @@ -182,7 +182,7 @@
//!
//! // Returns the door the game host opens given our choice and knowledge of
//! // where the car is. The game host will never open the door with the car.
//! fn game_host_open<R: Rng>(car: u32, choice: u32, rng: &mut R) -> u32 {
//! fn game_host_open<R: SampleRng>(car: u32, choice: u32, rng: &mut R) -> u32 {
//! let choices = free_doors(&[car, choice]);
//! rand::seq::sample_slice(rng, &choices, 1)[0]
//! }
Expand Down Expand Up @@ -346,6 +346,21 @@ pub trait Rand : Sized {
}

/// A random number generator.
///
/// This trait encapsulates the low-level functionality common to all
/// generators, and is the "back end", to be implemented by generators.
/// Several extension traits exist:
///
/// * [`SampleRng`] provides high-level generic functionality built on top of
/// `Rng`
/// * [`SeedableRng`] is another "back end" trait covering creation and
/// seeding of algorithmic RNGs (PRNGs)
/// * [`NewRng`] is a high-level trait providing a convenient way to create
/// freshly-seeded PRNGs
///
/// [`SampleRng`]: trait.SampleRng.html
/// [`SeedableRng`]: trait.SeedableRng.html
/// [`NewRng`]: trait.NewRng.html
pub trait Rng {
/// Return the next random `u32`.
///
Expand Down Expand Up @@ -473,21 +488,36 @@ pub trait Rng {
fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
Ok(self.fill_bytes(dest))
}
}

/// An automatically-implemented extension trait on [`Rng`] providing high-level
/// generic methods for sampling values and other convenience methods.
///
/// Users should "use" this trait to enable its extension methods on [`Rng`]
/// or require this type directly (i.e. `<R: SampleRng>`). Since `SampleRng`
/// extends `Rng` and every `Rng` implements `SampleRng`, usage of the two
/// traits is somewhat interchangeable.
///
/// This functionality is provided as an extension trait to allow separation
/// between the backend (the [`Rng`] providing randomness) and the front-end
/// (converting that randomness to the desired type and distribution).
///
/// [`Rng`]: trait.Rng.html
pub trait SampleRng: Rng + Sized {
/// Return a random value of a `Rand` type.
///
/// # Example
///
/// ```rust
/// use rand::{thread_rng, Rng};
/// use rand::{thread_rng, SampleRng};
///
/// let mut rng = thread_rng();
/// let x: u32 = rng.gen();
/// println!("{}", x);
/// println!("{:?}", rng.gen::<(f64, bool)>());
/// ```
#[inline(always)]
fn gen<T: Rand>(&mut self) -> T where Self: Sized {
fn gen<T: Rand>(&mut self) -> T {
Rand::rand(self)
}

Expand All @@ -497,15 +527,15 @@ pub trait Rng {
/// # Example
///
/// ```
/// use rand::{thread_rng, Rng};
/// use rand::{thread_rng, SampleRng};
///
/// let mut rng = thread_rng();
/// let x = rng.gen_iter::<u32>().take(10).collect::<Vec<u32>>();
/// println!("{:?}", x);
/// println!("{:?}", rng.gen_iter::<(f64, bool)>().take(5)
/// .collect::<Vec<(f64, bool)>>());
/// ```
fn gen_iter<'a, T: Rand>(&'a mut self) -> Generator<'a, T, Self> where Self: Sized {
fn gen_iter<'a, T: Rand>(&'a mut self) -> Generator<'a, T, Self> {
Generator { rng: self, _marker: marker::PhantomData }
}

Expand All @@ -524,16 +554,16 @@ pub trait Rng {
/// # Example
///
/// ```rust
/// use rand::{thread_rng, Rng};
/// use rand::{thread_rng, SampleRng};
///
/// let mut rng = thread_rng();
/// let n: u32 = rng.gen_range(0, 10);
/// println!("{}", n);
/// let m: f64 = rng.gen_range(-40.0f64, 1.3e5f64);
/// println!("{}", m);
/// ```
fn gen_range<T: PartialOrd + SampleRange>(&mut self, low: T, high: T) -> T where Self: Sized {
assert!(low < high, "Rng.gen_range called with low >= high");
fn gen_range<T: PartialOrd + SampleRange>(&mut self, low: T, high: T) -> T {
assert!(low < high, "SampleRng::gen_range called with low >= high");
Range::new(low, high).ind_sample(self)
}

Expand All @@ -542,12 +572,12 @@ pub trait Rng {
/// # Example
///
/// ```rust
/// use rand::{thread_rng, Rng};
/// use rand::{thread_rng, SampleRng};
///
/// let mut rng = thread_rng();
/// println!("{}", rng.gen_weighted_bool(3));
/// ```
fn gen_weighted_bool(&mut self, n: u32) -> bool where Self: Sized {
fn gen_weighted_bool(&mut self, n: u32) -> bool {
n <= 1 || self.gen_range(0, n) == 0
}

Expand All @@ -556,12 +586,12 @@ pub trait Rng {
/// # Example
///
/// ```rust
/// use rand::{thread_rng, Rng};
/// use rand::{thread_rng, SampleRng};
///
/// let s: String = thread_rng().gen_ascii_chars().take(10).collect();
/// println!("{}", s);
/// ```
fn gen_ascii_chars<'a>(&'a mut self) -> AsciiGenerator<'a, Self> where Self: Sized {
fn gen_ascii_chars<'a>(&'a mut self) -> AsciiGenerator<'a, Self> {
AsciiGenerator { rng: self }
}

Expand All @@ -572,14 +602,14 @@ pub trait Rng {
/// # Example
///
/// ```
/// use rand::{thread_rng, Rng};
/// use rand::{thread_rng, SampleRng};
///
/// let choices = [1, 2, 4, 8, 16, 32];
/// let mut rng = thread_rng();
/// println!("{:?}", rng.choose(&choices));
/// assert_eq!(rng.choose(&choices[..0]), None);
/// ```
fn choose<'a, T>(&mut self, values: &'a [T]) -> Option<&'a T> where Self: Sized {
fn choose<'a, T>(&mut self, values: &'a [T]) -> Option<&'a T> {
if values.is_empty() {
None
} else {
Expand All @@ -590,7 +620,7 @@ pub trait Rng {
/// Return a mutable pointer to a random element from `values`.
///
/// Return `None` if `values` is empty.
fn choose_mut<'a, T>(&mut self, values: &'a mut [T]) -> Option<&'a mut T> where Self: Sized {
fn choose_mut<'a, T>(&mut self, values: &'a mut [T]) -> Option<&'a mut T> {
if values.is_empty() {
None
} else {
Expand All @@ -607,7 +637,7 @@ pub trait Rng {
/// # Example
///
/// ```rust
/// use rand::{thread_rng, Rng};
/// use rand::{thread_rng, SampleRng};
///
/// let mut rng = thread_rng();
/// let mut y = [1, 2, 3];
Expand All @@ -616,7 +646,7 @@ pub trait Rng {
/// rng.shuffle(&mut y);
/// println!("{:?}", y);
/// ```
fn shuffle<T>(&mut self, values: &mut [T]) where Self: Sized {
fn shuffle<T>(&mut self, values: &mut [T]) {
let mut i = values.len();
while i >= 2 {
// invariant: elements with index >= i have been locked in place.
Expand All @@ -627,6 +657,8 @@ pub trait Rng {
}
}

impl<R: Rng> SampleRng for R {}

impl<'a, R: ?Sized> Rng for &'a mut R where R: Rng {
#[inline]
fn next_u32(&mut self) -> u32 {
Expand Down Expand Up @@ -737,7 +769,15 @@ impl<'a, R: Rng> Iterator for AsciiGenerator<'a, R> {

/// A random number generator that can be explicitly seeded.
///
/// Each pseudo-random number generator (PRNG) should implement this.
/// This trait encapsulates the low-level functionality common to all
/// pseudo-random number generators (PRNGs, or algorithmic generators).
///
/// Normally users should use the [`NewRng`] extension trait, excepting when a
/// fixed seed must be used, in which case usage of [`SeedableRng::from_seed`]
/// is recommended.
///
/// [`NewRng`]: trait.NewRng.html
/// [`SeedableRng::from_seed`]: #tymethod.from_seed
pub trait SeedableRng: Sized {
/// Seed type, which is restricted to types mutably-dereferencable as `u8`
/// arrays (we recommend `[u8; N]` for some `N`).
Expand Down Expand Up @@ -767,8 +807,12 @@ pub trait SeedableRng: Sized {

/// Create a new PRNG seeded from another `Rng`.
///
/// This is the recommended way to initialize PRNGs. The [`NewRng`] trait
/// provides a convenient new method based on `from_rng`.
/// This is the recommended way to initialize PRNGs with fresh entropy. The
/// [`NewRng`] trait provides a convenient new method based on `from_rng`.
///
/// Usage of this method is not recommended when reproducibility is required
/// since implementing PRNGs are not required to fix Endianness and are
/// allowed to modify implementations in new releases.
///
/// It is important to use a good source of randomness to initialize the
/// PRNG. Cryptographic PRNG may be rendered insecure when seeded from a
Expand All @@ -789,7 +833,6 @@ pub trait SeedableRng: Sized {
///
/// PRNG implementations are allowed to assume that a good RNG is provided
/// for seeding, and that it is cryptographically secure when appropriate.
/// There are no reproducibility requirements like endianness conversion.
///
/// [`NewRng`]: trait.NewRng.html
/// [`OsRng`]: os/struct.OsRng.html
Expand All @@ -806,21 +849,22 @@ pub trait SeedableRng: Sized {
/// pseudo-random number generators (PRNGs).
///
/// This is the recommended way to create PRNGs, unless a deterministic seed is
/// desired (in which case `SeedableRng::from_seed` should be used).
/// desired (in which case [`SeedableRng::from_seed`] should be used).
///
/// Note: this trait is automatically implemented for any PRNG implementing
/// [`SeedableRng`] and is not intended to be implemented by users.
///
/// ## Example
///
/// ```
/// use rand::{StdRng, Rng, NewRng};
/// use rand::{StdRng, SampleRng, NewRng};
///
/// let mut rng = StdRng::new().unwrap();
/// println!("Random die roll: {}", rng.gen_range(1, 7));
/// ```
///
/// [`SeedableRng`]: trait.SeedableRng.html
/// [`SeedableRng::from_seed`]: trait.SeedableRng.html#tymethod.from_seed
#[cfg(feature="std")]
pub trait NewRng: SeedableRng {
/// Creates a new instance, automatically seeded with fresh entropy.
Expand Down Expand Up @@ -1032,7 +1076,7 @@ impl Rng for ThreadRng {
/// Caching the thread local random number generator:
///
/// ```
/// use rand::Rng;
/// use rand::SampleRng;
///
/// let mut v = vec![1, 2, 3];
///
Expand Down Expand Up @@ -1085,7 +1129,7 @@ mod test {
use impls;
#[cfg(feature="std")]
use super::{random, thread_rng};
use super::{Rng, SeedableRng, StdRng};
use super::{Rng, SampleRng, SeedableRng, StdRng};
#[cfg(feature="alloc")]
use alloc::boxed::Box;

Expand Down
4 changes: 2 additions & 2 deletions src/rand_impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

use core::{char, mem};

use {Rand, Rng, SeedableRng};
use {Rand, Rng, SampleRng, SeedableRng};

impl Rand for isize {
#[inline]
Expand Down Expand Up @@ -255,7 +255,7 @@ impl<T: SeedableRng> Rand for T {
#[cfg(test)]
mod tests {
use impls;
use {Rng, Open01, Closed01};
use {Rng, SampleRng, Open01, Closed01};

struct ConstantRng(u64);
impl Rng for ConstantRng {
Expand Down
Loading