Repository: statrs-dev/statrs (language: rust)

Issue:
WeakRngDistribution is broken
It currently initializes a `XorShiftRng` using Rand's `thread_rng`, samples a value, and discards the `XorShiftRng`. This is probably not what you want, because you might just use the `thread_rng()` instead. However, then the name `WeakRngDistribution` is wrong, because `thread_rng()` uses a strong RNG.


Discussion / hints:

Fix patch:
diff --git a/Cargo.toml b/Cargo.toml
index 0b9fd9ae..afb04eb1 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -17,4 +17,4 @@ name = "statrs"
 path = "src/lib.rs"
 
 [dependencies]
-rand = "0.3"
\ No newline at end of file
+rand = "0.5"
diff --git a/src/distribution/bernoulli.rs b/src/distribution/bernoulli.rs
index 81db67e9..93f4d889 100644
--- a/src/distribution/bernoulli.rs
+++ b/src/distribution/bernoulli.rs
@@ -1,5 +1,5 @@
-use distribution::{Binomial, Discrete, Distribution, Univariate, WeakRngDistribution};
-use rand::distributions::{IndependentSample, Sample};
+use distribution::{Binomial, Discrete, Univariate};
+use rand::distributions::Distribution;
 use rand::Rng;
 use statistics::*;
 use Result;
@@ -81,52 +81,12 @@ impl Bernoulli {
     }
 }
 
-impl Sample<f64> for Bernoulli {
-    /// Generate a random sample from a bernoulli
-    /// distribution using `r` as the source of randomness.
-    /// Refer [here](#method.sample-1) for implementation details
-    fn sample<R: Rng>(&mut self, r: &mut R) -> f64 {
-        super::Distribution::sample(self, r)
-    }
-}
-
-impl IndependentSample<f64> for Bernoulli {
-    /// Generate a random independent sample from a bernoulli
-    /// distribution using `r` as the source of randomness.
-    /// Refer [here](#method.sample-1) for implementation details
-    fn ind_sample<R: Rng>(&self, r: &mut R) -> f64 {
-        super::Distribution::sample(self, r)
-    }
-}
-
 impl Distribution<f64> for Bernoulli {
-    /// Generate a random sample from the
-    /// bernoulli distribution using `r` as the source
-    /// of randomness where the generated
-    /// values are `1` with probability `p` and `0`
-    /// with probability `1-p`.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// # extern crate rand;
-    /// # extern crate statrs;
-    /// use rand::StdRng;
-    /// use statrs::distribution::{Bernoulli, Distribution};
-    ///
-    /// # fn main() {
-    /// let mut r = rand::StdRng::new().unwrap();
-    /// let n = Bernoulli::new(0.5).unwrap();
-    /// print!("{}", n.sample::<StdRng>(&mut r));
-    /// # }
-    /// ```
-    fn sample<R: Rng>(&self, r: &mut R) -> f64 {
-        self.b.sample(r)
+    fn sample<R: Rng + ?Sized>(&self, r: &mut R) -> f64 {
+        r.gen_bool(self.p()) as u8 as f64
     }
 }
 
-impl WeakRngDistribution<f64> for Bernoulli {}
-
 impl Univariate<u64, f64> for Bernoulli {
     /// Calculates the cumulative distribution
     /// function for the bernoulli distribution at `x`.
diff --git a/src/distribution/beta.rs b/src/distribution/beta.rs
index a8ec1039..69937d81 100644
--- a/src/distribution/beta.rs
+++ b/src/distribution/beta.rs
@@ -1,6 +1,6 @@
-use distribution::{Continuous, Distribution, Univariate, WeakRngDistribution};
+use distribution::{Continuous, Univariate};
 use function::{beta, gamma};
-use rand::distributions::{IndependentSample, Sample};
+use rand::distributions::Distribution;
 use rand::Rng;
 use statistics::*;
 use std::f64;
@@ -87,52 +87,15 @@ impl Beta {
     }
 }
 
-impl Sample<f64> for Beta {
-    /// Generate a random sample from a beta distribution
-    /// using `r` as the source of randomness.
-    /// Refer [here](#method.sample-1) for implementation details.
-    fn sample<R: Rng>(&mut self, r: &mut R) -> f64 {
-        super::Distribution::sample(self, r)
-    }
-}
-
-impl IndependentSample<f64> for Beta {
-    /// Generate a random independent sample from a beta distribution
-    /// using `r` as the source of randomness.
-    /// Refer [here](#method.sample-1) for implementation details.
-    fn ind_sample<R: Rng>(&self, r: &mut R) -> f64 {
-        super::Distribution::sample(self, r)
-    }
-}
-
 impl Distribution<f64> for Beta {
-    /// Generate a random sample from a beta distribution using
-    /// `r` as the source of randomness. Generated by sampling
-    /// two gamma distributions and normalizing.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// # extern crate rand;
-    /// # extern crate statrs;
-    /// use rand::StdRng;
-    /// use statrs::distribution::{Beta, Distribution};
-    ///
-    /// # fn main() {
-    /// let mut r = rand::StdRng::new().unwrap();
-    /// let n = Beta::new(2.0, 2.0).unwrap();
-    /// print!("{}", n.sample::<StdRng>(&mut r));
-    /// # }
-    /// ```
-    fn sample<R: Rng>(&self, r: &mut R) -> f64 {
+    fn sample<R: Rng + ?Sized>(&self, r: &mut R) -> f64 {
+        // Generated by sampling two gamma distributions and normalizing.
         let x = super::gamma::sample_unchecked(r, self.shape_a, 1.0);
         let y = super::gamma::sample_unchecked(r, self.shape_b, 1.0);
         x / (x + y)
     }
 }
 
-impl WeakRngDistribution<f64> for Beta {}
-
 impl Univariate<f64, f64> for Beta {
     /// Calculates the cumulative distribution function for the beta
     /// distribution
diff --git a/src/distribution/binomial.rs b/src/distribution/binomial.rs
index c8bca75c..c0998cc1 100644
--- a/src/distribution/binomial.rs
+++ b/src/distribution/binomial.rs
@@ -1,6 +1,6 @@
-use distribution::{Discrete, Distribution, Univariate, WeakRngDistribution};
+use distribution::{Discrete, Univariate};
 use function::{beta, factorial};
-use rand::distributions::{IndependentSample, Sample};
+use rand::distributions::Distribution;
 use rand::Rng;
 use statistics::*;
 use std::f64;
@@ -87,46 +87,10 @@ impl Binomial {
     }
 }
 
-impl Sample<f64> for Binomial {
-    /// Generate a random sample from a binomial
-    /// distribution using `r` as the source of randomness.
-    /// Refer [here](#method.sample-1) for implementation details
-    fn sample<R: Rng>(&mut self, r: &mut R) -> f64 {
-        super::Distribution::sample(self, r)
-    }
-}
-
-/// Generate a random independent sample from a binomial
-/// distribution using `r` as the source of randomness.
-/// Refer [here](#method.sample-1) for implementation details
-impl IndependentSample<f64> for Binomial {
-    fn ind_sample<R: Rng>(&self, r: &mut R) -> f64 {
-        super::Distribution::sample(self, r)
-    }
-}
-
 impl Distribution<f64> for Binomial {
-    /// Generate a random sample from the binomial distribution
-    /// using `r` as the source of randomness  where the range of
-    /// values is `[0.0, n]`.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// # extern crate rand;
-    /// # extern crate statrs;
-    /// use rand::StdRng;
-    /// use statrs::distribution::{Binomial, Distribution};
-    ///
-    /// # fn main() {
-    /// let mut r = rand::StdRng::new().unwrap();
-    /// let n = Binomial::new(0.5, 5).unwrap();
-    /// print!("{}", n.sample::<StdRng>(&mut r));
-    /// # }
-    /// ```
-    fn sample<R: Rng>(&self, r: &mut R) -> f64 {
+    fn sample<R: Rng + ?Sized>(&self, r: &mut R) -> f64 {
         (0..self.n).fold(0.0, |acc, _| {
-            let n = r.next_f64();
+            let n: f64 = r.gen();
             if n < self.p {
                 acc + 1.0
             } else {
@@ -136,8 +100,6 @@ impl Distribution<f64> for Binomial {
     }
 }
 
-impl WeakRngDistribution<f64> for Binomial {}
-
 impl Univariate<u64, f64> for Binomial {
     /// Calulcates the cumulative distribution function for the
     /// binomial distribution at `x`
@@ -320,8 +282,7 @@ impl Discrete<u64, f64> for Binomial {
         } else {
             (factorial::ln_binomial(self.n as u64, x as u64)
                 + x as f64 * self.p.ln()
-                + (self.n - x) as f64 * (1.0 - self.p).ln())
-                .exp()
+                + (self.n - x) as f64 * (1.0 - self.p).ln()).exp()
         }
     }
 
diff --git a/src/distribution/categorical.rs b/src/distribution/categorical.rs
index 9e0066ef..fe5dd25b 100644
--- a/src/distribution/categorical.rs
+++ b/src/distribution/categorical.rs
@@ -1,7 +1,5 @@
-use distribution::{
-    CheckedInverseCDF, Discrete, Distribution, InverseCDF, Univariate, WeakRngDistribution,
-};
-use rand::distributions::{IndependentSample, Sample};
+use distribution::{CheckedInverseCDF, Discrete, InverseCDF, Univariate};
+use rand::distributions::Distribution;
 use rand::Rng;
 use statistics::*;
 use std::f64;
@@ -82,49 +80,12 @@ impl Categorical {
     }
 }
 
-impl Sample<f64> for Categorical {
-    /// Generate a random sample from a categorical
-    /// distribution using `r` as the source of randomness.
-    /// Refer [here](#method.sample-1) for implementation details
-    fn sample<R: Rng>(&mut self, r: &mut R) -> f64 {
-        super::Distribution::sample(self, r)
-    }
-}
-
-impl IndependentSample<f64> for Categorical {
-    /// Generate a random independent sample from a categorical
-    /// distribution using `r` as the source of randomness.
-    /// Refer [here](#method.sample-1) for implementation details
-    fn ind_sample<R: Rng>(&self, r: &mut R) -> f64 {
-        super::Distribution::sample(self, r)
-    }
-}
-
 impl Distribution<f64> for Categorical {
-    /// Generate a random sample from the categorical distribution
-    /// using `r` as the source of randomness
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// # extern crate rand;
-    /// # extern crate statrs;
-    /// use rand::StdRng;
-    /// use statrs::distribution::{Categorical, Distribution};
-    ///
-    /// # fn main() {
-    /// let mut r = rand::StdRng::new().unwrap();
-    /// let n = Categorical::new(&[1.0, 2.0, 3.0]).unwrap();
-    /// print!("{}", n.sample::<StdRng>(&mut r));
-    /// # }
-    /// ```
-    fn sample<R: Rng>(&self, r: &mut R) -> f64 {
+    fn sample<R: Rng + ?Sized>(&self, r: &mut R) -> f64 {
         sample_unchecked(r, &self.cdf)
     }
 }
 
-impl WeakRngDistribution<f64> for Categorical {}
-
 impl Univariate<u64, f64> for Categorical {
     /// Calculates the cumulative distribution function for the categorical
     /// distribution at `x`
@@ -348,8 +309,8 @@ impl Discrete<u64, f64> for Categorical {
 
 /// Draws a sample from the categorical distribution described by `cdf`
 /// without doing any bounds checking
-pub fn sample_unchecked<R: Rng>(r: &mut R, cdf: &[f64]) -> f64 {
-    let draw = r.next_f64() * unsafe { cdf.get_unchecked(cdf.len() - 1) };
+pub fn sample_unchecked<R: Rng + ?Sized>(r: &mut R, cdf: &[f64]) -> f64 {
+    let draw = r.gen::<f64>() * unsafe { cdf.get_unchecked(cdf.len() - 1) };
     let mut idx = 0;
 
     if draw == 0.0 {
diff --git a/src/distribution/cauchy.rs b/src/distribution/cauchy.rs
index cf9949d3..d7063f2c 100644
--- a/src/distribution/cauchy.rs
+++ b/src/distribution/cauchy.rs
@@ -1,5 +1,5 @@
-use distribution::{Continuous, Distribution, Univariate, WeakRngDistribution};
-use rand::distributions::{IndependentSample, Sample};
+use distribution::{Continuous, Univariate};
+use rand::distributions::Distribution;
 use rand::Rng;
 use statistics::*;
 use std::f64;
@@ -83,49 +83,12 @@ impl Cauchy {
     }
 }
 
-impl Sample<f64> for Cauchy {
-    /// Generate a random sample from a cauchy
-    /// distribution using `r` as the source of randomness.
-    /// Refer [here](#method.sample-1) for implementation details
-    fn sample<R: Rng>(&mut self, r: &mut R) -> f64 {
-        super::Distribution::sample(self, r)
-    }
-}
-
-impl IndependentSample<f64> for Cauchy {
-    /// Generate a random independent sample from a cauchy
-    /// distribution using `r` as the source of randomness.
-    /// Refer [here](#method.sample-1) for implementation details
-    fn ind_sample<R: Rng>(&self, r: &mut R) -> f64 {
-        super::Distribution::sample(self, r)
-    }
-}
-
 impl Distribution<f64> for Cauchy {
-    /// Generate a random sample from the cauchy distribution
-    /// using `r` as the source of randomness
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// # extern crate rand;
-    /// # extern crate statrs;
-    /// use rand::StdRng;
-    /// use statrs::distribution::{Cauchy, Distribution};
-    ///
-    /// # fn main() {
-    /// let mut r = rand::StdRng::new().unwrap();
-    /// let n = Cauchy::new(0.0, 1.0).unwrap();
-    /// print!("{}", n.sample::<StdRng>(&mut r));
-    /// # }
-    /// ```
-    fn sample<R: Rng>(&self, r: &mut R) -> f64 {
-        self.location + self.scale * (f64::consts::PI * (r.next_f64() - 0.5)).tan()
+    fn sample<R: Rng + ?Sized>(&self, r: &mut R) -> f64 {
+        self.location + self.scale * (f64::consts::PI * (r.gen::<f64>() - 0.5)).tan()
     }
 }
 
-impl WeakRngDistribution<f64> for Cauchy {}
-
 impl Univariate<f64, f64> for Cauchy {
     /// Calculates the cumulative distribution function for the
     /// cauchy distribution at `x`
diff --git a/src/distribution/chi.rs b/src/distribution/chi.rs
index 70a5b80f..72ecd959 100644
--- a/src/distribution/chi.rs
+++ b/src/distribution/chi.rs
@@ -1,6 +1,6 @@
-use distribution::{Continuous, Distribution, Univariate, WeakRngDistribution};
+use distribution::{Continuous, Univariate};
 use function::gamma;
-use rand::distributions::{IndependentSample, Sample};
+use rand::distributions::Distribution;
 use rand::Rng;
 use statistics::*;
 use std::f64;
@@ -69,53 +69,15 @@ impl Chi {
     }
 }
 
-impl Sample<f64> for Chi {
-    /// Generate a random sample from a chi
-    /// distribution using `r` as the source of randomness.
-    /// Refer [here](#method.sample-1) for implementation details
-    fn sample<R: Rng>(&mut self, r: &mut R) -> f64 {
-        super::Distribution::sample(self, r)
-    }
-}
-
-impl IndependentSample<f64> for Chi {
-    /// Generate a random independent sample from a chi
-    /// distribution using `r` as the source of randomness.
-    /// Refer [here](#method.sample-1) for implementation details
-    fn ind_sample<R: Rng>(&self, r: &mut R) -> f64 {
-        super::Distribution::sample(self, r)
-    }
-}
-
 impl Distribution<f64> for Chi {
-    /// Generate a random sample from the chi distribution
-    /// using `r` as the source of randomness
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// # extern crate rand;
-    /// # extern crate statrs;
-    /// use rand::StdRng;
-    /// use statrs::distribution::{Chi, Distribution};
-    ///
-    /// # fn main() {
-    /// let mut r = rand::StdRng::new().unwrap();
-    /// let n = Chi::new(2.0).unwrap();
-    /// print!("{}", n.sample::<StdRng>(&mut r));
-    /// # }
-    /// ```
-    fn sample<R: Rng>(&self, r: &mut R) -> f64 {
+    fn sample<R: Rng + ?Sized>(&self, r: &mut R) -> f64 {
         (0..self.freedom as i64)
             .fold(0.0, |acc, _| {
                 acc + super::normal::sample_unchecked(r, 0.0, 1.0).powf(2.0)
-            })
-            .sqrt()
+            }).sqrt()
     }
 }
 
-impl WeakRngDistribution<f64> for Chi {}
-
 impl Univariate<f64, f64> for Chi {
     /// Calculates the cumulative distribution function for the chi
     /// distribution at `x`.
@@ -244,7 +206,8 @@ impl Entropy<f64> for Chi {
         gamma::ln_gamma(self.freedom / 2.0)
             + (self.freedom
                 - (2.0f64).ln()
-                - (self.freedom - 1.0) * gamma::digamma(self.freedom / 2.0)) / 2.0
+                - (self.freedom - 1.0) * gamma::digamma(self.freedom / 2.0))
+                / 2.0
     }
 }
 
@@ -329,7 +292,8 @@ impl Continuous<f64, f64> for Chi {
         } else {
             (2.0f64).powf(1.0 - self.freedom / 2.0)
                 * x.powf(self.freedom - 1.0)
-                * (-x * x / 2.0).exp() / gamma::gamma(self.freedom / 2.0)
+                * (-x * x / 2.0).exp()
+                / gamma::gamma(self.freedom / 2.0)
         }
     }
 
diff --git a/src/distribution/chi_squared.rs b/src/distribution/chi_squared.rs
index 8519a06e..525f9ba3 100644
--- a/src/distribution/chi_squared.rs
+++ b/src/distribution/chi_squared.rs
@@ -1,5 +1,5 @@
-use distribution::{Continuous, Distribution, Gamma, Univariate, WeakRngDistribution};
-use rand::distributions::{IndependentSample, Sample};
+use distribution::{Continuous, Gamma, Univariate};
+use rand::distributions::Distribution;
 use rand::Rng;
 use statistics::*;
 use std::f64;
@@ -100,49 +100,12 @@ impl ChiSquared {
     }
 }
 
-impl Sample<f64> for ChiSquared {
-    /// Generate a random sample from a chi-squared
-    /// distribution using `r` as the source of randomness.
-    /// Refer [here](#method.sample-1) for implementation details
-    fn sample<R: Rng>(&mut self, r: &mut R) -> f64 {
-        super::Distribution::sample(self, r)
-    }
-}
-
-impl IndependentSample<f64> for ChiSquared {
-    /// Generate a random independent sample from a Chi
-    /// distribution using `r` as the source of randomness.
-    /// Refer [here](#method.sample-1) for implementation details
-    fn ind_sample<R: Rng>(&self, r: &mut R) -> f64 {
-        super::Distribution::sample(self, r)
-    }
-}
-
 impl Distribution<f64> for ChiSquared {
-    /// Generate a random sample from the chi-squared distribution
-    /// using `r` as the source of randomness
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// # extern crate rand;
-    /// # extern crate statrs;
-    /// use rand::StdRng;
-    /// use statrs::distribution::{ChiSquared, Distribution};
-    ///
-    /// # fn main() {
-    /// let mut r = rand::StdRng::new().unwrap();
-    /// let n = ChiSquared::new(3.0).unwrap();
-    /// print!("{}", n.sample::<StdRng>(&mut r));
-    /// # }
-    /// ```
-    fn sample<R: Rng>(&self, r: &mut R) -> f64 {
-        self.g.sample(r)
+    fn sample<R: Rng + ?Sized>(&self, r: &mut R) -> f64 {
+        Distribution::sample(&self.g, r)
     }
 }
 
-impl WeakRngDistribution<f64> for ChiSquared {}
-
 impl Univariate<f64, f64> for ChiSquared {
     /// Calculates the cumulative distribution function for the
     /// chi-squared distribution at `x`
diff --git a/src/distribution/dirichlet.rs b/src/distribution/dirichlet.rs
index 6dec5fbd..ddd870ec 100644
--- a/src/distribution/dirichlet.rs
+++ b/src/distribution/dirichlet.rs
@@ -1,6 +1,6 @@
-use distribution::{CheckedContinuous, Continuous, Distribution, WeakRngDistribution};
+use distribution::{CheckedContinuous, Continuous};
 use function::gamma;
-use rand::distributions::{IndependentSample, Sample};
+use rand::distributions::Distribution;
 use rand::Rng;
 use statistics::*;
 use std::f64;
@@ -101,43 +101,8 @@ impl Dirichlet {
     }
 }
 
-impl Sample<Vec<f64>> for Dirichlet {
-    /// Generate random samples from a dirichlet
-    /// distribution using `r` as the source of randomness.
-    /// Refer [here](#method.sample-1) for implementation details
-    fn sample<R: Rng>(&mut self, r: &mut R) -> Vec<f64> {
-        super::Distribution::sample(self, r)
-    }
-}
-
-impl IndependentSample<Vec<f64>> for Dirichlet {
-    /// Generate random independent samples from a dirichlet
-    /// distribution using `r` as the source of randomness.
-    /// Refer [here](#method.sample-1) for implementation details
-    fn ind_sample<R: Rng>(&self, r: &mut R) -> Vec<f64> {
-        super::Distribution::sample(self, r)
-    }
-}
-
 impl Distribution<Vec<f64>> for Dirichlet {
-    /// Generate random samples from the dirichlet distribution
-    /// using `r` as the source of randomness
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// # extern crate rand;
-    /// # extern crate statrs;
-    /// use rand::StdRng;
-    /// use statrs::distribution::{Dirichlet, Distribution};
-    ///
-    /// # fn main() {
-    /// let mut r = rand::StdRng::new().unwrap();
-    /// let n = Dirichlet::new(&[1.0, 2.0, 3.0]).unwrap();
-    /// print!("{:?}", n.sample::<StdRng>(&mut r));
-    /// # }
-    /// ```
-    fn sample<R: Rng>(&self, r: &mut R) -> Vec<f64> {
+    fn sample<R: Rng + ?Sized>(&self, r: &mut R) -> Vec<f64> {
         let n = self.alpha.len();
         let mut samples = vec![0.0; n];
         let mut sum = 0.0;
@@ -152,8 +117,6 @@ impl Distribution<Vec<f64>> for Dirichlet {
     }
 }
 
-impl WeakRngDistribution<Vec<f64>> for Dirichlet {}
-
 impl Mean<Vec<f64>> for Dirichlet {
     /// Returns the means of the dirichlet distribution
     ///
diff --git a/src/distribution/discrete_uniform.rs b/src/distribution/discrete_uniform.rs
index 408ead74..5151470c 100644
--- a/src/distribution/discrete_uniform.rs
+++ b/src/distribution/discrete_uniform.rs
@@ -1,5 +1,5 @@
-use distribution::{Discrete, Distribution, Univariate, WeakRngDistribution};
-use rand::distributions::{IndependentSample, Sample};
+use distribution::{Discrete, Univariate};
+use rand::distributions::Distribution;
 use rand::Rng;
 use statistics::*;
 use std::f64;
@@ -53,49 +53,12 @@ impl DiscreteUniform {
     }
 }
 
-impl Sample<f64> for DiscreteUniform {
-    /// Generate a random sample from a discrete uniform
-    /// distribution using `r` as the source of randomness.
-    /// Refer [here](#method.sample-1) for implementation details
-    fn sample<R: Rng>(&mut self, r: &mut R) -> f64 {
-        super::Distribution::sample(self, r)
-    }
-}
-
-impl IndependentSample<f64> for DiscreteUniform {
-    /// Generate a random independent sample from a discrete uniform
-    /// distribution using `r` as the source of randomness.
-    /// Refer [here](#method.sample-1) for implementation details
-    fn ind_sample<R: Rng>(&self, r: &mut R) -> f64 {
-        super::Distribution::sample(self, r)
-    }
-}
-
 impl Distribution<f64> for DiscreteUniform {
-    /// Generate a random sample from the discrete uniform distribution
-    /// using `r` as the source of randomness in the range `[min, max]`
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// # extern crate rand;
-    /// # extern crate statrs;
-    /// use rand::StdRng;
-    /// use statrs::distribution::{DiscreteUniform, Distribution};
-    ///
-    /// # fn main() {
-    /// let mut r = rand::StdRng::new().unwrap();
-    /// let n = DiscreteUniform::new(0, 5).unwrap();
-    /// print!("{}", n.sample::<StdRng>(&mut r));
-    /// # }
-    /// ```
-    fn sample<R: Rng>(&self, r: &mut R) -> f64 {
+    fn sample<R: Rng + ?Sized>(&self, r: &mut R) -> f64 {
         r.gen_range(self.min, self.max + 1) as f64
     }
 }
 
-impl WeakRngDistribution<f64> for DiscreteUniform {}
-
 impl Univariate<i64, f64> for DiscreteUniform {
     /// Calculates the cumulative distribution function for the
     /// discrete uniform distribution at `x`
diff --git a/src/distribution/erlang.rs b/src/distribution/erlang.rs
index b2217ba5..ffc78de0 100644
--- a/src/distribution/erlang.rs
+++ b/src/distribution/erlang.rs
@@ -1,5 +1,5 @@
-use distribution::{Continuous, Distribution, Gamma, Univariate, WeakRngDistribution};
-use rand::distributions::{IndependentSample, Sample};
+use distribution::{Continuous, Gamma, Univariate};
+use rand::distributions::Distribution;
 use rand::Rng;
 use statistics::*;
 use Result;
@@ -79,49 +79,12 @@ impl Erlang {
     }
 }
 
-impl Sample<f64> for Erlang {
-    /// Generate a random sample from a erlang
-    /// distribution using `r` as the source of randomness.
-    /// Refer [here](#method.sample-1) for implementation details
-    fn sample<R: Rng>(&mut self, r: &mut R) -> f64 {
-        super::Distribution::sample(self, r)
-    }
-}
-
-impl IndependentSample<f64> for Erlang {
-    /// Generate a random independent sample from a erlang
-    /// distribution using `r` as the source of randomness.
-    /// Refer [here](#method.sample-1) for implementation details
-    fn ind_sample<R: Rng>(&self, r: &mut R) -> f64 {
-        super::Distribution::sample(self, r)
-    }
-}
-
 impl Distribution<f64> for Erlang {
-    /// Generate a random sample from a erlang distribution using
-    /// `r` as the source of randomness.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// # extern crate rand;
-    /// # extern crate statrs;
-    /// use rand::StdRng;
-    /// use statrs::distribution::{Erlang, Distribution};
-    ///
-    /// # fn main() {
-    /// let mut r = rand::StdRng::new().unwrap();
-    /// let n = Erlang::new(3, 1.0).unwrap();
-    /// print!("{}", n.sample::<StdRng>(&mut r));
-    /// # }
-    /// ```
-    fn sample<R: Rng>(&self, r: &mut R) -> f64 {
-        self.g.sample(r)
+    fn sample<R: Rng + ?Sized>(&self, r: &mut R) -> f64 {
+        Distribution::sample(&self.g, r)
     }
 }
 
-impl WeakRngDistribution<f64> for Erlang {}
-
 impl Univariate<f64, f64> for Erlang {
     /// Calculates the cumulative distribution function for the erlang
     /// distribution
diff --git a/src/distribution/exponential.rs b/src/distribution/exponential.rs
index 02284600..ec5c2b18 100644
--- a/src/distribution/exponential.rs
+++ b/src/distribution/exponential.rs
@@ -1,5 +1,5 @@
-use distribution::{ziggurat, Continuous, Distribution, Univariate, WeakRngDistribution};
-use rand::distributions::{IndependentSample, Sample};
+use distribution::{ziggurat, Continuous, Univariate};
+use rand::distributions::Distribution;
 use rand::Rng;
 use statistics::*;
 use std::f64;
@@ -68,49 +68,12 @@ impl Exponential {
     }
 }
 
-impl Sample<f64> for Exponential {
-    /// Generate a random sample from an exponential
-    /// distribution using `r` as the source of randomness.
-    /// Refer [here](#method.sample-1) for implementation details
-    fn sample<R: Rng>(&mut self, r: &mut R) -> f64 {
-        super::Distribution::sample(self, r)
-    }
-}
-
-impl IndependentSample<f64> for Exponential {
-    /// Generate a random independent sample from an exponential
-    /// distribution using `r` as the source of randomness.
-    /// Refer [here](#method.sample-1) for implementation details
-    fn ind_sample<R: Rng>(&self, r: &mut R) -> f64 {
-        super::Distribution::sample(self, r)
-    }
-}
-
 impl Distribution<f64> for Exponential {
-    /// Generate a random sample from the exponential distribution
-    /// using `r` as the source of randomness
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// # extern crate rand;
-    /// # extern crate statrs;
-    /// use rand::StdRng;
-    /// use statrs::distribution::{Exponential, Distribution};
-    ///
-    /// # fn main() {
-    /// let mut r = rand::StdRng::new().unwrap();
-    /// let n = Exponential::new(1.0).unwrap();
-    /// print!("{}", n.sample::<StdRng>(&mut r));
-    /// # }
-    /// ```
-    fn sample<R: Rng>(&self, r: &mut R) -> f64 {
+    fn sample<R: Rng + ?Sized>(&self, r: &mut R) -> f64 {
         ziggurat::sample_exp_1(r) / self.rate
     }
 }
 
-impl WeakRngDistribution<f64> for Exponential {}
-
 impl Univariate<f64, f64> for Exponential {
     /// Calculates the cumulative distribution function for the
     /// exponential distribution at `x`
diff --git a/src/distribution/fisher_snedecor.rs b/src/distribution/fisher_snedecor.rs
index b1828e73..89feb374 100644
--- a/src/distribution/fisher_snedecor.rs
+++ b/src/distribution/fisher_snedecor.rs
@@ -1,6 +1,6 @@
-use distribution::{Continuous, Distribution, Univariate, WeakRngDistribution};
+use distribution::{Continuous, Univariate};
 use function::beta;
-use rand::distributions::{IndependentSample, Sample};
+use rand::distributions::Distribution;
 use rand::Rng;
 use statistics::*;
 use std::f64;
@@ -93,50 +93,13 @@ impl FisherSnedecor {
     }
 }
 
-impl Sample<f64> for FisherSnedecor {
-    /// Generate a random sample from a fisher-snedecor distribution
-    /// using `r` as the source of randomness.
-    /// Refer [here](#method.sample-1) for implementation details.
-    fn sample<R: Rng>(&mut self, r: &mut R) -> f64 {
-        super::Distribution::sample(self, r)
-    }
-}
-
-impl IndependentSample<f64> for FisherSnedecor {
-    /// Generate a random independent sample from a fisher-snedecor distribution
-    /// using `r` as the source of randomness.
-    /// Refer [here](#method.sample-1) for implementation details.
-    fn ind_sample<R: Rng>(&self, r: &mut R) -> f64 {
-        super::Distribution::sample(self, r)
-    }
-}
-
 impl Distribution<f64> for FisherSnedecor {
-    /// Generate a random sample from a fisher-snedecor distribution using
-    /// `r` as the source of randomness.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// # extern crate rand;
-    /// # extern crate statrs;
-    /// use rand::StdRng;
-    /// use statrs::distribution::{FisherSnedecor, Distribution};
-    ///
-    /// # fn main() {
-    /// let mut r = rand::StdRng::new().unwrap();
-    /// let n = FisherSnedecor::new(2.0, 2.0).unwrap();
-    /// print!("{}", n.sample::<StdRng>(&mut r));
-    /// # }
-    /// ```
-    fn sample<R: Rng>(&self, r: &mut R) -> f64 {
+    fn sample<R: Rng + ?Sized>(&self, r: &mut R) -> f64 {
         (super::gamma::sample_unchecked(r, self.freedom_1 / 2.0, 0.5) * self.freedom_2)
             / (super::gamma::sample_unchecked(r, self.freedom_2 / 2.0, 0.5) * self.freedom_1)
     }
 }
 
-impl WeakRngDistribution<f64> for FisherSnedecor {}
-
 impl Univariate<f64, f64> for FisherSnedecor {
     /// Calculates the cumulative distribution function for the fisher-snedecor
     /// distribution
diff --git a/src/distribution/gamma.rs b/src/distribution/gamma.rs
index a3671daa..c234500e 100644
--- a/src/distribution/gamma.rs
+++ b/src/distribution/gamma.rs
@@ -1,6 +1,6 @@
-use distribution::{Continuous, Distribution, Univariate, WeakRngDistribution};
+use distribution::{Continuous, Univariate};
 use function::gamma;
-use rand::distributions::{IndependentSample, Sample};
+use rand::distributions::Distribution;
 use rand::Rng;
 use statistics::*;
 use std::f64;
@@ -87,60 +87,12 @@ impl Gamma {
     }
 }
 
-impl Sample<f64> for Gamma {
-    /// Generate a random sample from a gamma
-    /// distribution using `r` as the source of randomness.
-    /// Refer [here](#method.sample-1) for implementation details
-    fn sample<R: Rng>(&mut self, r: &mut R) -> f64 {
-        super::Distribution::sample(self, r)
-    }
-}
-
-impl IndependentSample<f64> for Gamma {
-    /// Generate a random independent sample from a gamma
-    /// distribution using `r` as the source of randomness.
-    /// Refer [here](#method.sample-1) for implementation details
-    fn ind_sample<R: Rng>(&self, r: &mut R) -> f64 {
-        super::Distribution::sample(self, r)
-    }
-}
-
 impl Distribution<f64> for Gamma {
-    /// Generate a random sample from a gamma distribution using
-    /// `r` as the source of randomness. The implementation is based
-    /// on:
-    /// <br />
-    /// <div>
-    /// <i>"A Simple Method for Generating Gamma Variables"</i> - Marsaglia &
-    /// Tsang
-    /// </div>
-    /// <div>
-    /// ACM Transactions on Mathematical Software, Vol. 26, No. 3, September
-    /// 2000, Pages 363-372
-    /// </div>
-    /// <br />
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// # extern crate rand;
-    /// # extern crate statrs;
-    /// use rand::StdRng;
-    /// use statrs::distribution::{Gamma, Distribution};
-    ///
-    /// # fn main() {
-    /// let mut r = rand::StdRng::new().unwrap();
-    /// let n = Gamma::new(3.0, 1.0).unwrap();
-    /// print!("{}", n.sample::<StdRng>(&mut r));
-    /// # }
-    /// ```
-    fn sample<R: Rng>(&self, r: &mut R) -> f64 {
+    fn sample<R: Rng + ?Sized>(&self, r: &mut R) -> f64 {
         sample_unchecked(r, self.shape, self.rate)
     }
 }
 
-impl WeakRngDistribution<f64> for Gamma {}
-
 impl Univariate<f64, f64> for Gamma {
     /// Calculates the cumulative distribution function for the gamma
     /// distribution
@@ -389,14 +341,14 @@ impl Continuous<f64, f64> for Gamma {
 /// Pages 363-372
 /// </div>
 /// <br />
-pub fn sample_unchecked<R: Rng>(r: &mut R, shape: f64, rate: f64) -> f64 {
+pub fn sample_unchecked<R: Rng + ?Sized>(r: &mut R, shape: f64, rate: f64) -> f64 {
     if rate == f64::INFINITY {
         return shape;
     }
 
     let a = if shape < 1.0 { shape + 1.0 } else { shape };
     let afix = if shape < 1.0 {
-        r.next_f64().powf(1.0 / shape)
+        r.gen::<f64>().powf(1.0 / shape)
     } else {
         1.0
     };
@@ -412,7 +364,7 @@ pub fn sample_unchecked<R: Rng>(r: &mut R, shape: f64, rate: f64) -> f64 {
 
         v *= v * v;
         x *= x;
-        let u = r.next_f64();
+        let u: f64 = r.gen();
         if u < 1.0 - 0.0331 * x * x {
             return afix * d * v / rate;
         }
diff --git a/src/distribution/geometric.rs b/src/distribution/geometric.rs
index a9a74d9f..f14584d0 100644
--- a/src/distribution/geometric.rs
+++ b/src/distribution/geometric.rs
@@ -1,5 +1,6 @@
-use distribution::{Discrete, Distribution, Univariate, WeakRngDistribution};
-use rand::distributions::{IndependentSample, Sample};
+use distribution::{Discrete, Univariate};
+use rand::distributions::Distribution;
+use rand::distributions::OpenClosed01;
 use rand::Rng;
 use statistics::*;
 use std::{f64, u64};
@@ -68,53 +69,17 @@ impl Geometric {
     }
 }
 
-impl Sample<f64> for Geometric {
-    /// Generate a random sample from a geometric
-    /// distribution using `r` as the source of randomness.
-    /// Refer [here](#method.sample-1) for implementation details
-    fn sample<R: Rng>(&mut self, r: &mut R) -> f64 {
-        super::Distribution::sample(self, r)
-    }
-}
-
-impl IndependentSample<f64> for Geometric {
-    /// Generate a random independent sample from a geometric
-    /// distribution using `r` as the source of randomness.
-    /// Refer [here](#method.sample-1) for implementation details
-    fn ind_sample<R: Rng>(&self, r: &mut R) -> f64 {
-        super::Distribution::sample(self, r)
-    }
-}
-
 impl Distribution<f64> for Geometric {
-    /// Generates a random sample from the geometric distribution
-    /// using `r` as the source of randomness
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// # extern crate rand;
-    /// # extern crate statrs;
-    /// use rand::StdRng;
-    /// use statrs::distribution::{Geometric, Distribution};
-    ///
-    /// # fn main() {
-    /// let mut r = rand::StdRng::new().unwrap();
-    /// let n = Geometric::new(0.5).unwrap();
-    /// print!("{}", n.sample::<StdRng>(&mut r));
-    /// # }
-    /// ```
-    fn sample<R: Rng>(&self, r: &mut R) -> f64 {
+    fn sample<R: Rng + ?Sized>(&self, r: &mut R) -> f64 {
         if self.p == 1.0 {
             1.0
         } else {
-            (1.0 - r.next_f64()).log(1.0 - self.p).ceil()
+            let x: f64 = r.sample(OpenClosed01);
+            x.log(1.0 - self.p).ceil()
         }
     }
 }
 
-impl WeakRngDistribution<f64> for Geometric {}
-
 impl Univariate<u64, f64> for Geometric {
     /// Calculates the cumulative distribution function for the geometric
     /// distribution at `x`
diff --git a/src/distribution/hypergeometric.rs b/src/distribution/hypergeometric.rs
index 4df9423c..7b6eedc5 100644
--- a/src/distribution/hypergeometric.rs
+++ b/src/distribution/hypergeometric.rs
@@ -1,6 +1,6 @@
-use distribution::{Discrete, Distribution, Univariate, WeakRngDistribution};
+use distribution::{Discrete, Univariate};
 use function::factorial;
-use rand::distributions::{IndependentSample, Sample};
+use rand::distributions::Distribution;
 use rand::Rng;
 use statistics::*;
 use std::cmp;
@@ -111,50 +111,15 @@ impl Hypergeometric {
     }
 }
 
-impl Sample<f64> for Hypergeometric {
-    /// Generate a random sample from a hypergeometric
-    /// distribution using `r` as the source of randomness.
-    /// Refer [here](#method.sample-1) for implementation details
-    fn sample<R: Rng>(&mut self, r: &mut R) -> f64 {
-        super::Distribution::sample(self, r)
-    }
-}
-
-impl IndependentSample<f64> for Hypergeometric {
-    /// Generate a random independent sample from a hypergeometric
-    /// distribution using `r` as the source of randomness.
-    /// Refer [here](#method.sample-1) for implementation details
-    fn ind_sample<R: Rng>(&self, r: &mut R) -> f64 {
-        super::Distribution::sample(self, r)
-    }
-}
-
 impl Distribution<f64> for Hypergeometric {
-    /// Generates a random sample from the hypergeometric distribution
-    /// using `r` as the source of randomness
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// # extern crate rand;
-    /// # extern crate statrs;
-    /// use rand::StdRng;
-    /// use statrs::distribution::{Hypergeometric, Distribution};
-    ///
-    /// # fn main() {
-    /// let mut r = rand::StdRng::new().unwrap();
-    /// let n = Hypergeometric::new(10, 5, 3).unwrap();
-    /// print!("{}", n.sample::<StdRng>(&mut r));
-    /// # }
-    /// ```
-    fn sample<R: Rng>(&self, r: &mut R) -> f64 {
+    fn sample<R: Rng + ?Sized>(&self, r: &mut R) -> f64 {
         let mut population = self.population as f64;
         let mut successes = self.successes as f64;
         let mut draws = self.draws;
         let mut x = 0.0;
         loop {
             let p = successes / population;
-            let next = r.next_f64();
+            let next: f64 = r.gen();
             if next < p {
                 x += 1.0;
                 successes -= 1.0;
@@ -169,8 +134,6 @@ impl Distribution<f64> for Hypergeometric {
     }
 }
 
-impl WeakRngDistribution<f64> for Hypergeometric {}
-
 impl Univariate<u64, f64> for Hypergeometric {
     /// Calculates the cumulative distribution function for the hypergeometric
     /// distribution at `x`
diff --git a/src/distribution/inverse_gamma.rs b/src/distribution/inverse_gamma.rs
index 0c98dbe3..c60f8f7d 100644
--- a/src/distribution/inverse_gamma.rs
+++ b/src/distribution/inverse_gamma.rs
@@ -1,6 +1,6 @@
-use distribution::{Continuous, Distribution, Univariate, WeakRngDistribution};
+use distribution::{Continuous, Univariate};
 use function::gamma;
-use rand::distributions::{IndependentSample, Sample};
+use rand::distributions::Distribution;
 use rand::Rng;
 use statistics::*;
 use std::f64;
@@ -91,49 +91,12 @@ impl InverseGamma {
     }
 }
 
-impl Sample<f64> for InverseGamma {
-    /// Generate a random sample from an inverse gamma
-    /// distribution using `r` as the source of randomness.
-    /// Refer [here](#method.sample-1) for implementation details
-    fn sample<R: Rng>(&mut self, r: &mut R) -> f64 {
-        super::Distribution::sample(self, r)
-    }
-}
-
-impl IndependentSample<f64> for InverseGamma {
-    /// Generate a random independent sample from an inverse gamma
-    /// distribution using `r` as the source of randomness.
-    /// Refer [here](#method.sample-1) for implementation details
-    fn ind_sample<R: Rng>(&self, r: &mut R) -> f64 {
-        super::Distribution::sample(self, r)
-    }
-}
-
 impl Distribution<f64> for InverseGamma {
-    /// Generate a random sample from an inverse gamma distribution
-    /// using `r` as the source of randomness.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// # extern crate rand;
-    /// # extern crate statrs;
-    /// use rand::StdRng;
-    /// use statrs::distribution::{InverseGamma, Distribution};
-    ///
-    /// # fn main() {
-    /// let mut r = rand::StdRng::new().unwrap();
-    /// let n = InverseGamma::new(3.0, 1.0).unwrap();
-    /// print!("{}", n.sample::<StdRng>(&mut r));
-    /// # }
-    /// ```
-    fn sample<R: Rng>(&self, r: &mut R) -> f64 {
+    fn sample<R: Rng + ?Sized>(&self, r: &mut R) -> f64 {
         1.0 / super::gamma::sample_unchecked(r, self.shape, self.rate)
     }
 }
 
-impl WeakRngDistribution<f64> for InverseGamma {}
-
 impl Univariate<f64, f64> for InverseGamma {
     /// Calculates the cumulative distribution function for the inverse gamma
     /// distribution at `x`
diff --git a/src/distribution/log_normal.rs b/src/distribution/log_normal.rs
index 3817654a..d74645f3 100644
--- a/src/distribution/log_normal.rs
+++ b/src/distribution/log_normal.rs
@@ -1,6 +1,6 @@
-use distribution::{Continuous, Distribution, Univariate, WeakRngDistribution};
+use distribution::{Continuous, Univariate};
 use function::erf;
-use rand::distributions::{IndependentSample, Sample};
+use rand::distributions::Distribution;
 use rand::Rng;
 use statistics::*;
 use std::f64;
@@ -59,50 +59,12 @@ impl LogNormal {
     }
 }
 
-impl Sample<f64> for LogNormal {
-    /// Generate a random sample from a log-normal
-    /// distribution using `r` as the source of randomness.
-    /// Refer [here](#method.sample-1) for implementation details
-    fn sample<R: Rng>(&mut self, r: &mut R) -> f64 {
-        super::Distribution::sample(self, r)
-    }
-}
-
-impl IndependentSample<f64> for LogNormal {
-    /// Generate a random independent sample from a log-normal
-    /// distribution using `r` as the source of randomness.
-    /// Refer [here](#method.sample-1) for implementation details
-    fn ind_sample<R: Rng>(&self, r: &mut R) -> f64 {
-        super::Distribution::sample(self, r)
-    }
-}
-
 impl Distribution<f64> for LogNormal {
-    /// Generate a random sample from the log-normal distribution
-    /// using `r` as the source of randomness. Uses the Box-Muller
-    /// algorithm
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// # extern crate rand;
-    /// # extern crate statrs;
-    /// use rand::StdRng;
-    /// use statrs::distribution::{LogNormal, Distribution};
-    ///
-    /// # fn main() {
-    /// let mut r = rand::StdRng::new().unwrap();
-    /// let n = LogNormal::new(0.0, 1.0).unwrap();
-    /// print!("{}", n.sample::<StdRng>(&mut r));
-    /// # }
-    /// ```
-    fn sample<R: Rng>(&self, r: &mut R) -> f64 {
+    fn sample<R: Rng + ?Sized>(&self, r: &mut R) -> f64 {
         super::normal::sample_unchecked(r, self.location, self.scale).exp()
     }
 }
 
-impl WeakRngDistribution<f64> for LogNormal {}
-
 impl Univariate<f64, f64> for LogNormal {
     /// Calculates the cumulative distribution function for the log-normal
     /// distribution
diff --git a/src/distribution/mod.rs b/src/distribution/mod.rs
index 777c97ff..93714a73 100644
--- a/src/distribution/mod.rs
+++ b/src/distribution/mod.rs
@@ -2,8 +2,6 @@
 //! and provides
 //! concrete implementations for a variety of distributions.
 
-use rand::{weak_rng, Rng, XorShiftRng};
-
 pub use self::bernoulli::Bernoulli;
 pub use self::beta::Beta;
 pub use self::binomial::Binomial;
@@ -62,66 +60,11 @@ mod ziggurat_tables;
 
 use Result;
 
-/// The `Distribution` trait is used to specify an interface
-/// for sampling statistical distributions
-pub trait Distribution<T> {
-    /// Draws a random sample using the supplied random number generator
-    ///
-    /// # Examples
-    ///
-    /// A trivial implementation that just samples from the supplied
-    /// random number generator
-    ///
-    /// ```
-    /// # extern crate rand;
-    /// # extern crate statrs;
-    ///
-    /// use rand::Rng;
-    /// use statrs::distribution::Distribution;
-    ///
-    /// struct Foo;
-    ///
-    /// impl Distribution<f64> for Foo {
-    ///     fn sample<R: Rng>(&self, r: &mut R) -> f64 {
-    ///         r.next_f64()
-    ///     }
-    /// }
-    ///
-    /// # fn main() { }
-    /// ```
-    fn sample<R: Rng>(&self, r: &mut R) -> T;
-}
-
-/// The `WeakRngDistribution` trait is used to specify an interface
-/// for sampling statistical distributions using a supplied default RNG
-/// (`weak_rng` from the `rand` crate)
-pub trait WeakRngDistribution<T>: Distribution<T> {
-    /// Draws a random sample using a default RNG (`weak_rng` from `rand`)
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// # extern crate statrs;
-    ///
-    /// use statrs::distribution::{Bernoulli, WeakRngDistribution};
-    ///
-    ///
-    /// # fn main() {
-    /// let n = Bernoulli::new(0.5).unwrap();
-    /// print!("{}", n.weak_sample());
-    /// }
-    /// ```
-    fn weak_sample(&self) -> T {
-        let mut r = weak_rng();
-        self.sample::<XorShiftRng>(&mut r)
-    }
-}
-
 /// The `Univariate` trait is used to specify an interface for univariate
 /// distributions e.g. distributions that have a closed form cumulative
 /// distribution
 /// function
-pub trait Univariate<T, K>: Distribution<K> + Min<T> + Max<T> {
+pub trait Univariate<T, K>: Min<T> + Max<T> {
     /// Returns the cumulative distribution function calculated
     /// at `x` for a given distribution. May panic depending
     /// on the implementor.
diff --git a/src/distribution/multinomial.rs b/src/distribution/multinomial.rs
index 3f9d9712..497ea2d0 100644
--- a/src/distribution/multinomial.rs
+++ b/src/distribution/multinomial.rs
@@ -1,6 +1,6 @@
-use distribution::{CheckedDiscrete, Discrete, Distribution, WeakRngDistribution};
+use distribution::{CheckedDiscrete, Discrete};
 use function::factorial;
-use rand::distributions::{IndependentSample, Sample};
+use rand::distributions::Distribution;
 use rand::Rng;
 use statistics::*;
 use {Result, StatsError};
@@ -92,43 +92,8 @@ impl Multinomial {
     }
 }
 
-impl Sample<Vec<f64>> for Multinomial {
-    /// Generate random samples from a multinomial
-    /// distribution using `r` as the source of randomness.
-    /// Refer [here](#method.sample-1) for implementation details
-    fn sample<R: Rng>(&mut self, r: &mut R) -> Vec<f64> {
-        super::Distribution::sample(self, r)
-    }
-}
-
-impl IndependentSample<Vec<f64>> for Multinomial {
-    /// Generate random independent samples from a M=multinomial
-    /// distribution using `r` as the source of randomness.
-    /// Refer [here](#method.sample-1) for implementation details
-    fn ind_sample<R: Rng>(&self, r: &mut R) -> Vec<f64> {
-        super::Distribution::sample(self, r)
-    }
-}
-
 impl Distribution<Vec<f64>> for Multinomial {
-    /// Generate random samples from the multinomial distribution
-    /// using `r` as the source of randomness
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// # extern crate rand;
-    /// # extern crate statrs;
-    /// use rand::StdRng;
-    /// use statrs::distribution::{Multinomial, Distribution};
-    ///
-    /// # fn main() {
-    /// let mut r = rand::StdRng::new().unwrap();
-    /// let n = Multinomial::new(&[0.0, 1.0, 2.0], 4).unwrap();
-    /// print!("{:?}", n.sample::<StdRng>(&mut r));
-    /// # }
-    /// ```
-    fn sample<R: Rng>(&self, r: &mut R) -> Vec<f64> {
+    fn sample<R: Rng + ?Sized>(&self, r: &mut R) -> Vec<f64> {
         let p_cdf = super::categorical::prob_mass_to_cdf(self.p());
         let mut res = vec![0.0; self.p.len()];
         for _ in 0..self.n {
@@ -140,8 +105,6 @@ impl Distribution<Vec<f64>> for Multinomial {
     }
 }
 
-impl WeakRngDistribution<Vec<f64>> for Multinomial {}
-
 impl Mean<Vec<f64>> for Multinomial {
     /// Returns the mean of the multinomial distribution
     ///
@@ -286,12 +249,11 @@ impl<'a> CheckedDiscrete<&'a [u64], f64> for Multinomial {
             return Err(StatsError::ContainerExpectedSumVar("x", "n"));
         }
         let coeff = factorial::multinomial(self.n, x);
-        let val = coeff
-            * self
-                .p
-                .iter()
-                .zip(x.iter())
-                .fold(1.0, |acc, (pi, xi)| acc * pi.powf(*xi as f64));
+        let val = coeff * self
+            .p
+            .iter()
+            .zip(x.iter())
+            .fold(1.0, |acc, (pi, xi)| acc * pi.powf(*xi as f64));
         Ok(val)
     }
 
@@ -322,13 +284,12 @@ impl<'a> CheckedDiscrete<&'a [u64], f64> for Multinomial {
             return Err(StatsError::ContainerExpectedSumVar("x", "n"));
         }
         let coeff = factorial::multinomial(self.n, x).ln();
-        let val = coeff
-            + self
-                .p
-                .iter()
-                .zip(x.iter())
-                .map(|(pi, xi)| *xi as f64 * pi.ln())
-                .fold(0.0, |acc, x| acc + x);
+        let val = coeff + self
+            .p
+            .iter()
+            .zip(x.iter())
+            .map(|(pi, xi)| *xi as f64 * pi.ln())
+            .fold(0.0, |acc, x| acc + x);
         Ok(val)
     }
 }
diff --git a/src/distribution/normal.rs b/src/distribution/normal.rs
index 856a7bfe..35d99539 100644
--- a/src/distribution/normal.rs
+++ b/src/distribution/normal.rs
@@ -1,6 +1,6 @@
-use distribution::{ziggurat, Continuous, Distribution, Univariate, WeakRngDistribution};
+use distribution::{ziggurat, Continuous, Univariate};
 use function::erf;
-use rand::distributions::{IndependentSample, Sample};
+use rand::distributions::Distribution;
 use rand::Rng;
 use statistics::*;
 use std::f64;
@@ -57,50 +57,12 @@ impl Normal {
     }
 }
 
-impl Sample<f64> for Normal {
-    /// Generate a random sample from a normal
-    /// distribution using `r` as the source of randomness.
-    /// Refer [here](#method.sample-1) for implementation details
-    fn sample<R: Rng>(&mut self, r: &mut R) -> f64 {
-        super::Distribution::sample(self, r)
-    }
-}
-
-impl IndependentSample<f64> for Normal {
-    /// Generate a random independent sample from a normal
-    /// distribution using `r` as the source of randomness.
-    /// Refer [here](#method.sample-1) for implementation details
-    fn ind_sample<R: Rng>(&self, r: &mut R) -> f64 {
-        super::Distribution::sample(self, r)
-    }
-}
-
 impl Distribution<f64> for Normal {
-    /// Generate a random sample from the normal distribution
-    /// using `r` as the source of randomness. Uses the Box-Muller
-    /// algorithm
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// # extern crate rand;
-    /// # extern crate statrs;
-    /// use rand::StdRng;
-    /// use statrs::distribution::{Normal, Distribution};
-    ///
-    /// # fn main() {
-    /// let mut r = rand::StdRng::new().unwrap();
-    /// let n = Normal::new(0.0, 1.0).unwrap();
-    /// print!("{}", n.sample::<StdRng>(&mut r));
-    /// # }
-    /// ```
-    fn sample<R: Rng>(&self, r: &mut R) -> f64 {
+    fn sample<R: Rng + ?Sized>(&self, r: &mut R) -> f64 {
         sample_unchecked(r, self.mean, self.std_dev)
     }
 }
 
-impl WeakRngDistribution<f64> for Normal {}
-
 impl Univariate<f64, f64> for Normal {
     /// Calculates the cumulative distribution function for the
     /// normal distribution at `x`
@@ -291,8 +253,8 @@ pub fn ln_pdf_unchecked(x: f64, mean: f64, std_dev: f64) -> f64 {
     (-0.5 * d * d) - consts::LN_SQRT_2PI - std_dev.ln()
 }
 
-/// `sample_unchecked` draws a sample from a normal distribution
-pub fn sample_unchecked<R: Rng>(r: &mut R, mean: f64, std_dev: f64) -> f64 {
+/// draws a sample from a normal distribution using the Box-Muller algorithm
+pub fn sample_unchecked<R: Rng + ?Sized>(r: &mut R, mean: f64, std_dev: f64) -> f64 {
     mean + std_dev * ziggurat::sample_std_normal(r)
 }
 
diff --git a/src/distribution/pareto.rs b/src/distribution/pareto.rs
index a76f1798..a3827627 100644
--- a/src/distribution/pareto.rs
+++ b/src/distribution/pareto.rs
@@ -1,5 +1,6 @@
-use distribution::{Continuous, Distribution, Univariate, WeakRngDistribution};
-use rand::distributions::{IndependentSample, Sample};
+use distribution::{Continuous, Univariate};
+use rand::distributions::Distribution;
+use rand::distributions::OpenClosed01;
 use rand::Rng;
 use statistics::*;
 use std::f64;
@@ -86,53 +87,14 @@ impl Pareto {
     }
 }
 
-impl Sample<f64> for Pareto {
-    /// Generate a random sample from a Pareto distribution
-    /// distribution using `r` as the source of randomness.
-    /// Refer [here](#method.sample-1) for implementation details
-    fn sample<R: Rng>(&mut self, r: &mut R) -> f64 {
-        super::Distribution::sample(self, r)
-    }
-}
-
-impl IndependentSample<f64> for Pareto {
-    /// Generate a random independent sample from a Pareto distribution
-    /// distribution using `r` as the source of randomness.
-    /// Refer [here](#method.sample-1) for implementation details
-    fn ind_sample<R: Rng>(&self, r: &mut R) -> f64 {
-        super::Distribution::sample(self, r)
-    }
-}
-
 impl Distribution<f64> for Pareto {
-    /// Generate a random sample from a Pareto distribution using
-    /// `r` as the source of randomness. The implementation uses inverse
-    /// transform sampling.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// # extern crate rand;
-    /// # extern crate statrs;
-    /// use rand::StdRng;
-    /// use statrs::distribution::{Pareto, Distribution};
-    ///
-    /// # fn main() {
-    /// let mut r = rand::StdRng::new().unwrap();
-    /// let n = Pareto::new(1.0, 2.0).unwrap();
-    /// print!("{}", n.sample::<StdRng>(&mut r));
-    /// # }
-    /// ```
-    fn sample<R: Rng>(&self, r: &mut R) -> f64 {
-        // Draw a sample from (0, 1]
-        // next_f64() samples from [0, 1), so we have to subtract it from 1
-        let u = 1.0 - r.next_f64();
+    fn sample<R: Rng + ?Sized>(&self, r: &mut R) -> f64 {
+        // Inverse transform sampling
+        let u: f64 = r.sample(OpenClosed01);
         self.scale * u.powf(-1.0 / self.shape)
     }
 }
 
-impl WeakRngDistribution<f64> for Pareto {}
-
 impl Univariate<f64, f64> for Pareto {
     /// Calculates the cumulative distribution function for the Pareto
     /// distribution at `x`
diff --git a/src/distribution/poisson.rs b/src/distribution/poisson.rs
index 500f4de0..dab29e61 100644
--- a/src/distribution/poisson.rs
+++ b/src/distribution/poisson.rs
@@ -1,6 +1,6 @@
-use distribution::{Discrete, Distribution, Univariate, WeakRngDistribution};
+use distribution::{Discrete, Univariate};
 use function::{factorial, gamma};
-use rand::distributions::{IndependentSample, Sample};
+use rand::distributions::Distribution;
 use rand::Rng;
 use statistics::*;
 use std::f64;
@@ -68,52 +68,12 @@ impl Poisson {
     }
 }
 
-impl Sample<f64> for Poisson {
-    /// Generate a random sample from a poisson
-    /// distribution using `r` as the source of randomness.
-    /// Refer [here](#method.sample-1) for implementation details
-    fn sample<R: Rng>(&mut self, r: &mut R) -> f64 {
-        super::Distribution::sample(self, r)
-    }
-}
-
-impl IndependentSample<f64> for Poisson {
-    /// Generate a random independent sample from a poisson
-    /// distribution using `r` as the source of randomness.
-    /// Refer [here](#method.sample-1) for implementation details
-    fn ind_sample<R: Rng>(&self, r: &mut R) -> f64 {
-        super::Distribution::sample(self, r)
-    }
-}
-
 impl Distribution<f64> for Poisson {
-    /// Generate a random sample from a poisson distribution using
-    /// `r` as the source of randomness. The implementation is based
-    /// on Knuth's method if `lambda < 30.0` or Rejection method PA by
-    /// A. C. Atkinson from the <i>Journal of the Royal Statistical Society
-    /// Series C (Applied Statistics)</i> Vol. 28 No. 1. (1979) pp. 29 - 35
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// # extern crate rand;
-    /// # extern crate statrs;
-    /// use rand::StdRng;
-    /// use statrs::distribution::{Poisson, Distribution};
-    ///
-    /// # fn main() {
-    /// let mut r = rand::StdRng::new().unwrap();
-    /// let n = Poisson::new(1.0).unwrap();
-    /// print!("{}", n.sample::<StdRng>(&mut r));
-    /// # }
-    /// ```
-    fn sample<R: Rng>(&self, r: &mut R) -> f64 {
+    fn sample<R: Rng + ?Sized>(&self, r: &mut R) -> f64 {
         sample_unchecked(r, self.lambda)
     }
 }
 
-impl WeakRngDistribution<f64> for Poisson {}
-
 impl Univariate<u64, f64> for Poisson {
     /// Calculates the cumulative distribution function for the poisson
     /// distribution at `x`
@@ -306,14 +266,14 @@ impl Discrete<u64, f64> for Poisson {
 /// A. C. Atkinson from the Journal of the Royal Statistical Society
 /// Series C (Applied Statistics) Vol. 28 No. 1. (1979) pp. 29 - 35
 /// otherwise
-fn sample_unchecked<R: Rng>(r: &mut R, lambda: f64) -> f64 {
+fn sample_unchecked<R: Rng + ?Sized>(r: &mut R, lambda: f64) -> f64 {
     if lambda < 30.0 {
         let limit = (-lambda).exp();
         let mut count = 0.0;
-        let mut product = r.next_f64();
+        let mut product: f64 = r.gen();
         while product >= limit {
             count += 1.0;
-            product *= r.next_f64();
+            product *= r.gen::<f64>();
         }
         count
     } else {
@@ -323,14 +283,14 @@ fn sample_unchecked<R: Rng>(r: &mut R, lambda: f64) -> f64 {
         let k = c.ln() - lambda - beta.ln();
 
         loop {
-            let u = r.next_f64();
+            let u: f64 = r.gen();
             let x = (alpha - ((1.0 - u) / u).ln()) / beta;
             let n = (x + 0.5).floor();
             if n < 0.0 {
                 continue;
             }
 
-            let v = r.next_f64();
+            let v: f64 = r.gen();
             let y = alpha - beta * x;
             let temp = 1.0 + y.exp();
             let lhs = y + (v / (temp * temp)).ln();
diff --git a/src/distribution/students_t.rs b/src/distribution/students_t.rs
index 731344e2..f5ae62f4 100644
--- a/src/distribution/students_t.rs
+++ b/src/distribution/students_t.rs
@@ -1,6 +1,6 @@
-use distribution::{Continuous, Distribution, Univariate, WeakRngDistribution};
+use distribution::{Continuous, Univariate};
 use function::{beta, gamma};
-use rand::distributions::{IndependentSample, Sample};
+use rand::distributions::Distribution;
 use rand::Rng;
 use statistics::*;
 use std::f64;
@@ -104,45 +104,10 @@ impl StudentsT {
     }
 }
 
-impl Sample<f64> for StudentsT {
-    /// Generate a random sample from a student's t-distribution
-    /// distribution using `r` as the source of randomness.
-    /// Refer [here](#method.sample-1) for implementation details
-    fn sample<R: Rng>(&mut self, r: &mut R) -> f64 {
-        super::Distribution::sample(self, r)
-    }
-}
-
-impl IndependentSample<f64> for StudentsT {
-    /// Generate a random independent sample from a student's t-distribution
-    /// distribution using `r` as the source of randomness.
-    /// Refer [here](#method.sample-1) for implementation details
-    fn ind_sample<R: Rng>(&self, r: &mut R) -> f64 {
-        super::Distribution::sample(self, r)
-    }
-}
-
 impl Distribution<f64> for StudentsT {
-    /// Generate a random sample from a student's t-distribution using
-    /// `r` as the source of randomness. The implementation is based
-    /// on method 2, section 5 in chapter 9 of L. Devroye's
-    /// <i>"Non-Uniform Random Variate Generation"</i>
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// # extern crate rand;
-    /// # extern crate statrs;
-    /// use rand::StdRng;
-    /// use statrs::distribution::{StudentsT, Distribution};
-    ///
-    /// # fn main() {
-    /// let mut r = rand::StdRng::new().unwrap();
-    /// let n = StudentsT::new(0.0, 1.0, 2.0).unwrap();
-    /// print!("{}", n.sample::<StdRng>(&mut r));
-    /// # }
-    /// ```
-    fn sample<R: Rng>(&self, r: &mut R) -> f64 {
+    fn sample<R: Rng + ?Sized>(&self, r: &mut R) -> f64 {
+        // based on method 2, section 5 in chapter 9 of L. Devroye's
+        // "Non-Uniform Random Variate Generation"
         let gamma = super::gamma::sample_unchecked(r, 0.5 * self.freedom, 0.5);
         super::normal::sample_unchecked(
             r,
@@ -152,8 +117,6 @@ impl Distribution<f64> for StudentsT {
     }
 }
 
-impl WeakRngDistribution<f64> for StudentsT {}
-
 impl Univariate<f64, f64> for StudentsT {
     /// Calculates the cumulative distribution function for the student's
     /// t-distribution
@@ -508,8 +471,10 @@ impl Continuous<f64, f64> for StudentsT {
         } else {
             let d = (x - self.location) / self.scale;
             (gamma::ln_gamma((self.freedom + 1.0) / 2.0) - gamma::ln_gamma(self.freedom / 2.0))
-                .exp() * (1.0 + d * d / self.freedom).powf(-0.5 * (self.freedom + 1.0))
-                / (self.freedom * f64::consts::PI).sqrt() / self.scale
+                .exp()
+                * (1.0 + d * d / self.freedom).powf(-0.5 * (self.freedom + 1.0))
+                / (self.freedom * f64::consts::PI).sqrt()
+                / self.scale
         }
     }
 
diff --git a/src/distribution/triangular.rs b/src/distribution/triangular.rs
index 60ab7409..89a87e4f 100644
--- a/src/distribution/triangular.rs
+++ b/src/distribution/triangular.rs
@@ -1,5 +1,5 @@
-use distribution::{Continuous, Distribution, Univariate, WeakRngDistribution};
-use rand::distributions::{IndependentSample, Sample};
+use distribution::{Continuous, Univariate};
+use rand::distributions::Distribution;
 use rand::Rng;
 use statistics::*;
 use std::f64;
@@ -67,49 +67,12 @@ impl Triangular {
     }
 }
 
-impl Sample<f64> for Triangular {
-    /// Generate a random sample from a triangular distribution
-    /// distribution using `r` as the source of randomness.
-    /// Refer [here](#method.sample-1) for implementation details
-    fn sample<R: Rng>(&mut self, r: &mut R) -> f64 {
-        super::Distribution::sample(self, r)
-    }
-}
-
-impl IndependentSample<f64> for Triangular {
-    /// Generate a random independent sample from a triangular distribution
-    /// distribution using `r` as the source of randomness.
-    /// Refer [here](#method.sample-1) for implementation details
-    fn ind_sample<R: Rng>(&self, r: &mut R) -> f64 {
-        super::Distribution::sample(self, r)
-    }
-}
-
 impl Distribution<f64> for Triangular {
-    /// Generate a random sample from a triangular distribution using
-    /// `r` as the source of randomness.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// # extern crate rand;
-    /// # extern crate statrs;
-    /// use rand::StdRng;
-    /// use statrs::distribution::{Triangular, Distribution};
-    ///
-    /// # fn main() {
-    /// let mut r = rand::StdRng::new().unwrap();
-    /// let n = Triangular::new(0.0, 5.0, 2.5).unwrap();
-    /// print!("{}", n.sample::<StdRng>(&mut r));
-    /// # }
-    /// ```
-    fn sample<R: Rng>(&self, r: &mut R) -> f64 {
+    fn sample<R: Rng + ?Sized>(&self, r: &mut R) -> f64 {
         sample_unchecked(r, self.min, self.max, self.mode)
     }
 }
 
-impl WeakRngDistribution<f64> for Triangular {}
-
 impl Univariate<f64, f64> for Triangular {
     /// Calculates the cumulative distribution function for the triangular
     /// distribution
@@ -333,8 +296,8 @@ impl Continuous<f64, f64> for Triangular {
     }
 }
 
-fn sample_unchecked<R: Rng>(r: &mut R, min: f64, max: f64, mode: f64) -> f64 {
-    let f = r.next_f64();
+fn sample_unchecked<R: Rng + ?Sized>(r: &mut R, min: f64, max: f64, mode: f64) -> f64 {
+    let f: f64 = r.gen();
     if f < (mode - min) / (max - min) {
         min + (f * (max - min) * (mode - min)).sqrt()
     } else {
diff --git a/src/distribution/uniform.rs b/src/distribution/uniform.rs
index dd80cb1d..c5732baf 100644
--- a/src/distribution/uniform.rs
+++ b/src/distribution/uniform.rs
@@ -1,5 +1,6 @@
-use distribution::{Continuous, Distribution, Univariate, WeakRngDistribution};
-use rand::distributions::{IndependentSample, Sample};
+use distribution::{Continuous, Univariate};
+use rand::distributions::Distribution;
+use rand::distributions::Uniform as RandUniform;
 use rand::Rng;
 use statistics::*;
 use std::f64;
@@ -54,51 +55,13 @@ impl Uniform {
     }
 }
 
-impl Sample<f64> for Uniform {
-    /// Generate a random sample from a continuous uniform
-    /// distribution using `r` as the source of randomness.
-    /// Refer [here](#method.sample-1) for implementation details
-    fn sample<R: Rng>(&mut self, r: &mut R) -> f64 {
-        super::Distribution::sample(self, r)
-    }
-}
-
-impl IndependentSample<f64> for Uniform {
-    /// Generate a random independent sample from a continuous uniform
-    /// distribution using `r` as the source of randomness.
-    /// Refer [here](#method.sample-1) for implementation details
-    fn ind_sample<R: Rng>(&self, r: &mut R) -> f64 {
-        super::Distribution::sample(self, r)
-    }
-}
-
 impl Distribution<f64> for Uniform {
-    /// Generate a random sample from the continuous uniform distribution
-    /// using `r` as the source of randomness in the range `[min, max]`
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// # extern crate rand;
-    /// # extern crate statrs;
-    /// use rand::StdRng;
-    /// use statrs::distribution::{Uniform, Distribution};
-    ///
-    /// # fn main() {
-    /// let mut r = rand::StdRng::new().unwrap();
-    /// let n = Uniform::new(0.0, 5.0).unwrap();
-    /// print!("{}", n.sample::<StdRng>(&mut r));
-    /// # }
-    /// ```
-    fn sample<R: Rng>(&self, r: &mut R) -> f64 {
-        use rand::{Closed01, Rand};
-        let Closed01(rand01) = Closed01::<f64>::rand(r);
-        self.min + rand01 * (self.max - self.min)
+    fn sample<R: Rng + ?Sized>(&self, r: &mut R) -> f64 {
+        let d = RandUniform::new_inclusive(self.min, self.max);
+        r.sample(d)
     }
 }
 
-impl WeakRngDistribution<f64> for Uniform {}
-
 impl Univariate<f64, f64> for Uniform {
     /// Calculates the cumulative distribution function for the uniform
     /// distribution
@@ -472,10 +435,13 @@ mod test {
 
     #[test]
     fn test_samples_in_range() {
-        use super::Distribution;
-
         use rand::{StdRng, SeedableRng};
-        let seed: &[_] = &[1, 2, 3, 4, 5];
+        use rand::distributions::Distribution;
+
+        let seed = [
+            0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
+            19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
+        ];
         let mut r: StdRng = SeedableRng::from_seed(seed);
 
         let min = -0.5;
diff --git a/src/distribution/weibull.rs b/src/distribution/weibull.rs
index a337bb3a..37b2b4f2 100644
--- a/src/distribution/weibull.rs
+++ b/src/distribution/weibull.rs
@@ -1,6 +1,6 @@
-use distribution::{Continuous, Distribution, Univariate, WeakRngDistribution};
+use distribution::{Continuous, Univariate};
 use function::gamma;
-use rand::distributions::{IndependentSample, Sample};
+use rand::distributions::Distribution;
 use rand::Rng;
 use statistics::*;
 use std::f64;
@@ -90,50 +90,13 @@ impl Weibull {
     }
 }
 
-impl Sample<f64> for Weibull {
-    /// Generate a random sample from a weibull
-    /// distribution using `r` as the source of randomness.
-    /// Refer [here](#method.sample-1) for implementation details
-    fn sample<R: Rng>(&mut self, r: &mut R) -> f64 {
-        super::Distribution::sample(self, r)
-    }
-}
-
-impl IndependentSample<f64> for Weibull {
-    /// Generate a random sample from a weibull
-    /// distribution using `r` as the source of randomness.
-    /// Refer [here](#method.sample-1) for implementation details
-    fn ind_sample<R: Rng>(&self, r: &mut R) -> f64 {
-        super::Distribution::sample(self, r)
-    }
-}
-
 impl Distribution<f64> for Weibull {
-    /// Generate a random sample from the weibull distribution
-    /// using `r` as the source of randomness
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// # extern crate rand;
-    /// # extern crate statrs;
-    /// use rand::StdRng;
-    /// use statrs::distribution::{Weibull, Distribution};
-    ///
-    /// # fn main() {
-    /// let mut r = rand::StdRng::new().unwrap();
-    /// let n = Weibull::new(10.0, 1.0).unwrap();
-    /// print!("{}", n.sample::<StdRng>(&mut r));
-    /// # }
-    /// ```
-    fn sample<R: Rng>(&self, r: &mut R) -> f64 {
-        let x = r.next_f64();
+    fn sample<R: Rng + ?Sized>(&self, r: &mut R) -> f64 {
+        let x: f64 = r.gen();
         self.scale * (-x.ln()).powf(1.0 / self.shape)
     }
 }
 
-impl WeakRngDistribution<f64> for Weibull {}
-
 impl Univariate<f64, f64> for Weibull {
     /// Calculates the cumulative distribution function for the weibull
     /// distribution at `x`
@@ -263,7 +226,8 @@ impl Skewness<f64> for Weibull {
         let sigma3 = sigma2 * sigma;
         (self.scale * self.scale * self.scale * gamma::gamma(1.0 + 3.0 / self.shape)
             - 3.0 * sigma2 * mu
-            - (mu * mu * mu)) / sigma3
+            - (mu * mu * mu))
+            / sigma3
     }
 }
 
@@ -326,7 +290,8 @@ impl Continuous<f64, f64> for Weibull {
         } else {
             self.shape
                 * (x / self.scale).powf(self.shape - 1.0)
-                * (-(x.powf(self.shape)) * self.scale_pow_shape_inv).exp() / self.scale
+                * (-(x.powf(self.shape)) * self.scale_pow_shape_inv).exp()
+                / self.scale
         }
     }
 
diff --git a/src/distribution/ziggurat.rs b/src/distribution/ziggurat.rs
index 58dc584f..6de9d68d 100644
--- a/src/distribution/ziggurat.rs
+++ b/src/distribution/ziggurat.rs
@@ -1,19 +1,20 @@
 use super::ziggurat_tables;
-use rand::{Open01, Rng};
+use rand::distributions::Open01;
+use rand::Rng;
 
-pub fn sample_std_normal<R: Rng>(r: &mut R) -> f64 {
+pub fn sample_std_normal<R: Rng + ?Sized>(r: &mut R) -> f64 {
     #[inline]
     fn pdf(x: f64) -> f64 {
         (-x * x / 2.0).exp()
     }
 
     #[inline]
-    fn zero_case<R: Rng>(r: &mut R, u: f64) -> f64 {
+    fn zero_case<R: Rng + ?Sized>(r: &mut R, u: f64) -> f64 {
         let mut x = 1.0f64;
         let mut y = 0.0f64;
         while -2.0 * y < x * x {
-            let Open01(x_) = r.gen::<Open01<f64>>();
-            let Open01(y_) = r.gen::<Open01<f64>>();
+            let x_: f64 = r.sample(Open01);
+            let y_: f64 = r.sample(Open01);
 
             x = x_.ln() / ziggurat_tables::ZIG_NORM_R;
             y = y_.ln();
@@ -35,14 +36,14 @@ pub fn sample_std_normal<R: Rng>(r: &mut R) -> f64 {
     )
 }
 
-pub fn sample_exp_1<R: Rng>(r: &mut R) -> f64 {
+pub fn sample_exp_1<R: Rng + ?Sized>(r: &mut R) -> f64 {
     #[inline]
     fn pdf(x: f64) -> f64 {
         (-x).exp()
     }
 
     #[inline]
-    fn zero_case<R: Rng>(r: &mut R, _u: f64) -> f64 {
+    fn zero_case<R: Rng + ?Sized>(r: &mut R, _u: f64) -> f64 {
         ziggurat_tables::ZIG_EXP_R - r.gen::<f64>().ln()
     }
 
@@ -61,7 +62,7 @@ pub fn sample_exp_1<R: Rng>(r: &mut R) -> f64 {
 // https://github.com/rust-lang-nursery/rand/blob/master/src/distributions/mod.
 // rs#L223
 #[inline(always)]
-fn ziggurat<R: Rng, P, Z>(
+fn ziggurat<R: Rng + ?Sized, P, Z>(
     rng: &mut R,
     symmetric: bool,
     x_tab: ziggurat_tables::ZigTable,
diff --git a/src/function/beta.rs b/src/function/beta.rs
index fdb91f40..7d7fc591 100644
--- a/src/function/beta.rs
+++ b/src/function/beta.rs
@@ -122,8 +122,7 @@ pub fn checked_beta_reg(a: f64, b: f64, x: f64) -> Result<f64> {
         } else {
             (gamma::ln_gamma(a + b) - gamma::ln_gamma(a) - gamma::ln_gamma(b)
                 + a * x.ln()
-                + b * (1.0 - x).ln())
-                .exp()
+                + b * (1.0 - x).ln()).exp()
         };
         let symm_transform = x >= (a + 1.0) / (a + b + 2.0);
         let eps = prec::F64_PREC;
diff --git a/src/generate.rs b/src/generate.rs
index 9b97d683..dc4c19f3 100644
--- a/src/generate.rs
+++ b/src/generate.rs
@@ -113,7 +113,10 @@ impl Periodic {
     /// let x = Periodic::new(10, 8.0, 2.0, 10.0, 1.0, 2).collect::<Vec<f64>>();
     /// assert_eq!(x, [6.0, 8.5, 1.0, 3.5, 6.0, 8.5, 1.0, 3.5, 6.0, 8.5]);
     /// ```
-    #[deprecated(since = "0.9.0", note = "please use `InfinitePeriodic::new` and `take` instead")]
+    #[deprecated(
+        since = "0.9.0",
+        note = "please use `InfinitePeriodic::new` and `take` instead"
+    )]
     pub fn new(
         length: usize,
         sampling_rate: f64,
@@ -139,7 +142,8 @@ impl Periodic {
     /// assert_eq!(x, [0.0, 0.25, 0.5, 0.75, 0.0, 0.25, 0.5, 0.75, 0.0, 0.25]);
     /// ```
     #[deprecated(
-        since = "0.9.0", note = "please use `InfinitePeriodic::default` and `take` instead"
+        since = "0.9.0",
+        note = "please use `InfinitePeriodic::default` and `take` instead"
     )]
     pub fn default(length: usize, sampling_rate: f64, frequency: f64) -> Periodic {
         Periodic {
@@ -255,7 +259,10 @@ impl Sinusoidal {
     ///     4.583853163452858, 4.090702573174318, 5.416146836547142,
     ///     5.909297426825682]);
     /// ```
-    #[deprecated(since = "0.9.0", note = "please use `InfiniteSinusoidal::new` and `take` instead")]
+    #[deprecated(
+        since = "0.9.0",
+        note = "please use `InfiniteSinusoidal::new` and `take` instead"
+    )]
     pub fn new(
         length: usize,
         sampling_rate: f64,
@@ -292,7 +299,8 @@ impl Sinusoidal {
     ///     -0.0000000000000004898587196589413, 1.0]);
     /// ```
     #[deprecated(
-        since = "0.9.0", note = "please use `InfiniteSinusoidal::default` and `take` instead"
+        since = "0.9.0",
+        note = "please use `InfiniteSinusoidal::default` and `take` instead"
     )]
     pub fn default(
         length: usize,
@@ -385,7 +393,10 @@ impl Square {
     /// assert_eq!(x, [-1.0, 1.0, 1.0, 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0,
     /// -1.0, 1.0])
     /// ```
-    #[deprecated(since = "0.9.0", note = "please use `InfiniteSquare::new` and `take` instead")]
+    #[deprecated(
+        since = "0.9.0",
+        note = "please use `InfiniteSquare::new` and `take` instead"
+    )]
     pub fn new(
         length: usize,
         high_duration: i64,
@@ -506,7 +517,10 @@ impl Triangle {
     /// }
     /// # }
     /// ```
-    #[deprecated(since = "0.9.0", note = "please use `InfiniteTriangle::new` and `take` instead")]
+    #[deprecated(
+        since = "0.9.0",
+        note = "please use `InfiniteTriangle::new` and `take` instead"
+    )]
     pub fn new(
         length: usize,
         raise_duration: i64,
@@ -597,7 +611,10 @@ impl Sawtooth {
     /// assert_eq!(x, [1.0, -1.0, -0.5, 0.0, 0.5, 1.0, -1.0, -0.5, 0.0, 0.5,
     /// 1.0, -1.0]);
     /// ```
-    #[deprecated(since = "0.9.0", note = "please use `InfiniteSawtooth::new` and `take` instead")]
+    #[deprecated(
+        since = "0.9.0",
+        note = "please use `InfiniteSawtooth::new` and `take` instead"
+    )]
     pub fn new(
         length: usize,
         period: i64,
diff --git a/src/lib.rs b/src/lib.rs
index b7d054d9..aecb5104 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -11,15 +11,14 @@
 //! ```
 //! # extern crate rand;
 //! # extern crate statrs;
-
-//! use rand::StdRng;
-//! use statrs::distribution::{Distribution, Normal};
+//! use rand::distributions::Distribution;
+//! use statrs::distribution::Normal;
 //!
 //! # fn main() {
-//! let mut r = rand::StdRng::new().unwrap();
+//! let mut r = rand::thread_rng();
 //! let n = Normal::new(0.0, 1.0).unwrap();
 //! for _ in 0..10 {
-//!     print!("{}", n.sample::<StdRng>(&mut r));
+//!     print!("{}", n.sample(&mut r));
 //! }
 //! # }
 //! ```
diff --git a/src/statistics/iter_statistics.rs b/src/statistics/iter_statistics.rs
index 9288904a..106d8a8a 100644
--- a/src/statistics/iter_statistics.rs
+++ b/src/statistics/iter_statistics.rs
@@ -245,9 +245,10 @@ where
 mod test {
     use std::f64::consts;
     use rand::{SeedableRng, StdRng};
-    use distribution::{Distribution, Normal};
+    use rand::distributions::Distribution;
+    use distribution::Normal;
     use statistics::Statistics;
-    use generate::{Periodic, Sinusoidal};
+    use generate::{InfinitePeriodic, InfiniteSinusoidal};
     use testing;
 
     #[test]
@@ -313,7 +314,10 @@ mod test {
 
     #[test]
     fn test_mean_variance_stability() {
-        let seed: &[_] = &[1,2,3,4];
+        let seed = [
+            0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
+            19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
+        ];
         let mut rng: StdRng = SeedableRng::from_seed(seed);
         let normal = Normal::new(1e9, 2.0).unwrap();
         let samples = (0..10000).map(|_| normal.sample::<StdRng>(&mut rng)).collect::<Vec<f64>>();
@@ -382,8 +386,8 @@ mod test {
 
     #[test]
     fn test_large_samples() {
-        let shorter = Periodic::default(4*4096, 4.0, 1.0).collect::<Vec<f64>>();
-        let longer = Periodic::default(4*32768, 4.0, 1.0).collect::<Vec<f64>>();
+        let shorter = InfinitePeriodic::default(4.0, 1.0).take(4*4096).collect::<Vec<f64>>();
+        let longer = InfinitePeriodic::default(4.0, 1.0).take(4*32768).collect::<Vec<f64>>();
         assert_almost_eq!((&shorter).mean(), 0.375, 1e-14);
         assert_almost_eq!((&longer).mean(), 0.375, 1e-14);
         assert_almost_eq!((&shorter).quadratic_mean(), (0.21875f64).sqrt(), 1e-14);
@@ -392,7 +396,7 @@ mod test {
 
     #[test]
     fn test_quadratic_mean_of_sinusoidal() {
-        let data = Sinusoidal::default(128, 64.0, 16.0, 2.0).collect::<Vec<f64>>();
+        let data = InfiniteSinusoidal::default(64.0, 16.0, 2.0).take(128).collect::<Vec<f64>>();
         assert_almost_eq!((&data).quadratic_mean(), 2.0 / consts::SQRT_2, 1e-15);
     }
 }


Test patch: