diff --git a/src/distributions/default.rs b/src/distributions/default.rs index 054598e774..fab58fae08 100644 --- a/src/distributions/default.rs +++ b/src/distributions/default.rs @@ -11,8 +11,8 @@ //! Generic value creation use Rng; -use distributions::{Distribution, Rand}; -use distributions::uniform::{Uniform, Uniform01, codepoint}; +use distributions::Distribution; +use distributions::uniform::{Uniform, Uniform01, Codepoint}; /// A generic random value distribution. Generates values using what appears to /// be "the best" distribution for each type, but ultimately the choice is arbitrary. @@ -21,10 +21,7 @@ use distributions::uniform::{Uniform, Uniform01, codepoint}; /// /// * [`Uniform`] for integer types /// * [`Uniform01`] for floating point types -/// -/// Makes use of the following methods: -/// -/// * [`codepoint`] for `char` +/// * [`Codepoint`] for `char` /// /// TODO: link #[derive(Debug)] @@ -32,56 +29,53 @@ pub struct Default; // ----- implementations ----- -impl> Distribution for Default { +impl Distribution for Default where Uniform: Distribution{ fn sample(&self, rng: &mut R) -> T { - T::rand(rng, Uniform) + Uniform.sample(rng) } } // FIXME: https://github.com/rust-lang/rust/issues/23341 -// impl> Distribution for Default { +// impl Distribution for Default where Uniform01: Distribution{ // fn sample(&self, rng: &mut R) -> T { -// T::rand(rng, Uniform01) +// Uniform01.sample(rng) // } // } // workaround above issue: impl Distribution for Default { fn sample(&self, rng: &mut R) -> f32 { - f32::rand(rng, Uniform01) + Uniform01.sample(rng) } } impl Distribution for Default { fn sample(&self, rng: &mut R) -> f64 { - f64::rand(rng, Uniform01) + Uniform01.sample(rng) } } impl Distribution for Default { fn sample(&self, rng: &mut R) -> char { - codepoint(rng) + Codepoint.sample(rng) } } #[cfg(test)] mod tests { - use {Rng, thread_rng}; - use distributions::{Rand, Default}; + use {Rng, Sample, thread_rng}; + use distributions::{Default}; #[test] fn test_types() { let rng: &mut Rng = &mut thread_rng(); - fn do_test>(rng: &mut Rng) -> T { - T::rand(rng, Default) - } - do_test::(rng); - do_test::(rng); - do_test::(rng); - do_test::(rng); + rng.sample::(Default); + rng.sample::(Default); + rng.sample::(Default); + rng.sample::(Default); #[cfg(feature = "i128_support")] - do_test::(rng); - do_test::(rng); - do_test::(rng); + rng.sample::(Default); + rng.sample::(Default); + rng.sample::(Default); } } diff --git a/src/distributions/exponential.rs b/src/distributions/exponential.rs index be8616391e..48a988dee3 100644 --- a/src/distributions/exponential.rs +++ b/src/distributions/exponential.rs @@ -11,7 +11,7 @@ //! The exponential distribution. use {Rng}; -use distributions::{ziggurat, ziggurat_tables, Distribution, Uniform01, Rand}; +use distributions::{ziggurat, ziggurat_tables, Distribution, Uniform01}; /// Generates Exp(1) random numbers. /// @@ -43,7 +43,7 @@ pub fn exp1(rng: &mut R) -> f64 { } #[inline] fn zero_case(rng: &mut R, _u: f64) -> f64 { - let x = f64::rand(rng, Uniform01); + let x: f64 = Uniform01.sample(rng); ziggurat_tables::ZIG_EXP_R - x.ln() } diff --git a/src/distributions/gamma.rs b/src/distributions/gamma.rs index 93f1a4835c..5ddbc1cc6c 100644 --- a/src/distributions/gamma.rs +++ b/src/distributions/gamma.rs @@ -17,7 +17,7 @@ use self::ChiSquaredRepr::*; use {Rng}; use distributions::normal::standard_normal; -use distributions::{Distribution, Exp, Rand, Open01}; +use distributions::{Distribution, Exp, Open01}; /// The Gamma distribution `Gamma(shape, scale)` distribution. /// @@ -145,7 +145,7 @@ impl Distribution for Gamma { } impl Distribution for GammaSmallShape { fn sample(&self, rng: &mut R) -> f64 { - let u = f64::rand(rng, Open01); + let u: f64 = Open01.sample(rng); self.large_shape.sample(rng) * u.powf(self.inv_shape) } @@ -160,7 +160,7 @@ impl Distribution for GammaLargeShape { } let v = v_cbrt * v_cbrt * v_cbrt; - let u = f64::rand(rng, Open01); + let u: f64 = Open01.sample(rng); let x_sqr = x * x; if u < 1.0 - 0.0331 * x_sqr * x_sqr || diff --git a/src/distributions/mod.rs b/src/distributions/mod.rs index e0523cb93f..6db1a5af15 100644 --- a/src/distributions/mod.rs +++ b/src/distributions/mod.rs @@ -18,8 +18,7 @@ use Rng; pub use self::default::Default; -pub use self::uniform::{uniform, codepoint, ascii_word_char}; -pub use self::uniform::{Uniform, Uniform01, Open01, Closed01, AsciiWordChar}; +pub use self::uniform::{Uniform, Uniform01, Open01, Closed01, Codepoint, AsciiWordChar}; pub use self::range::Range; #[cfg(feature="std")] @@ -77,55 +76,26 @@ impl<'a, T, D: Distribution> Distribution for &'a D { } } -/// Generic trait for sampling random values from some distribution +/// Trait for sampling values from the `Default` distribution. /// -/// TODO: quite possibly remove both this and `SimpleRand` since `Sample` is -/// more convenient and distributions like `Default` handle all the real work. +/// This is mostly a shim around `Default` for backwards compatibility; the +/// implementation is simply `Default.sample(rng)`. /// /// # Example /// ```rust -/// use rand::distributions::{Rand, Default, Range}; +/// use rand::{Rand, thread_rng}; /// -/// let mut rng = rand::thread_rng(); -/// println!("Random byte: {}", u8::rand(&mut rng, Default)); -/// println!("Random range: {}", i32::rand(&mut rng, Range::new(-99, 100))); -/// ``` -pub trait Rand { - /// Generate a random value of the given type, according to the specified - /// distribution. - /// - /// The distributions `Default` (or `Uniform` and `Uniform01`) and `Range` - /// should cover most simpler usages; `Normal`, `LogNormal`, `Exp`, `Gamma` - /// and a few others are also available. - fn rand(rng: &mut R, distr: D) -> Self; -} - -impl> Rand for T { - fn rand(rng: &mut R, distr: D) -> Self { - distr.sample(rng) - } -} - -/// Simpler version of `Rand`, without support for alternative distributions. -/// -/// TODO: decide which version of `Rand` to keep. If this one, rename struct to -/// `Rand` and function to `rand`. -/// -/// # Example -/// ```rust -/// use rand::distributions::SimpleRand; -/// -/// let mut rng = rand::thread_rng(); -/// println!("Random byte: {}", u8::simple_rand(&mut rng)); +/// let mut rng = thread_rng(); +/// println!("Random byte: {}", u8::rand(&mut rng)); /// ``` -pub trait SimpleRand { +pub trait Rand : Sized { /// Generate a random value of the given type, using the `Default` /// distribution. - fn simple_rand(rng: &mut R) -> Self; + fn rand(rng: &mut R) -> Self; } -impl SimpleRand for T where Default: Distribution { - fn simple_rand(rng: &mut R) -> Self { +impl Rand for T where Default: Distribution { + fn rand(rng: &mut R) -> Self { Default.sample(rng) } } @@ -165,7 +135,7 @@ fn ziggurat( // precision of using 64 bits for f64 does not buy us much. // Because for some RNG's the least significant bits can be of lower // statistical quality, we use bits 3..10 for i. - let bits: u64 = uniform(rng); + let bits: u64 = rng.sample(Uniform); // u is either U(-1, 1) or U(0, 1) depending on if this is a // symmetric distribution or not. @@ -190,7 +160,7 @@ fn ziggurat( return zero_case(rng, u); } // algebraically equivalent to f1 + DRanU()*(f0 - f1) < 1 - if f_tab[i + 1] + (f_tab[i] - f_tab[i + 1]) * f64::rand(rng, Uniform01) < pdf(x) { + if f_tab[i + 1] + (f_tab[i] - f_tab[i + 1]) * rng.sample::(Uniform01) < pdf(x) { return x; } } diff --git a/src/distributions/normal.rs b/src/distributions/normal.rs index 6cda325df4..92664b94a1 100644 --- a/src/distributions/normal.rs +++ b/src/distributions/normal.rs @@ -11,7 +11,7 @@ //! The normal and derived distributions. use {Rng}; -use distributions::{ziggurat, ziggurat_tables, Distribution, Rand, Open01}; +use distributions::{ziggurat, ziggurat_tables, Distribution, Open01}; /// Generates N(0, 1) random numbers /// (a.k.a. a standard normal, or Gaussian). @@ -50,8 +50,8 @@ pub fn standard_normal(rng: &mut R) -> f64 { let mut y = 0.0f64; while -2.0 * y < x * x { - let x_ = f64::rand(rng, Open01); - let y_ = f64::rand(rng, Open01); + let x_: f64 = Open01.sample(rng); + let y_: f64 = Open01.sample(rng); x = x_.ln() / ziggurat_tables::ZIG_NORM_R; y = y_.ln(); diff --git a/src/distributions/range.rs b/src/distributions/range.rs index e99010f130..9120028de8 100644 --- a/src/distributions/range.rs +++ b/src/distributions/range.rs @@ -10,7 +10,6 @@ //! A distribution generating numbers within a given range. -use Rand; use Rng; use distributions::{Distribution, Uniform}; use utils::FloatConversions; @@ -262,7 +261,7 @@ macro_rules! range_int_impl { // casting is a no-op. let zone = self.zone as $signed as $i_large as $u_large; loop { - let v: $u_large = Rand::rand(rng, Uniform); + let v: $u_large = Uniform.sample(rng); if $use_mult { let (hi, lo) = v.wmul(range); if lo <= zone { @@ -276,7 +275,7 @@ macro_rules! range_int_impl { } } else { // Sample from the entire integer range. - Rand::rand(rng, Uniform) + Uniform.sample(rng) } } @@ -297,7 +296,7 @@ macro_rules! range_int_impl { }; loop { - let v: $u_large = Rand::rand(rng, Uniform); + let v: $u_large = Uniform.sample(rng); if $use_mult { let (hi, lo) = v.wmul(range); if lo <= zone { @@ -553,8 +552,8 @@ range_float_impl! { f64, Rng::next_u64 } #[cfg(test)] mod tests { - use {Rng, thread_rng}; - use distributions::{Rand, Distribution}; + use {Rng, Sample, thread_rng}; + use distributions::{Distribution}; use distributions::range::{Range, RangeImpl, RangeFloat, SampleRange}; #[test] @@ -612,7 +611,7 @@ mod tests { for &(low, high) in v.iter() { let my_range = Range::new(low, high); for _ in 0..1000 { - let v: $ty = Rand::rand(&mut rng, my_range); + let v: $ty = rng.sample(my_range); assert!(low <= v && v < high); } } @@ -638,7 +637,7 @@ mod tests { for &(low, high) in v.iter() { let my_range = Range::new(low, high); for _ in 0..1000 { - let v: $ty = Rand::rand(&mut rng, my_range); + let v: $ty = rng.sample(my_range); assert!(low <= v && v < high); } } @@ -681,7 +680,7 @@ mod tests { let range = Range::new(low, high); let mut rng = ::test::rng(); for _ in 0..100 { - let x = MyF32::rand(&mut rng, range); + let x: MyF32 = rng.sample(range); assert!(low <= x && x < high); } } diff --git a/src/distributions/uniform.rs b/src/distributions/uniform.rs index 13aaa4620c..afda3ddbc1 100644 --- a/src/distributions/uniform.rs +++ b/src/distributions/uniform.rs @@ -14,60 +14,9 @@ use core::char; use core::mem; use Rng; -use distributions::{Distribution, Rand}; +use distributions::Distribution; use utils::FloatConversions; -// ----- convenience functions ----- - -/// Sample values uniformly over the whole range supported by the type -/// -/// This method has precisely two template parameters. To fix the output type, -/// use the syntax `uniform::(rng)`. -pub fn uniform, R: Rng+?Sized>(rng: &mut R) -> T { - T::rand(rng, Uniform) -} - -/// Sample a `char`, uniformly distributed over all Unicode scalar values, -/// i.e. all code points in the range `0...0x10_FFFF`, except for the range -/// `0xD800...0xDFFF` (the surrogate code points). This includes -/// unassigned/reserved code points. -/// -/// TODO: should this be removed in favour of a distribution? -#[inline] -pub fn codepoint(rng: &mut R) -> char { - // a char is 21 bits - const CHAR_MASK: u32 = 0x001f_ffff; - loop { - // Rejection sampling. About 0.2% of numbers with at most - // 21-bits are invalid codepoints (surrogates), so this - // will succeed first go almost every time. - match char::from_u32(rng.next_u32() & CHAR_MASK) { - Some(c) => return c, - None => {} - } - } -} - -/// Sample a `char`, uniformly distributed over ASCII letters and numbers: -/// a-z, A-Z and 0-9. -/// -/// TODO: should this be removed in favour of `AsciiWordChar`? -#[inline] -pub fn ascii_word_char(rng: &mut R) -> char { - const RANGE: u32 = 26 + 26 + 10; - const GEN_ASCII_STR_CHARSET: &'static [u8] = - b"ABCDEFGHIJKLMNOPQRSTUVWXYZ\ - abcdefghijklmnopqrstuvwxyz\ - 0123456789"; - loop { - let var = rng.next_u32() & 0x3F; - if var < RANGE { - return GEN_ASCII_STR_CHARSET[var as usize] as char - } - } -} - - // ----- Sampling distributions ----- /// Sample values uniformly over the whole range supported by the type @@ -86,7 +35,15 @@ pub struct Open01; #[derive(Debug)] pub struct Closed01; -/// Sample values uniformly from the ASCII ranges z-a, A-Z, and 0-9. +/// Sample a `char`, uniformly distributed over all Unicode scalar values, +/// i.e. all code points in the range `0...0x10_FFFF`, except for the range +/// `0xD800...0xDFFF` (the surrogate code points). This includes +/// unassigned/reserved code points. +#[derive(Debug)] +pub struct Codepoint; + +/// Sample a `char`, uniformly distributed over ASCII letters and numbers: +/// a-z, A-Z and 0-9. #[derive(Debug)] pub struct AsciiWordChar; @@ -95,10 +52,12 @@ pub struct AsciiWordChar; impl Distribution for Uniform { fn sample(&self, rng: &mut R) -> isize { - if mem::size_of::() == 4 { - i32::rand(rng, Uniform) as isize + if mem::size_of::() <= 4 { + rng.next_u32() as isize + } else if mem::size_of::() == 8 { + rng.next_u64() as isize } else { - i64::rand(rng, Uniform) as isize + unreachable!() } } } @@ -142,10 +101,12 @@ impl Distribution for Uniform { impl Distribution for Uniform { #[inline] fn sample(&self, rng: &mut R) -> usize { - if mem::size_of::() == 4 { - u32::rand(rng, Uniform) as usize + if mem::size_of::() <= 4 { + rng.next_u32() as usize + } else if mem::size_of::() == 8 { + rng.next_u64() as usize } else { - u64::rand(rng, Uniform) as usize + unreachable!() } } } @@ -243,60 +204,83 @@ float_impls! { f32, Rng::next_u32 } float_impls! { f64, Rng::next_u64 } +impl Distribution for Codepoint { + fn sample(&self, rng: &mut R) -> char { + // a char is 21 bits + const CHAR_MASK: u32 = 0x001f_ffff; + loop { + // Rejection sampling. About 0.2% of numbers with at most + // 21-bits are invalid codepoints (surrogates), so this + // will succeed first go almost every time. + match char::from_u32(rng.next_u32() & CHAR_MASK) { + Some(c) => return c, + None => {} + } + } + } +} + impl Distribution for AsciiWordChar { fn sample(&self, rng: &mut R) -> char { - ascii_word_char(rng) + const RANGE: u32 = 26 + 26 + 10; + const GEN_ASCII_STR_CHARSET: &'static [u8] = + b"ABCDEFGHIJKLMNOPQRSTUVWXYZ\ + abcdefghijklmnopqrstuvwxyz\ + 0123456789"; + loop { + let var = rng.next_u32() & 0x3F; + if var < RANGE { + return GEN_ASCII_STR_CHARSET[var as usize] as char + } + } } } #[cfg(test)] mod tests { - use {thread_rng, iter}; - use distributions::{Rand, uniform, Uniform, Uniform01, Open01, Closed01}; - use distributions::uniform::{codepoint, ascii_word_char}; + use {Sample, thread_rng, iter}; + use distributions::{Uniform, Uniform01, Open01, Closed01, + Codepoint, AsciiWordChar}; #[test] fn test_integers() { let mut rng = ::test::rng(); - let _: i32 = Rand::rand(&mut rng, Uniform); - let _ = i32::rand(&mut rng, Uniform); - - let _: isize = uniform(&mut rng); - let _: i8 = uniform(&mut rng); - let _: i16 = uniform(&mut rng); - let _: i32 = uniform(&mut rng); - let _: i64 = uniform(&mut rng); + rng.sample::(Uniform); + rng.sample::(Uniform); + rng.sample::(Uniform); + rng.sample::(Uniform); + rng.sample::(Uniform); #[cfg(feature = "i128_support")] - let _: i128 = uniform(&mut rng); + rng.sample::(Uniform); - let _: usize = uniform(&mut rng); - let _: u8 = uniform(&mut rng); - let _: u16 = uniform(&mut rng); - let _: u32 = uniform(&mut rng); - let _: u64 = uniform(&mut rng); + rng.sample::(Uniform); + rng.sample::(Uniform); + rng.sample::(Uniform); + rng.sample::(Uniform); + rng.sample::(Uniform); #[cfg(feature = "i128_support")] - let _: u128 = uniform(&mut rng); + rng.sample::(Uniform); } #[test] fn test_chars() { let mut rng = ::test::rng(); - let _ = codepoint(&mut rng); - let c = ascii_word_char(&mut rng); + let _ = rng.sample(Codepoint); + let c = rng.sample(AsciiWordChar); assert!((c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')); - let word: String = iter(&mut rng).take(5).map(|rng| ascii_word_char(rng)).collect(); + let word: String = iter(&mut rng).take(5).map(|rng| rng.sample(AsciiWordChar)).collect(); assert_eq!(word.len(), 5); } #[test] fn test_f64() { - let mut r = thread_rng(); - let a: f64 = Rand::rand(&mut r, Uniform01); - let b = f64::rand(&mut r, Uniform01); + let mut rng = thread_rng(); + let a: f64 = rng.sample(Uniform01); + let b = rng.sample::(Uniform01); assert!(0.0 <= a && a < 1.0); assert!(0.0 <= b && b < 1.0); } @@ -308,10 +292,10 @@ mod tests { let mut rng = thread_rng(); for _ in 0..1_000 { // strict inequalities - let f = f64::rand(&mut rng, Open01); + let f: f64 = rng.sample(Open01); assert!(0.0 < f && f < 1.0); - let f = f32::rand(&mut rng, Open01); + let f: f32 = rng.sample(Open01); assert!(0.0 < f && f < 1.0); } } @@ -321,10 +305,10 @@ mod tests { let mut rng = thread_rng(); for _ in 0..1_000 { // strict inequalities - let f = f64::rand(&mut rng, Closed01); + let f: f64 = rng.sample(Closed01); assert!(0.0 <= f && f <= 1.0); - let f = f32::rand(&mut rng, Closed01); + let f: f32 = rng.sample(Closed01); assert!(0.0 <= f && f <= 1.0); } } diff --git a/src/iter.rs b/src/iter.rs index a819d33cdf..1d44d2c9d0 100644 --- a/src/iter.rs +++ b/src/iter.rs @@ -36,14 +36,14 @@ pub struct Iter<'a, R: Rng+?Sized+'a> { /// # Example /// /// ``` -/// use rand::{thread_rng, Rng, iter}; -/// use rand::distributions::{uniform, ascii_word_char}; +/// use rand::{thread_rng, Rng, Sample, iter}; +/// use rand::distributions::{Uniform, AsciiWordChar}; /// /// let mut rng = thread_rng(); -/// let x: Vec = iter(&mut rng).take(10).map(|rng| uniform(rng)).collect(); +/// let x: Vec = iter(&mut rng).take(10).map(|rng| rng.sample(Uniform)).collect(); /// println!("{:?}", x); /// -/// let w: String = iter(&mut rng).take(6).map(|rng| ascii_word_char(rng)).collect(); +/// let w: String = iter(&mut rng).take(6).map(|rng| rng.sample(AsciiWordChar)).collect(); /// println!("{}", w); /// ``` pub fn iter<'a, R: Rng+?Sized+'a>(rng: &'a mut R) -> Iter<'a, R> { @@ -159,8 +159,8 @@ impl<'a, R:?Sized+'a, U, F> Iterator for FlatMap<'a, R, U, F> #[cfg(test)] mod tests { - use {Rng, thread_rng, iter}; - use distributions::{uniform, ascii_word_char}; + use {Rng, Sample, thread_rng, iter}; + use distributions::{Uniform, AsciiWordChar}; #[test] fn test_iter() { @@ -168,10 +168,10 @@ mod tests { let x: Vec<()> = iter(&mut rng).take(10).map(|_| ()).collect(); assert_eq!(x.len(), 10); - let y: Vec = iter(&mut rng).take(10).map(|rng| uniform(rng)).collect(); + let y: Vec = iter(&mut rng).take(10).map(|rng| rng.sample(Uniform)).collect(); assert_eq!(y.len(), 10); let z: Vec = iter(&mut rng).take(10).flat_map(|rng| - vec![uniform(rng), uniform(rng)].into_iter()).collect(); + vec![rng.sample(Uniform), rng.sample(Uniform)].into_iter()).collect(); assert_eq!(z.len(), 20); let w: Vec = iter(&mut rng).take(10).flat_map(|_| vec![].into_iter()).collect(); assert_eq!(w.len(), 0); @@ -181,7 +181,7 @@ mod tests { fn test_dyn_dispatch() { let r: &mut Rng = &mut thread_rng(); - let x: String = iter(r).take(10).map(|rng| ascii_word_char(rng)).collect(); + let x: String = iter(r).take(10).map(|rng| rng.sample(AsciiWordChar)).collect(); assert_eq!(x.len(), 10); } } diff --git a/src/lib.rs b/src/lib.rs index 4f336131e9..fcc0e18078 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -86,10 +86,10 @@ //! ``` //! //! ```rust -//! use rand::thread_rng; -//! use rand::distributions::{Rand, Uniform, Uniform01}; +//! use rand::{Sample, thread_rng}; +//! use rand::distributions::{Uniform, Uniform01}; //! let mut rng = thread_rng(); -//! let tuple = (f64::rand(&mut rng, Uniform01), u8::rand(&mut rng, Uniform)); +//! let tuple: (f64, u8) = (rng.sample(Uniform01), rng.sample(Uniform)); //! println!("{:?}", tuple) //! ``` //! @@ -111,18 +111,19 @@ //! and multiply this fraction by 4. //! //! ``` -//! use rand::distributions::{Rand, Range}; +//! use rand::{thread_rng, Sample}; +//! use rand::distributions::{Range}; //! //! fn main() { //! let between = Range::new(-1f64, 1.); -//! let mut rng = rand::thread_rng(); +//! let mut rng = thread_rng(); //! //! let total = 1_000_000; //! let mut in_circle = 0; //! //! for _ in 0..total { -//! let a = f64::rand(&mut rng, between); -//! let b = f64::rand(&mut rng, between); +//! let a = rng.sample(between); +//! let b = rng.sample(between); //! if a*a + b*b <= 1. { //! in_circle += 1; //! } @@ -153,8 +154,8 @@ //! [Monty Hall Problem]: http://en.wikipedia.org/wiki/Monty_Hall_problem //! //! ``` -//! use rand::Rng; -//! use rand::distributions::{Distribution, Range, uniform}; +//! use rand::{Rng, Sample}; +//! use rand::distributions::{Distribution, Range}; //! use rand::distributions::range::RangeInt; //! use rand::sequences::Choose; //! @@ -175,7 +176,7 @@ //! let open = game_host_open(car, choice, rng); //! //! // Shall we switch? -//! let switch = uniform(rng); +//! let switch = rng.gen(); //! if switch { //! choice = switch_door(choice, open); //! } @@ -490,8 +491,7 @@ impl SeedFromRng for StdRng { #[cfg(test)] mod test { use {Rng, thread_rng, Sample, Error}; - use mock::MockAddRng; - use distributions::{uniform}; + use mock::MockAddRng; use distributions::{Uniform, Range, Exp}; use sequences::Shuffle; use std::iter::repeat; @@ -562,7 +562,7 @@ mod test { #[test] fn test_thread_rng() { let mut r = thread_rng(); - uniform::(&mut r); + r.sample::(Uniform); let mut v = [1, 1, 1]; v.shuffle(&mut r); let b: &[_] = &[1, 1, 1]; @@ -576,7 +576,7 @@ mod test { { let r = &mut rng as &mut Rng; r.next_u32(); - uniform::(r); + r.sample::(Uniform); let mut v = [1, 1, 1]; v[..].shuffle(r); let b: &[_] = &[1, 1, 1]; @@ -586,7 +586,7 @@ mod test { { let mut r = Box::new(rng) as Box; r.next_u32(); - uniform::(&mut r); + r.sample::(Uniform); let mut v = [1, 1, 1]; v[..].shuffle(&mut *r); let b: &[_] = &[1, 1, 1]; diff --git a/src/read.rs b/src/read.rs index 772d83e722..c4a41bbbd1 100644 --- a/src/read.rs +++ b/src/read.rs @@ -26,11 +26,11 @@ use {Rng, Error, ErrorKind}; /// # Example /// /// ```rust -/// use rand::{ReadRng, distributions}; +/// use rand::{Rng, ReadRng, distributions}; /// /// let data = vec![1, 2, 3, 4, 5, 6, 7, 8]; /// let mut rng = ReadRng::new(&data[..]); -/// println!("{:x}", distributions::uniform::(&mut rng)); +/// println!("{:x}", rng.next_u32()); /// ``` #[derive(Debug)] // Do not derive Clone, because it could share the underlying reader diff --git a/src/thread_local.rs b/src/thread_local.rs index 0d7348ec24..fe5b9e4619 100644 --- a/src/thread_local.rs +++ b/src/thread_local.rs @@ -13,7 +13,7 @@ use std::cell::RefCell; use std::rc::Rc; -use {Rng, StdRng, NewSeeded, Rand, Default, Error}; +use {Rng, StdRng, NewSeeded, Distribution, Default, Sample, Error}; use reseeding::{ReseedingRng, ReseedWithNew}; @@ -100,7 +100,7 @@ pub fn thread_rng() -> ThreadRng { /// Caching the thread local random number generator: /// /// ``` -/// use rand::{Rand, Default}; +/// use rand::{Sample}; /// /// let mut v = vec![1, 2, 3]; /// @@ -113,15 +113,12 @@ pub fn thread_rng() -> ThreadRng { /// let mut rng = rand::thread_rng(); /// /// for x in v.iter_mut() { -/// *x = Rand::rand(&mut rng, Default); +/// *x = rng.gen() /// } /// ``` -/// -/// Note that the above example uses `SampleDefault` which is a zero-sized -/// marker type. #[inline] -pub fn random>() -> T { - T::rand(&mut thread_rng(), Default) +pub fn random() -> T where Default: Distribution { + thread_rng().sample(Default) } /// Generates a random value using the thread-local random number generator. @@ -130,8 +127,8 @@ pub fn random>() -> T { /// distribution used. For example: /// /// ``` -/// use rand::random_with; -/// use rand::distributions::{Rand, Default, Uniform01, Closed01, Range}; +/// use rand::{Sample, random_with}; +/// use rand::distributions::{Default, Uniform01, Closed01, Range}; /// /// // identical to calling `random()`: /// let x: f64 = random_with(Default); @@ -150,9 +147,9 @@ pub fn random>() -> T { /// let mut rng = rand::thread_rng(); /// let range = Range::new(0.0, 2.0); /// // Do this bit many times: -/// let v = f64::rand(&mut rng, range); +/// let v = rng.sample(range); /// ``` #[inline] -pub fn random_with>(distribution: D) -> T { - T::rand(&mut thread_rng(), distribution) +pub fn random_with(distribution: D) -> T where D: Distribution { + thread_rng().sample(distribution) } diff --git a/src/utils.rs b/src/utils.rs index 406d721b56..e6ed5ecbf1 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -10,7 +10,7 @@ //! A collection of utility functions //! -//! This module exposes some utility functions used internally by the `Rand` +//! This module exposes some utility functions used internally by the `rand` //! crate. They are not the intended or most ergonomic way to use the library. //! //! The `FloatConversions` trait provides the building blocks to convert a @@ -271,7 +271,8 @@ float_impls! { f64, u64, 64, 52, 0xf_ffff_ffff_ffff, 1023, Rng::next_u64 } #[cfg(test)] mod tests { use super::FloatConversions; - use distributions::uniform; + use Sample; + use distributions::Uniform; #[test] fn closed_open01_edge_cases() { @@ -315,14 +316,14 @@ mod tests { // These constants happen to generate the lowest and highest floats in // the range. let mut rng = ::test::rng(); - let mut bits: u32 = uniform(&mut rng); + let mut bits: u32 = rng.sample(Uniform); bits = bits & 0x1ff; // 9 bits with no influence assert!((bits | 0).closed_open01_fixed() == 0.0); assert!((bits | 0xfffffe00).closed_open01_fixed() == 0.9999999); // 1 - 2^-23 - let mut bits: u64 = uniform(&mut rng); + let mut bits: u64 = rng.sample(Uniform); bits = bits & 0xfff; // 12 bits with no influence assert!((bits | 0).closed_open01_fixed() == 0.0); @@ -336,13 +337,13 @@ mod tests { // These constants happen to generate the lowest and highest floats in // the range. let mut rng = ::test::rng(); - let mut bits: u32 = uniform(&mut rng); + let mut bits: u32 = rng.sample(Uniform); bits = bits & 0x1ff; // 9 bits with no influence assert!((bits | 0).open_closed01_fixed() == 1.1920929e-7); // 2^-23 assert!((bits | 0xfffffe00).open_closed01_fixed() == 1.0); - let mut bits: u64 = uniform(&mut rng); + let mut bits: u64 = rng.sample(Uniform); bits = bits & 0xfff; // 12 bits with no influence assert!((bits | 0).open_closed01_fixed() == @@ -356,14 +357,14 @@ mod tests { // These constants happen to generate the lowest and highest floats in // the range. let mut rng = ::test::rng(); - let mut bits: u32 = uniform(&mut rng); + let mut bits: u32 = rng.sample(Uniform); bits = bits & 0x1ff; // 9 bits with no influence assert!((bits | 0).closed_open11_fixed() == -1.0); assert!((bits | 0xfffffe00).closed_open11_fixed() == 0.99999976); // 1 - 2^-22 - let mut bits: u64 = uniform(&mut rng); + let mut bits: u64 = rng.sample(Uniform); bits = bits & 0xfff; // 12 bits with no influence assert!((bits | 0).closed_open11_fixed() == -1.0);