Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 53 additions & 4 deletions src/consts.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,31 @@
//! Defines mathematical expressions commonly used when computing distribution
//! values as constants
//! Mathematical and statistical constants for the library.
//!
//! # Kernel Constants
//!
//! ## Core Properties
//! - **Variance (μ₂)**: Second moment `∫ u² K(u) du`
//! - **Roughness (R)**: Squared integral `∫ K(u)² du`
//! - **Efficiency**: AMISE efficiency relative to Epanechnikov (1.0 = optimal)
//! - **Bandwidth Factors**: AMISE-optimal scaling relative to Epanechnikov
//!
//! ## Usage
//! If Silverman's rule gives bandwidth `h` for Epanechnikov, then:
//! - Gaussian: `h * 0.45` (narrower)
//! - Triangular: `h * 1.10` (wider)
//!
//! ## References
//! - Silverman (1986), *Density Estimation*, Table 3.1
//! - Wand & Jones (1995), *Kernel Smoothing*, Table 2.2
// ====================
// General mathematical constants
// ====================

/// Constant value for `sqrt(2 * pi)`
pub const SQRT_2PI: f64 = 2.5066282746310005024157652848110452530069867406099;

/// Constant value for `sqrt(pi)`
pub const SQRT_PI: f64 = 1.7724538509055160272981674833411451827975494561223871;

/// Constant value for `ln(pi)`
pub const LN_PI: f64 = 1.1447298858494001741434273513530587116472948129153;

Expand All @@ -19,7 +41,34 @@ pub const LN_2_SQRT_E_OVER_PI: f64 = 0.62078223763524522234551844578164721225185
/// Constant value for `2 * sqrt(e / pi)`
pub const TWO_SQRT_E_OVER_PI: f64 = 1.8603827342052657173362492472666631120594218414085755;

/// Constant value for Euler-Masheroni constant `lim(n -> inf) { sum(k=1 -> n)
/// { 1/k - ln(n) } }`
/// Constant value for Euler-Mascheroni constant `γ = lim_{n→∞} (∑_{k=1}^n 1/k - ln n)`
pub const EULER_MASCHERONI: f64 =
0.5772156649015328606065120900824024310421593359399235988057672348849;

// ====================
// Kernel constants
// ====================

use core::f64::consts::PI;

// Kernel Variance: μ₂ = ∫ u² K(u) du
pub const VARIANCE_GAUSSIAN: f64 = 1.0;
pub const VARIANCE_EPANECHNIKOV: f64 = 1.0 / 5.0;
pub const VARIANCE_TRIANGULAR: f64 = 1.0 / 6.0;
pub const VARIANCE_TRICUBE: f64 = 35.0 / 243.0;
pub const VARIANCE_BISQUARE: f64 = 1.0 / 7.0;
pub const VARIANCE_UNIFORM: f64 = 1.0 / 3.0;
pub const VARIANCE_COSINE: f64 = 1.0 - 8.0 / (PI * PI);
pub const VARIANCE_LOGISTIC: f64 = PI * PI / 3.0;
pub const VARIANCE_SIGMOID: f64 = PI * PI / 4.0;

// Kernel Roughness: R(K) = ∫ K(u)² du
pub const ROUGHNESS_GAUSSIAN: f64 = 1.0 / (2.0 * SQRT_PI);
pub const ROUGHNESS_EPANECHNIKOV: f64 = 3.0 / 5.0;
pub const ROUGHNESS_TRIANGULAR: f64 = 2.0 / 3.0;
pub const ROUGHNESS_TRICUBE: f64 = 175.0 / 247.0;
pub const ROUGHNESS_BISQUARE: f64 = 5.0 / 7.0;
pub const ROUGHNESS_UNIFORM: f64 = 1.0 / 2.0;
pub const ROUGHNESS_COSINE: f64 = PI * PI / 16.0;
pub const ROUGHNESS_LOGISTIC: f64 = 1.0 / 6.0;
pub const ROUGHNESS_SIGMOID: f64 = 2.0 / (PI * PI);
23 changes: 23 additions & 0 deletions src/distribution/geometric.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,29 @@ impl DiscreteCDF<u64, f64> for Geometric {
((-self.p).ln_1p() * (x as f64)).exp()
}
}

/// Calculates the inverse cumulative distribution function for the geometric
/// distribution at `p`
///
/// # Formula
///
/// ```text
/// ceil(log(1-p) / log(1-self.p))
/// ```
fn inverse_cdf(&self, p: f64) -> u64 {
if p <= 0.0 {
return self.min();
}
if prec::ulps_eq!(self.p, 1.0) {
return 1;
}
if p >= 1.0 {
return self.max();
}
// ceil(log(1-p) / log(1-self.p))
let result = ((1.0 - p).ln() / (1.0 - self.p).ln()).ceil();
result.max(1.0) as u64
}
}

impl Min<u64> for Geometric {
Expand Down
1 change: 0 additions & 1 deletion src/distribution/inverse_gamma.rs
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,6 @@ impl Continuous<f64, f64> 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);

Expand Down
2 changes: 0 additions & 2 deletions src/distribution/laplace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
1 change: 0 additions & 1 deletion src/distribution/log_normal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -364,7 +364,6 @@ impl Continuous<f64, f64> 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);

Expand Down
1 change: 0 additions & 1 deletion src/distribution/negative_binomial.rs
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,6 @@ impl Discrete<u64, f64> 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);

Expand Down
1 change: 0 additions & 1 deletion src/distribution/poisson.rs
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,6 @@ pub fn sample_unchecked<R: ::rand::Rng + ?Sized>(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]
Expand Down
1 change: 0 additions & 1 deletion src/distribution/triangular.rs
Original file line number Diff line number Diff line change
Expand Up @@ -438,7 +438,6 @@ fn sample_unchecked<R: ::rand::Rng + ?Sized>(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);

Expand Down
1 change: 0 additions & 1 deletion src/distribution/uniform.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
1 change: 0 additions & 1 deletion src/distribution/weibull.rs
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,6 @@ impl Continuous<f64, f64> 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);

Expand Down
Loading