From 31667424d60a16e4809d5c602797d44bfe91080b Mon Sep 17 00:00:00 2001 From: Matt Brubeck Date: Mon, 22 May 2017 11:58:30 -0700 Subject: [PATCH] [breaking change] Automatically impl Sample for T: IndependentSample This removes the need to manually implement Sample for types that implement IndependentSample, cutting down on boilerplate and reducing chances for mis-matched implementations. It also adds blanket impls for `&T` where `T: IndependentSample`, so that `.sample()` can be called on these types without needing a unique reference. This is a breaking change because it conflicts with crates that impl both Sample and IndependentSample for their own types. --- src/distributions/exponential.rs | 5 +---- src/distributions/gamma.rs | 21 +-------------------- src/distributions/mod.rs | 22 ++++++++++++++-------- src/distributions/normal.rs | 8 +------- src/distributions/range.rs | 6 +----- 5 files changed, 18 insertions(+), 44 deletions(-) diff --git a/src/distributions/exponential.rs b/src/distributions/exponential.rs index c3c924c6b7e..cac79f36f2b 100644 --- a/src/distributions/exponential.rs +++ b/src/distributions/exponential.rs @@ -11,7 +11,7 @@ //! The exponential distribution. use {Rng, Rand}; -use distributions::{ziggurat, ziggurat_tables, Sample, IndependentSample}; +use distributions::{ziggurat, ziggurat_tables, IndependentSample}; /// A wrapper around an `f64` to generate Exp(1) random numbers. /// @@ -87,9 +87,6 @@ impl Exp { } } -impl Sample for Exp { - fn sample(&mut self, rng: &mut R) -> f64 { self.ind_sample(rng) } -} impl IndependentSample for Exp { fn ind_sample(&self, rng: &mut R) -> f64 { let Exp1(n) = rng.gen::(); diff --git a/src/distributions/gamma.rs b/src/distributions/gamma.rs index 1cff4dd4f46..66ba5aada41 100644 --- a/src/distributions/gamma.rs +++ b/src/distributions/gamma.rs @@ -17,7 +17,7 @@ use self::ChiSquaredRepr::*; use {Rng, Open01}; use super::normal::StandardNormal; -use super::{IndependentSample, Sample, Exp}; +use super::{IndependentSample, Exp}; /// The Gamma distribution `Gamma(shape, scale)` distribution. /// @@ -131,16 +131,6 @@ impl GammaLargeShape { } } -impl Sample for Gamma { - fn sample(&mut self, rng: &mut R) -> f64 { self.ind_sample(rng) } -} -impl Sample for GammaSmallShape { - fn sample(&mut self, rng: &mut R) -> f64 { self.ind_sample(rng) } -} -impl Sample for GammaLargeShape { - fn sample(&mut self, rng: &mut R) -> f64 { self.ind_sample(rng) } -} - impl IndependentSample for Gamma { fn ind_sample(&self, rng: &mut R) -> f64 { match self.repr { @@ -222,9 +212,6 @@ impl ChiSquared { ChiSquared { repr: repr } } } -impl Sample for ChiSquared { - fn sample(&mut self, rng: &mut R) -> f64 { self.ind_sample(rng) } -} impl IndependentSample for ChiSquared { fn ind_sample(&self, rng: &mut R) -> f64 { match self.repr { @@ -276,9 +263,6 @@ impl FisherF { } } } -impl Sample for FisherF { - fn sample(&mut self, rng: &mut R) -> f64 { self.ind_sample(rng) } -} impl IndependentSample for FisherF { fn ind_sample(&self, rng: &mut R) -> f64 { self.numer.ind_sample(rng) / self.denom.ind_sample(rng) * self.dof_ratio @@ -314,9 +298,6 @@ impl StudentT { } } } -impl Sample for StudentT { - fn sample(&mut self, rng: &mut R) -> f64 { self.ind_sample(rng) } -} impl IndependentSample for StudentT { fn ind_sample(&self, rng: &mut R) -> f64 { let StandardNormal(norm) = rng.gen::(); diff --git a/src/distributions/mod.rs b/src/distributions/mod.rs index f128b75c1ce..1fd75dea1be 100644 --- a/src/distributions/mod.rs +++ b/src/distributions/mod.rs @@ -51,6 +51,20 @@ pub trait IndependentSample: Sample { fn ind_sample(&self, &mut R) -> Support; } +impl> Sample for T { + #[inline] + fn sample(&mut self, rng: &mut R) -> Support { + self.ind_sample(rng) + } +} + +impl<'a, Support, T: IndependentSample> IndependentSample for &'a T { + #[inline] + fn ind_sample(&self, rng: &mut R) -> Support { + (*self).ind_sample(rng) + } +} + /// A wrapper for generating types that implement `Rand` via the /// `Sample` & `IndependentSample` traits. #[derive(Debug)] @@ -63,10 +77,6 @@ impl Clone for RandSample { fn clone(&self) -> Self { *self } } -impl Sample for RandSample { - fn sample(&mut self, rng: &mut R) -> Sup { self.ind_sample(rng) } -} - impl IndependentSample for RandSample { fn ind_sample(&self, rng: &mut R) -> Sup { rng.gen() @@ -155,10 +165,6 @@ impl<'a, T: Clone> WeightedChoice<'a, T> { } } -impl<'a, T: Clone> Sample for WeightedChoice<'a, T> { - fn sample(&mut self, rng: &mut R) -> T { self.ind_sample(rng) } -} - impl<'a, T: Clone> IndependentSample for WeightedChoice<'a, T> { fn ind_sample(&self, rng: &mut R) -> T { // we want to find the first element that has cumulative diff --git a/src/distributions/normal.rs b/src/distributions/normal.rs index 280613d8595..b9456c113fe 100644 --- a/src/distributions/normal.rs +++ b/src/distributions/normal.rs @@ -11,7 +11,7 @@ //! The normal and derived distributions. use {Rng, Rand, Open01}; -use distributions::{ziggurat, ziggurat_tables, Sample, IndependentSample}; +use distributions::{ziggurat, ziggurat_tables, IndependentSample}; /// A wrapper around an `f64` to generate N(0, 1) random numbers /// (a.k.a. a standard normal, or Gaussian). @@ -110,9 +110,6 @@ impl Normal { } } } -impl Sample for Normal { - fn sample(&mut self, rng: &mut R) -> f64 { self.ind_sample(rng) } -} impl IndependentSample for Normal { fn ind_sample(&self, rng: &mut R) -> f64 { let StandardNormal(n) = rng.gen::(); @@ -154,9 +151,6 @@ impl LogNormal { LogNormal { norm: Normal::new(mean, std_dev) } } } -impl Sample for LogNormal { - fn sample(&mut self, rng: &mut R) -> f64 { self.ind_sample(rng) } -} impl IndependentSample for LogNormal { fn ind_sample(&self, rng: &mut R) -> f64 { self.norm.ind_sample(rng).exp() diff --git a/src/distributions/range.rs b/src/distributions/range.rs index 7206941d0dc..97888173faa 100644 --- a/src/distributions/range.rs +++ b/src/distributions/range.rs @@ -15,7 +15,7 @@ use std::num::Wrapping as w; use Rng; -use distributions::{Sample, IndependentSample}; +use distributions::IndependentSample; /// Sample values uniformly between two bounds. /// @@ -62,10 +62,6 @@ impl Range { } } -impl Sample for Range { - #[inline] - fn sample(&mut self, rng: &mut R) -> Sup { self.ind_sample(rng) } -} impl IndependentSample for Range { fn ind_sample(&self, rng: &mut R) -> Sup { SampleRange::sample_range(self, rng)