Skip to content

Commit

Permalink
Deprecate Rng::sample and Rng::sample_iter in favor of Distribution::…
Browse files Browse the repository at this point in the history
…sample and Distribution::sample_iter
  • Loading branch information
sicking committed Jul 13, 2018
1 parent b9cc581 commit 89ec7b4
Show file tree
Hide file tree
Showing 14 changed files with 127 additions and 170 deletions.
6 changes: 3 additions & 3 deletions benches/misc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ fn misc_bernoulli_const(b: &mut Bencher) {
let d = rand::distributions::Bernoulli::new(0.18);
let mut accum = true;
for _ in 0..::RAND_BENCH_N {
accum ^= rng.sample(d);
accum ^= d.sample(&mut rng);
}
accum
})
Expand All @@ -80,7 +80,7 @@ fn misc_bernoulli_var(b: &mut Bencher) {
let mut p = 0.18;
for _ in 0..::RAND_BENCH_N {
let d = rand::distributions::Bernoulli::new(p);
accum ^= rng.sample(d);
accum ^= d.sample(&mut rng);
p += 0.0001;
}
accum
Expand All @@ -95,7 +95,7 @@ macro_rules! sample_binomial {
let (n, p) = ($n, $p);
b.iter(|| {
let d = rand::distributions::Binomial::new(n, p);
rng.sample(d)
d.sample(&mut rng)
})
}
}
Expand Down
7 changes: 2 additions & 5 deletions src/distributions/bernoulli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,6 @@ impl Distribution<bool> for Bernoulli {

#[cfg(test)]
mod test {
use Rng;
use distributions::Distribution;
use super::Bernoulli;

Expand All @@ -130,10 +129,8 @@ mod test {
let always_false = Bernoulli::new(0.0);
let always_true = Bernoulli::new(1.0);
for _ in 0..5 {
assert_eq!(r.sample::<bool, _>(&always_false), false);
assert_eq!(r.sample::<bool, _>(&always_true), true);
assert_eq!(Distribution::<bool>::sample(&always_false, &mut r), false);
assert_eq!(Distribution::<bool>::sample(&always_true, &mut r), true);
assert_eq!(always_false.sample(&mut r), false);
assert_eq!(always_true.sample(&mut r), true);
}
}

Expand Down
8 changes: 4 additions & 4 deletions src/distributions/binomial.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ impl Distribution<u64> for Binomial {
let mut result = 0;
let d = Bernoulli::new(self.p);
for _ in 0 .. self.n {
result += rng.sample(d) as u32;
result += d.sample(rng) as u32;
}
return result as u64;
}
Expand Down Expand Up @@ -96,7 +96,7 @@ impl Distribution<u64> for Binomial {
let mut comp_dev: f64;
loop {
// draw from the Cauchy distribution
comp_dev = rng.sample(cauchy);
comp_dev = cauchy.sample(rng);
// shift the peak of the comparison ditribution
lresult = expected + sq * comp_dev;
// repeat the drawing until we are in the range of possible values
Expand Down Expand Up @@ -166,8 +166,8 @@ mod test {
#[test]
fn test_binomial_end_points() {
let mut rng = ::test::rng(352);
assert_eq!(rng.sample(Binomial::new(20, 0.0)), 0);
assert_eq!(rng.sample(Binomial::new(20, 1.0)), 20);
assert_eq!(Binomial::new(20, 0.0).sample(&mut rng), 0);
assert_eq!(Binomial::new(20, 1.0).sample(&mut rng), 20);
}

#[test]
Expand Down
4 changes: 2 additions & 2 deletions src/distributions/exponential.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ use distributions::utils::ziggurat;
/// use rand::prelude::*;
/// use rand::distributions::Exp1;
///
/// let val: f64 = SmallRng::from_entropy().sample(Exp1);
/// let val: f64 = Exp1.sample(&mut SmallRng::from_entropy());
/// println!("{}", val);
/// ```
#[derive(Clone, Copy, Debug)]
Expand Down Expand Up @@ -92,7 +92,7 @@ impl Exp {

impl Distribution<f64> for Exp {
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> f64 {
let n: f64 = rng.sample(Exp1);
let n: f64 = Exp1.sample(rng);
n * self.lambda_inverse
}
}
Expand Down
88 changes: 31 additions & 57 deletions src/distributions/float.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,10 @@ use core::simd::*;
///
/// # Example
/// ```
/// use rand::{thread_rng, Rng};
/// use rand::prelude::*;
/// use rand::distributions::OpenClosed01;
///
/// let val: f32 = thread_rng().sample(OpenClosed01);
/// let val: f32 = OpenClosed01.sample(&mut thread_rng());
/// println!("f32 from (0, 1): {}", val);
/// ```
///
Expand All @@ -57,10 +57,10 @@ pub struct OpenClosed01;
///
/// # Example
/// ```
/// use rand::{thread_rng, Rng};
/// use rand::prelude::*;
/// use rand::distributions::Open01;
///
/// let val: f32 = thread_rng().sample(Open01);
/// let val: f32 = Open01.sample(&mut thread_rng());
/// println!("f32 from (0, 1): {}", val);
/// ```
///
Expand Down Expand Up @@ -171,91 +171,65 @@ float_impls! { f64x8, u64x8, f64, u64, 52, 1023 }
#[cfg(test)]
mod tests {
use Rng;
use distributions::{Open01, OpenClosed01};
use distributions::{Distribution, Open01, OpenClosed01};
use rngs::mock::StepRng;
#[cfg(feature="simd_support")]
use core::simd::*;

const EPSILON32: f32 = ::core::f32::EPSILON;
const EPSILON64: f64 = ::core::f64::EPSILON;

macro_rules! test_f32 {
($fnn:ident, $ty:ident, $ZERO:expr, $EPSILON:expr) => {
macro_rules! test_float {
($fnn:ident, $ty:ident, $ZERO:expr, $EPSILON:expr, $ONE_BITS:expr) => {
#[test]
fn $fnn() {
// Standard
let mut zeros = StepRng::new(0, 0);
assert_eq!(zeros.gen::<$ty>(), $ZERO);
let mut one = StepRng::new(1 << 8 | 1 << (8 + 32), 0);
let mut one = StepRng::new($ONE_BITS, 0);
assert_eq!(one.gen::<$ty>(), $EPSILON / 2.0);
let mut max = StepRng::new(!0, 0);
assert_eq!(max.gen::<$ty>(), 1.0 - $EPSILON / 2.0);

// OpenClosed01
let mut zeros = StepRng::new(0, 0);
assert_eq!(zeros.sample::<$ty, _>(OpenClosed01),
0.0 + $EPSILON / 2.0);
let mut one = StepRng::new(1 << 8 | 1 << (8 + 32), 0);
assert_eq!(one.sample::<$ty, _>(OpenClosed01), $EPSILON);
assert_eq!(Distribution::<$ty>::sample(&OpenClosed01, &mut zeros),
(0.0 + $EPSILON / 2.0) as $ty);
let mut one = StepRng::new($ONE_BITS, 0);
assert_eq!(Distribution::<$ty>::sample(&OpenClosed01, &mut one),
$EPSILON);
let mut max = StepRng::new(!0, 0);
assert_eq!(max.sample::<$ty, _>(OpenClosed01), $ZERO + 1.0);
assert_eq!(Distribution::<$ty>::sample(&OpenClosed01, &mut max),
$ZERO + 1.0);

// Open01
let mut zeros = StepRng::new(0, 0);
assert_eq!(zeros.sample::<$ty, _>(Open01), 0.0 + $EPSILON / 2.0);
let mut one = StepRng::new(1 << 9 | 1 << (9 + 32), 0);
assert_eq!(one.sample::<$ty, _>(Open01), $EPSILON / 2.0 * 3.0);
assert_eq!(Distribution::<$ty>::sample(&Open01, &mut zeros),
0.0 + $EPSILON / 2.0);
let mut one = StepRng::new($ONE_BITS << 1, 0);
assert_eq!(Distribution::<$ty>::sample(&Open01, &mut one),
$EPSILON / 2.0 * 3.0);
let mut max = StepRng::new(!0, 0);
assert_eq!(max.sample::<$ty, _>(Open01), 1.0 - $EPSILON / 2.0);
assert_eq!(Distribution::<$ty>::sample(&Open01, &mut max),
1.0 - $EPSILON / 2.0);
}
}
}
test_f32! { f32_edge_cases, f32, 0.0, EPSILON32 }
test_float! { f32_edge_cases, f32, 0.0, EPSILON32, 1 << 8 | 1 << (8 + 32) }
#[cfg(feature="simd_support")]
test_f32! { f32x2_edge_cases, f32x2, f32x2::splat(0.0), f32x2::splat(EPSILON32) }
test_float! { f32x2_edge_cases, f32x2, f32x2::splat(0.0), f32x2::splat(EPSILON32), 1 << 8 | 1 << (8 + 32) }
#[cfg(feature="simd_support")]
test_f32! { f32x4_edge_cases, f32x4, f32x4::splat(0.0), f32x4::splat(EPSILON32) }
test_float! { f32x4_edge_cases, f32x4, f32x4::splat(0.0), f32x4::splat(EPSILON32), 1 << 8 | 1 << (8 + 32) }
#[cfg(feature="simd_support")]
test_f32! { f32x8_edge_cases, f32x8, f32x8::splat(0.0), f32x8::splat(EPSILON32) }
test_float! { f32x8_edge_cases, f32x8, f32x8::splat(0.0), f32x8::splat(EPSILON32), 1 << 8 | 1 << (8 + 32) }
#[cfg(feature="simd_support")]
test_f32! { f32x16_edge_cases, f32x16, f32x16::splat(0.0), f32x16::splat(EPSILON32) }

macro_rules! test_f64 {
($fnn:ident, $ty:ident, $ZERO:expr, $EPSILON:expr) => {
#[test]
fn $fnn() {
// Standard
let mut zeros = StepRng::new(0, 0);
assert_eq!(zeros.gen::<$ty>(), $ZERO);
let mut one = StepRng::new(1 << 11, 0);
assert_eq!(one.gen::<$ty>(), $EPSILON / 2.0);
let mut max = StepRng::new(!0, 0);
assert_eq!(max.gen::<$ty>(), 1.0 - $EPSILON / 2.0);
test_float! { f32x16_edge_cases, f32x16, f32x16::splat(0.0), f32x16::splat(EPSILON32), 1 << 8 | 1 << (8 + 32) }

// OpenClosed01
let mut zeros = StepRng::new(0, 0);
assert_eq!(zeros.sample::<$ty, _>(OpenClosed01),
0.0 + $EPSILON / 2.0);
let mut one = StepRng::new(1 << 11, 0);
assert_eq!(one.sample::<$ty, _>(OpenClosed01), $EPSILON);
let mut max = StepRng::new(!0, 0);
assert_eq!(max.sample::<$ty, _>(OpenClosed01), $ZERO + 1.0);

// Open01
let mut zeros = StepRng::new(0, 0);
assert_eq!(zeros.sample::<$ty, _>(Open01), 0.0 + $EPSILON / 2.0);
let mut one = StepRng::new(1 << 12, 0);
assert_eq!(one.sample::<$ty, _>(Open01), $EPSILON / 2.0 * 3.0);
let mut max = StepRng::new(!0, 0);
assert_eq!(max.sample::<$ty, _>(Open01), 1.0 - $EPSILON / 2.0);
}
}
}
test_f64! { f64_edge_cases, f64, 0.0, EPSILON64 }
test_float! { f64_edge_cases, f64, 0.0, EPSILON64, 1 << 11 }
#[cfg(feature="simd_support")]
test_f64! { f64x2_edge_cases, f64x2, f64x2::splat(0.0), f64x2::splat(EPSILON64) }
test_float! { f64x2_edge_cases, f64x2, f64x2::splat(0.0), f64x2::splat(EPSILON64), 1 << 11 }
#[cfg(feature="simd_support")]
test_f64! { f64x4_edge_cases, f64x4, f64x4::splat(0.0), f64x4::splat(EPSILON64) }
test_float! { f64x4_edge_cases, f64x4, f64x4::splat(0.0), f64x4::splat(EPSILON64), 1 << 11 }
#[cfg(feature="simd_support")]
test_f64! { f64x8_edge_cases, f64x8, f64x8::splat(0.0), f64x8::splat(EPSILON64) }
test_float! { f64x8_edge_cases, f64x8, f64x8::splat(0.0), f64x8::splat(EPSILON64), 1 << 11 }
}
10 changes: 5 additions & 5 deletions src/distributions/gamma.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,22 +142,22 @@ impl Distribution<f64> for Gamma {
}
impl Distribution<f64> for GammaSmallShape {
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> f64 {
let u: f64 = rng.sample(Open01);
let u: f64 = Open01.sample(rng);

self.large_shape.sample(rng) * u.powf(self.inv_shape)
}
}
impl Distribution<f64> for GammaLargeShape {
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> f64 {
loop {
let x = rng.sample(StandardNormal);
let x = StandardNormal.sample(rng);
let v_cbrt = 1.0 + self.c * x;
if v_cbrt <= 0.0 { // a^3 <= 0 iff a <= 0
continue
}

let v = v_cbrt * v_cbrt * v_cbrt;
let u: f64 = rng.sample(Open01);
let u: f64 = Open01.sample(rng);

let x_sqr = x * x;
if u < 1.0 - 0.0331 * x_sqr * x_sqr ||
Expand Down Expand Up @@ -217,7 +217,7 @@ impl Distribution<f64> for ChiSquared {
match self.repr {
DoFExactlyOne => {
// k == 1 => N(0,1)^2
let norm = rng.sample(StandardNormal);
let norm = StandardNormal.sample(rng);
norm * norm
}
DoFAnythingElse(ref g) => g.sample(rng)
Expand Down Expand Up @@ -300,7 +300,7 @@ impl StudentT {
}
impl Distribution<f64> for StudentT {
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> f64 {
let norm = rng.sample(StandardNormal);
let norm = StandardNormal.sample(rng);
norm * (self.dof / self.chi.sample(rng)).sqrt()
}
}
Expand Down
29 changes: 14 additions & 15 deletions src/distributions/integer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,27 +122,26 @@ simd_impl!(512, u8x64, i8x64, u16x32, i16x32, u32x16, i32x16, u64x8, i64x8,);

#[cfg(test)]
mod tests {
use Rng;
use distributions::{Standard};
use distributions::{Distribution, Standard};

#[test]
fn test_integers() {
let mut rng = ::test::rng(806);
let rng = &mut ::test::rng(806);

rng.sample::<isize, _>(Standard);
rng.sample::<i8, _>(Standard);
rng.sample::<i16, _>(Standard);
rng.sample::<i32, _>(Standard);
rng.sample::<i64, _>(Standard);
let _: isize = Standard.sample(rng);
let _: i8 = Standard.sample(rng);
let _: i16 = Standard.sample(rng);
let _: i32 = Standard.sample(rng);
let _: i64 = Standard.sample(rng);
#[cfg(feature = "i128_support")]
rng.sample::<i128, _>(Standard);
let _: i128 = Standard.sample(rng);

rng.sample::<usize, _>(Standard);
rng.sample::<u8, _>(Standard);
rng.sample::<u16, _>(Standard);
rng.sample::<u32, _>(Standard);
rng.sample::<u64, _>(Standard);
let _: usize = Standard.sample(rng);
let _: u8 = Standard.sample(rng);
let _: u16 = Standard.sample(rng);
let _: u32 = Standard.sample(rng);
let _: u64 = Standard.sample(rng);
#[cfg(feature = "i128_support")]
rng.sample::<u128, _>(Standard);
let _: u128 = Standard.sample(rng);
}
}
20 changes: 17 additions & 3 deletions src/distributions/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,11 +106,11 @@
//! Sampling from a distribution:
//!
//! ```
//! use rand::{thread_rng, Rng};
//! use rand::prelude::*;
//! use rand::distributions::Exp;
//!
//! let exp = Exp::new(2.0);
//! let v = thread_rng().sample(exp);
//! let v = exp.sample(&mut thread_rng());
//! println!("{} is from an Exp(2) distribution", v);
//! ```
//!
Expand Down Expand Up @@ -220,6 +220,20 @@ mod utils;
/// [`sample_iter`]: trait.Distribution.html#method.sample_iter
pub trait Distribution<T> {
/// Generate a random value of `T`, using `rng` as the source of randomness.
///
/// ### Example
///
/// ```
/// use rand::prelude::*;
/// use rand::distributions::Uniform;
///
/// let mut rng = thread_rng();
/// let distr = Uniform::new(10u32, 15);
/// for _ in 0..10 {
/// let x = distr.sample(&mut rng);
/// println!("{}", x);
/// }
/// ```
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> T;

/// Create an iterator that generates random values of `T`, using `rng` as
Expand Down Expand Up @@ -329,7 +343,7 @@ impl<'a, D, R, T> Iterator for DistIter<'a, D, R, T>
/// use rand::prelude::*;
/// use rand::distributions::Standard;
///
/// let val: f32 = SmallRng::from_entropy().sample(Standard);
/// let val: f32 = Standard.sample(&mut SmallRng::from_entropy());
/// println!("f32 from [0, 1): {}", val);
/// ```
///
Expand Down
8 changes: 4 additions & 4 deletions src/distributions/normal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ use distributions::utils::ziggurat;
/// use rand::prelude::*;
/// use rand::distributions::StandardNormal;
///
/// let val: f64 = SmallRng::from_entropy().sample(StandardNormal);
/// let val: f64 = StandardNormal.sample(&mut SmallRng::from_entropy());
/// println!("{}", val);
/// ```
#[derive(Clone, Copy, Debug)]
Expand All @@ -56,8 +56,8 @@ impl Distribution<f64> for StandardNormal {
let mut y = 0.0f64;

while -2.0 * y < x * x {
let x_: f64 = rng.sample(Open01);
let y_: f64 = rng.sample(Open01);
let x_: f64 = Open01.sample(rng);
let y_: f64 = Open01.sample(rng);

x = x_.ln() / ziggurat_tables::ZIG_NORM_R;
y = y_.ln();
Expand Down Expand Up @@ -112,7 +112,7 @@ impl Normal {
}
impl Distribution<f64> for Normal {
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> f64 {
let n = rng.sample(StandardNormal);
let n = StandardNormal.sample(rng);
self.mean + self.std_dev * n
}
}
Expand Down

0 comments on commit 89ec7b4

Please sign in to comment.