From 296fd677186c9ffef295deefd0b8bfcf9adab3fb Mon Sep 17 00:00:00 2001 From: Soumya Sen Date: Fri, 5 Jun 2026 22:44:26 +0200 Subject: [PATCH 1/3] Add clippy fixes --- src/distribution/inverse_gamma.rs | 2 +- src/distribution/laplace.rs | 2 -- src/distribution/log_normal.rs | 1 - src/distribution/multivariate_normal.rs | 3 ++- src/distribution/negative_binomial.rs | 1 - src/distribution/poisson.rs | 1 - src/distribution/triangular.rs | 1 - src/distribution/uniform.rs | 1 - src/distribution/weibull.rs | 1 - src/function/evaluate.rs | 2 +- 10 files changed, 4 insertions(+), 11 deletions(-) diff --git a/src/distribution/inverse_gamma.rs b/src/distribution/inverse_gamma.rs index 9b029e43..d0cc3bab 100644 --- a/src/distribution/inverse_gamma.rs +++ b/src/distribution/inverse_gamma.rs @@ -344,7 +344,7 @@ impl Continuous for InverseGamma { mod tests { use super::*; use crate::distribution::internal::density_util; - use crate::distribution::internal::testing_boiler; + testing_boiler!(shape: f64, rate: f64; InverseGamma; InverseGammaError); diff --git a/src/distribution/laplace.rs b/src/distribution/laplace.rs index 12c4da36..a4e30398 100644 --- a/src/distribution/laplace.rs +++ b/src/distribution/laplace.rs @@ -323,8 +323,6 @@ mod tests { use super::*; use crate::prec; - use crate::distribution::internal::testing_boiler; - testing_boiler!(location: f64, scale: f64; Laplace; LaplaceError); // A wrapper for the `assert_relative_eq!` macro from the approx crate. diff --git a/src/distribution/log_normal.rs b/src/distribution/log_normal.rs index 4e937124..0b39af1c 100644 --- a/src/distribution/log_normal.rs +++ b/src/distribution/log_normal.rs @@ -364,7 +364,6 @@ impl Continuous for LogNormal { mod tests { use super::*; use crate::distribution::internal::density_util; - use crate::distribution::internal::testing_boiler; testing_boiler!(location: f64, scale: f64; LogNormal; LogNormalError); diff --git a/src/distribution/multivariate_normal.rs b/src/distribution/multivariate_normal.rs index 77be577b..abe94023 100644 --- a/src/distribution/multivariate_normal.rs +++ b/src/distribution/multivariate_normal.rs @@ -177,11 +177,12 @@ where /// /// # Panics /// If both the `cov` and `cholesky` arguments are `None`; at least one must be `Some(_)`. +type MeanCovarainceCholeskyReturn = (OVector, OMatrix, Cholesky); fn normalize_constructor_arguments( mean: OVector, covariance: Option>, cholesky: Option>, -) -> Result<(OVector, OMatrix, Cholesky), MultivariateNormalError> +) -> Result, MultivariateNormalError> where D: DimMin, nalgebra::DefaultAllocator: nalgebra::allocator::Allocator diff --git a/src/distribution/negative_binomial.rs b/src/distribution/negative_binomial.rs index 3e15ff48..7d9ba846 100644 --- a/src/distribution/negative_binomial.rs +++ b/src/distribution/negative_binomial.rs @@ -323,7 +323,6 @@ impl Discrete for NegativeBinomial { mod tests { use super::*; use crate::distribution::internal::density_util; - use crate::distribution::internal::testing_boiler; testing_boiler!(r: f64, p: f64; NegativeBinomial; NegativeBinomialError); diff --git a/src/distribution/poisson.rs b/src/distribution/poisson.rs index 78e06da2..5d04d379 100644 --- a/src/distribution/poisson.rs +++ b/src/distribution/poisson.rs @@ -342,7 +342,6 @@ pub fn sample_unchecked(rng: &mut R, lambda: f64) -> f6 mod tests { use super::*; use crate::distribution::internal::density_util; - use crate::distribution::internal::testing_boiler; testing_boiler!(lambda: f64; Poisson; PoissonError); #[test] diff --git a/src/distribution/triangular.rs b/src/distribution/triangular.rs index c8954901..e24fe110 100644 --- a/src/distribution/triangular.rs +++ b/src/distribution/triangular.rs @@ -438,7 +438,6 @@ fn sample_unchecked(rng: &mut R, min: f64, max: f64, mo mod tests { use super::*; use crate::distribution::internal::density_util; - use crate::distribution::internal::testing_boiler; testing_boiler!(min: f64, max: f64, mode: f64; Triangular; TriangularError); diff --git a/src/distribution/uniform.rs b/src/distribution/uniform.rs index bdb87444..9b26ef23 100644 --- a/src/distribution/uniform.rs +++ b/src/distribution/uniform.rs @@ -348,7 +348,6 @@ mod tests { use super::*; use crate::prec; use crate::distribution::internal::density_util; - use crate::distribution::internal::testing_boiler; testing_boiler!(min: f64, max: f64; Uniform; UniformError); diff --git a/src/distribution/weibull.rs b/src/distribution/weibull.rs index d3cc8748..3a563849 100644 --- a/src/distribution/weibull.rs +++ b/src/distribution/weibull.rs @@ -381,7 +381,6 @@ impl Continuous for Weibull { mod tests { use super::*; use crate::distribution::internal::density_util; - use crate::distribution::internal::testing_boiler; testing_boiler!(shape: f64, scale: f64; Weibull; WeibullError); diff --git a/src/function/evaluate.rs b/src/function/evaluate.rs index 5fe6e0a9..1aa18966 100644 --- a/src/function/evaluate.rs +++ b/src/function/evaluate.rs @@ -12,7 +12,7 @@ /// Returns 0 for a 0 length coefficient slice pub fn polynomial(z: f64, coeff: &[f64]) -> f64 { coeff - .into_iter() + .iter() .rev() .fold(0_f64, |acc, val| acc * z + val) } From 9be9cb026c321e1b8584a42430d1b3f610c0225c Mon Sep 17 00:00:00 2001 From: Soumya Sen Date: Fri, 5 Jun 2026 22:46:37 +0200 Subject: [PATCH 2/3] rust fmt --- src/function/evaluate.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/function/evaluate.rs b/src/function/evaluate.rs index 1aa18966..55646970 100644 --- a/src/function/evaluate.rs +++ b/src/function/evaluate.rs @@ -11,10 +11,7 @@ /// /// Returns 0 for a 0 length coefficient slice pub fn polynomial(z: f64, coeff: &[f64]) -> f64 { - coeff - .iter() - .rev() - .fold(0_f64, |acc, val| acc * z + val) + coeff.iter().rev().fold(0_f64, |acc, val| acc * z + val) } #[rustfmt::skip] From ad6861ec9cef15079636364d3cf97675c1ca4782 Mon Sep 17 00:00:00 2001 From: Soumya Sen Date: Fri, 5 Jun 2026 23:06:25 +0200 Subject: [PATCH 3/3] Initial commit to add a try method for beta --- src/distribution/beta.rs | 23 +++++++++++++++++++++++ src/distribution/mod.rs | 12 ++++++++++++ 2 files changed, 35 insertions(+) diff --git a/src/distribution/beta.rs b/src/distribution/beta.rs index 1fc94e7e..f7678fed 100644 --- a/src/distribution/beta.rs +++ b/src/distribution/beta.rs @@ -193,6 +193,29 @@ impl ContinuousCDF for Beta { beta::inv_beta_reg(self.shape_a, self.shape_b, x) } } + + /// Calculates the inverse cumulative distribution function for the beta + /// distribution at `x`. + /// + /// # Returns an error instead of a panic + /// + /// If x is not in `[0, 1]`. + /// + /// # Formula + /// + /// ```text + /// I^{-1}_x(α, β) + /// ``` + /// + /// where `α` is shapeA, `β` is shapeB, and `I_x` is the inverse of the + /// regularized lower incomplete beta function. + fn try_inverse_cdf(&self, x: f64) -> Result> { + if !(0.0..=1.0).contains(&x) { + Err("x must be in [0, 1]".into()) + } else { + Ok(beta::inv_beta_reg(self.shape_a, self.shape_b, x)) + } + } } impl Min for Beta { diff --git a/src/distribution/mod.rs b/src/distribution/mod.rs index 5b508e7f..ba0c9e83 100644 --- a/src/distribution/mod.rs +++ b/src/distribution/mod.rs @@ -166,6 +166,18 @@ pub trait ContinuousCDF: Min + Max { } (high + low) / two } + + /// Due to issues with rounding and floating-point accuracy the default + /// implementation may be ill-behaved. + /// Specialized inverse cdfs should be used whenever possible. + /// Performs a binary search on the domain of `cdf` to obtain an approximation + /// of `F^-1(p) := inf { x | F(x) >= p }`. Needless to say, performance may + /// may be lacking. + #[doc(alias = "quantile function")] + #[doc(alias = "quantile")] + fn try_inverse_cdf(&self, p: T) -> Result> { + Ok(self.inverse_cdf(p)) + } } /// The `DiscreteCDF` trait is used to specify an interface for univariate