From 75b650245fe0c7ce35980062f87a9484c1057d05 Mon Sep 17 00:00:00 2001 From: kennytm Date: Mon, 23 Dec 2019 01:20:59 +0800 Subject: [PATCH 1/3] impl Error for rand_distr::*Error. --- rand_distr/src/binomial.rs | 12 ++++++++ rand_distr/src/cauchy.rs | 11 ++++++++ rand_distr/src/dirichlet.rs | 16 ++++++++++- rand_distr/src/exponential.rs | 11 ++++++++ rand_distr/src/gamma.rs | 47 +++++++++++++++++++++++++++++++ rand_distr/src/lib.rs | 3 +- rand_distr/src/normal.rs | 11 ++++++++ rand_distr/src/pareto.rs | 12 ++++++++ rand_distr/src/pert.rs | 13 +++++++++ rand_distr/src/poisson.rs | 11 ++++++++ rand_distr/src/triangular.rs | 14 +++++++++ rand_distr/src/weibull.rs | 12 ++++++++ src/distributions/bernoulli.rs | 14 ++++++++- src/distributions/weighted/mod.rs | 3 -- 14 files changed, 184 insertions(+), 6 deletions(-) diff --git a/rand_distr/src/binomial.rs b/rand_distr/src/binomial.rs index 9c2b110ae5a..29919c88a06 100644 --- a/rand_distr/src/binomial.rs +++ b/rand_distr/src/binomial.rs @@ -11,6 +11,7 @@ use rand::Rng; use crate::{Distribution, Uniform}; +use std::{error, fmt}; /// The binomial distribution `Binomial(n, p)`. /// @@ -43,6 +44,17 @@ pub enum Error { ProbabilityTooLarge, } +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(match self { + Error::ProbabilityTooSmall => "p < 0 or is NaN in binomial distribution", + Error::ProbabilityTooLarge => "p > 1 in binomial distribution", + }) + } +} + +impl error::Error for Error {} + impl Binomial { /// Construct a new `Binomial` with the given shape parameters `n` (number /// of trials) and `p` (probability of success). diff --git a/rand_distr/src/cauchy.rs b/rand_distr/src/cauchy.rs index 7dcd7c9b6fb..297c19e6d9c 100644 --- a/rand_distr/src/cauchy.rs +++ b/rand_distr/src/cauchy.rs @@ -12,6 +12,7 @@ use rand::Rng; use crate::{Distribution, Standard}; use crate::utils::Float; +use std::{error, fmt}; /// The Cauchy distribution `Cauchy(median, scale)`. /// @@ -43,6 +44,16 @@ pub enum Error { ScaleTooSmall, } +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(match self { + Error::ScaleTooSmall => "scale is not positive in Cauchy distribution", + }) + } +} + +impl error::Error for Error {} + impl Cauchy where Standard: Distribution { diff --git a/rand_distr/src/dirichlet.rs b/rand_distr/src/dirichlet.rs index cba063ae755..7edfad312fd 100644 --- a/rand_distr/src/dirichlet.rs +++ b/rand_distr/src/dirichlet.rs @@ -12,8 +12,9 @@ use rand::Rng; use crate::{Distribution, Gamma, StandardNormal, Exp1, Open01}; use crate::utils::Float; +use std::{error, fmt}; -/// The dirichelet distribution `Dirichlet(alpha)`. +/// The Dirichlet distribution `Dirichlet(alpha)`. /// /// The Dirichlet distribution is a family of continuous multivariate /// probability distributions parameterized by a vector alpha of positive reals. @@ -46,6 +47,19 @@ pub enum Error { SizeTooSmall, } +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(match self { + Error::AlphaTooShort | Error::SizeTooSmall => { + "less than 2 dimensions in Dirichlet distribution" + } + Error::AlphaTooSmall => "alpha is not positive in Dirichlet distribution", + }) + } +} + +impl error::Error for Error {} + impl Dirichlet where StandardNormal: Distribution, Exp1: Distribution, Open01: Distribution { diff --git a/rand_distr/src/exponential.rs b/rand_distr/src/exponential.rs index 8695252a53f..ecd39beedb0 100644 --- a/rand_distr/src/exponential.rs +++ b/rand_distr/src/exponential.rs @@ -12,6 +12,7 @@ use rand::Rng; use crate::{ziggurat_tables, Distribution}; use crate::utils::{ziggurat, Float}; +use std::{error, fmt}; /// Samples floating-point numbers according to the exponential distribution, /// with rate parameter `λ = 1`. This is equivalent to `Exp::new(1.0)` or @@ -97,6 +98,16 @@ pub enum Error { LambdaTooSmall, } +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(match self { + Error::LambdaTooSmall => "lambda is not positive in exponential distribution", + }) + } +} + +impl error::Error for Error {} + impl Exp where Exp1: Distribution { diff --git a/rand_distr/src/gamma.rs b/rand_distr/src/gamma.rs index bbf861bd537..555a1a0c48c 100644 --- a/rand_distr/src/gamma.rs +++ b/rand_distr/src/gamma.rs @@ -16,6 +16,7 @@ use rand::Rng; use crate::normal::StandardNormal; use crate::{Distribution, Exp1, Exp, Open01}; use crate::utils::Float; +use std::{error, fmt}; /// The Gamma distribution `Gamma(shape, scale)` distribution. /// @@ -63,6 +64,18 @@ pub enum Error { ScaleTooLarge, } +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(match self { + Error::ShapeTooSmall => "shape is not positive in gamma distribution", + Error::ScaleTooSmall => "scale is not positive in gamma distribution", + Error::ScaleTooLarge => "scale is infinity in gamma distribution", + }) + } +} + +impl error::Error for Error {} + #[derive(Clone, Copy, Debug)] enum GammaRepr { Large(GammaLargeShape), @@ -224,6 +237,18 @@ pub enum ChiSquaredError { DoFTooSmall, } +impl fmt::Display for ChiSquaredError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(match self { + ChiSquaredError::DoFTooSmall => { + "degrees-of-freedom k is not positive in chi-squared distribution" + } + }) + } +} + +impl error::Error for ChiSquaredError {} + #[derive(Clone, Copy, Debug)] enum ChiSquaredRepr { // k == 1, Gamma(alpha, ..) is particularly slow for alpha < 1, @@ -298,6 +323,17 @@ pub enum FisherFError { NTooSmall, } +impl fmt::Display for FisherFError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(match self { + FisherFError::MTooSmall => "m is not positive in Fisher F distribution", + FisherFError::NTooSmall => "n is not positive in Fisher F distribution", + }) + } +} + +impl error::Error for FisherFError {} + impl FisherF where StandardNormal: Distribution, Exp1: Distribution, Open01: Distribution { @@ -390,6 +426,17 @@ pub enum BetaError { BetaTooSmall, } +impl fmt::Display for BetaError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(match self { + BetaError::AlphaTooSmall => "alpha is not positive in beta distribution", + BetaError::BetaTooSmall => "beta is not positive in beta distribution", + }) + } +} + +impl error::Error for BetaError {} + impl Beta where StandardNormal: Distribution, Exp1: Distribution, Open01: Distribution { diff --git a/rand_distr/src/lib.rs b/rand_distr/src/lib.rs index baf65ed07a7..454e93ede90 100644 --- a/rand_distr/src/lib.rs +++ b/rand_distr/src/lib.rs @@ -64,7 +64,8 @@ //! - [`UnitDisc`] distribution pub use rand::distributions::{Distribution, DistIter, Standard, - Alphanumeric, Uniform, OpenClosed01, Open01, Bernoulli, uniform, weighted}; + Alphanumeric, Uniform, OpenClosed01, Open01, Bernoulli, BernoulliError, + uniform, weighted}; pub use self::unit_sphere::UnitSphere; pub use self::unit_ball::UnitBall; diff --git a/rand_distr/src/normal.rs b/rand_distr/src/normal.rs index 0413ceaf541..e2148d8302d 100644 --- a/rand_distr/src/normal.rs +++ b/rand_distr/src/normal.rs @@ -12,6 +12,7 @@ use rand::Rng; use crate::{ziggurat_tables, Distribution, Open01}; use crate::utils::{ziggurat, Float}; +use std::{error, fmt}; /// Samples floating-point numbers according to the normal distribution /// `N(0, 1)` (a.k.a. a standard normal, or Gaussian). This is equivalent to @@ -114,6 +115,16 @@ pub enum Error { StdDevTooSmall, } +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(match self { + Error::StdDevTooSmall => "std_dev < 0 or is NaN in normal distribution", + }) + } +} + +impl error::Error for Error {} + impl Normal where StandardNormal: Distribution { diff --git a/rand_distr/src/pareto.rs b/rand_distr/src/pareto.rs index ccbce9c2566..75842c5fb92 100644 --- a/rand_distr/src/pareto.rs +++ b/rand_distr/src/pareto.rs @@ -11,6 +11,7 @@ use rand::Rng; use crate::{Distribution, OpenClosed01}; use crate::utils::Float; +use std::{error, fmt}; /// Samples floating-point numbers according to the Pareto distribution /// @@ -37,6 +38,17 @@ pub enum Error { ShapeTooSmall, } +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(match self { + Error::ScaleTooSmall => "scale is not positive in Pareto distribution", + Error::ShapeTooSmall => "shape is not positive in Pareto distribution", + }) + } +} + +impl error::Error for Error {} + impl Pareto where OpenClosed01: Distribution { diff --git a/rand_distr/src/pert.rs b/rand_distr/src/pert.rs index 040cd05cfed..7d6c41e30b9 100644 --- a/rand_distr/src/pert.rs +++ b/rand_distr/src/pert.rs @@ -10,6 +10,7 @@ use rand::Rng; use crate::{Distribution, Beta, StandardNormal, Exp1, Open01}; use crate::utils::Float; +use std::{error, fmt}; /// The PERT distribution. /// @@ -47,6 +48,18 @@ pub enum PertError { ShapeTooSmall, } +impl fmt::Display for PertError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(match self { + PertError::RangeTooSmall => "min..=max is not proper range in PERT distribution", + PertError::ModeRange => "mode is outside min..=max in PERT distribution", + PertError::ShapeTooSmall => "shape < 0 or is NaN in PERT distribution", + }) + } +} + +impl error::Error for PertError {} + impl Pert where StandardNormal: Distribution, Exp1: Distribution, Open01: Distribution { diff --git a/rand_distr/src/poisson.rs b/rand_distr/src/poisson.rs index d720ab4f413..504677e484f 100644 --- a/rand_distr/src/poisson.rs +++ b/rand_distr/src/poisson.rs @@ -12,6 +12,7 @@ use rand::Rng; use crate::{Distribution, Cauchy, Standard}; use crate::utils::Float; +use std::{error, fmt}; /// The Poisson distribution `Poisson(lambda)`. /// @@ -44,6 +45,16 @@ pub enum Error { ShapeTooSmall, } +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(match self { + Error::ShapeTooSmall => "lambda is not positive in Poisson distribution", + }) + } +} + +impl error::Error for Error {} + impl Poisson where Standard: Distribution { diff --git a/rand_distr/src/triangular.rs b/rand_distr/src/triangular.rs index dd0bbfbdf29..51486caa500 100644 --- a/rand_distr/src/triangular.rs +++ b/rand_distr/src/triangular.rs @@ -10,6 +10,7 @@ use rand::Rng; use crate::{Distribution, Standard}; use crate::utils::Float; +use std::{error, fmt}; /// The triangular distribution. /// @@ -46,6 +47,19 @@ pub enum TriangularError { ModeRange, } +impl fmt::Display for TriangularError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(match self { + TriangularError::RangeTooSmall => { + "min..=max is not proper range in triangular distribution" + } + TriangularError::ModeRange => "mode is outside min..=max in triangular distribution", + }) + } +} + +impl error::Error for TriangularError {} + impl Triangular where Standard: Distribution { diff --git a/rand_distr/src/weibull.rs b/rand_distr/src/weibull.rs index 388503284fa..84380419c92 100644 --- a/rand_distr/src/weibull.rs +++ b/rand_distr/src/weibull.rs @@ -11,6 +11,7 @@ use rand::Rng; use crate::{Distribution, OpenClosed01}; use crate::utils::Float; +use std::{error, fmt}; /// Samples floating-point numbers according to the Weibull distribution /// @@ -37,6 +38,17 @@ pub enum Error { ShapeTooSmall, } +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(match self { + Error::ScaleTooSmall => "scale is not positive in Weibull distribution", + Error::ShapeTooSmall => "shape is not positive in Weibull distribution", + }) + } +} + +impl error::Error for Error {} + impl Weibull where OpenClosed01: Distribution { diff --git a/src/distributions/bernoulli.rs b/src/distributions/bernoulli.rs index 7499e12a5d3..b5d96aca708 100644 --- a/src/distributions/bernoulli.rs +++ b/src/distributions/bernoulli.rs @@ -10,6 +10,7 @@ use crate::Rng; use crate::distributions::Distribution; +use core::{fmt, u64}; /// The Bernoulli distribution. /// @@ -55,7 +56,7 @@ pub struct Bernoulli { // the RNG, and pay the performance price for all uses that *are* reasonable. // Luckily, if `new()` and `sample` are close, the compiler can optimize out the // extra check. -const ALWAYS_TRUE: u64 = ::core::u64::MAX; +const ALWAYS_TRUE: u64 = u64::MAX; // This is just `2.0.powi(64)`, but written this way because it is not available // in `no_std` mode. @@ -68,6 +69,17 @@ pub enum BernoulliError { InvalidProbability, } +impl fmt::Display for BernoulliError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(match self { + BernoulliError::InvalidProbability => "p is outside 0..=1 in Bernoulli distribution", + }) + } +} + +#[cfg(feature = "std")] +impl ::std::error::Error for BernoulliError {} + impl Bernoulli { /// Construct a new `Bernoulli` with the given probability of success `p`. /// diff --git a/src/distributions/weighted/mod.rs b/src/distributions/weighted/mod.rs index c5e151be9b1..37433dbc3c6 100644 --- a/src/distributions/weighted/mod.rs +++ b/src/distributions/weighted/mod.rs @@ -380,9 +380,6 @@ impl ::std::error::Error for WeightedError { fn description(&self) -> &str { self.msg() } - fn cause(&self) -> Option<&dyn (::std::error::Error)> { - None - } } impl fmt::Display for WeightedError { From 68816c70ba9f407f8362d734790732b175236476 Mon Sep 17 00:00:00 2001 From: kennytm Date: Tue, 24 Dec 2019 05:04:25 +0800 Subject: [PATCH 2/3] Update CHANGELOG. --- CHANGELOG.md | 4 ++++ rand_distr/CHANGELOG.md | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 102a3b19768..95b4022ec9d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,10 @@ A [separate changelog is kept for rand_core](rand_core/CHANGELOG.md). You may also find the [Upgrade Guide](https://rust-random.github.io/book/update.html) useful. +## Unreleased +### Additions +- Implement `std::error::Error` for `BernoulliError` (#919) + ## [0.7.2] - 2019-09-16 ### Fixes - Fix dependency on `rand_core` 0.5.1 (#890) diff --git a/rand_distr/CHANGELOG.md b/rand_distr/CHANGELOG.md index 31a86d654ee..640b8626cb9 100644 --- a/rand_distr/CHANGELOG.md +++ b/rand_distr/CHANGELOG.md @@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## Unreleased +- All error types now implement `std::error::Error` (#919) +- Re-exported `rand::distributions::BernoulliError` (#919) + ## [0.2.2] - 2019-09-10 - Fix version requirement on rand lib (#847) - Clippy fixes & suppression (#840) From 413fc4b8d0db6b40b89bb33e00ece1025ae05980 Mon Sep 17 00:00:00 2001 From: kennytm Date: Tue, 31 Dec 2019 08:07:41 +0800 Subject: [PATCH 3/3] Fix comments --- rand_distr/src/pert.rs | 4 ++-- rand_distr/src/triangular.rs | 4 ++-- src/distributions/bernoulli.rs | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/rand_distr/src/pert.rs b/rand_distr/src/pert.rs index 7d6c41e30b9..bd8a0c40121 100644 --- a/rand_distr/src/pert.rs +++ b/rand_distr/src/pert.rs @@ -51,8 +51,8 @@ pub enum PertError { impl fmt::Display for PertError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str(match self { - PertError::RangeTooSmall => "min..=max is not proper range in PERT distribution", - PertError::ModeRange => "mode is outside min..=max in PERT distribution", + PertError::RangeTooSmall => "requirement min < max is not met in PERT distribution", + PertError::ModeRange => "mode is outside [min, max] in PERT distribution", PertError::ShapeTooSmall => "shape < 0 or is NaN in PERT distribution", }) } diff --git a/rand_distr/src/triangular.rs b/rand_distr/src/triangular.rs index 51486caa500..15e7e2662e8 100644 --- a/rand_distr/src/triangular.rs +++ b/rand_distr/src/triangular.rs @@ -51,9 +51,9 @@ impl fmt::Display for TriangularError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str(match self { TriangularError::RangeTooSmall => { - "min..=max is not proper range in triangular distribution" + "requirement min <= max is not met in triangular distribution" } - TriangularError::ModeRange => "mode is outside min..=max in triangular distribution", + TriangularError::ModeRange => "mode is outside [min, max] in triangular distribution", }) } } diff --git a/src/distributions/bernoulli.rs b/src/distributions/bernoulli.rs index b5d96aca708..e8099606e65 100644 --- a/src/distributions/bernoulli.rs +++ b/src/distributions/bernoulli.rs @@ -72,7 +72,7 @@ pub enum BernoulliError { impl fmt::Display for BernoulliError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str(match self { - BernoulliError::InvalidProbability => "p is outside 0..=1 in Bernoulli distribution", + BernoulliError::InvalidProbability => "p is outside [0, 1] in Bernoulli distribution", }) } }