rand_distr/
lib.rs

1// Copyright 2019 Developers of the Rand project.
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
9#![doc(
10    html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk.png",
11    html_favicon_url = "https://www.rust-lang.org/favicon.ico"
12)]
13#![forbid(unsafe_code)]
14#![deny(missing_docs)]
15#![deny(missing_debug_implementations)]
16#![allow(
17    clippy::excessive_precision,
18    clippy::float_cmp,
19    clippy::unreadable_literal
20)]
21#![allow(clippy::neg_cmp_op_on_partial_ord)] // suggested fix too verbose
22#![no_std]
23
24//! Generating random samples from probability distributions.
25//!
26//! ## Re-exports
27//!
28//! This crate is a super-set of the [`rand::distr`] module. See the
29//! [`rand::distr`] module documentation for an overview of the core
30//! [`Distribution`] trait and implementations.
31//!
32//! The following are re-exported:
33//!
34//! - The [`Distribution`] trait and [`Iter`] helper type
35//! - The [`StandardUniform`], [`Alphanumeric`], [`Uniform`], [`OpenClosed01`],
36//!   [`Open01`], [`Bernoulli`] distributions
37//! - The [`weighted`] module
38//!
39//! ## Distributions
40//!
41//! This crate provides the following probability distributions:
42//!
43//! - Related to real-valued quantities that grow linearly
44//!   (e.g. errors, offsets):
45//!   - [`Normal`] distribution, and [`StandardNormal`] as a primitive
46//!   - [`SkewNormal`] distribution
47//!   - [`Cauchy`] distribution
48//! - Related to Bernoulli trials (yes/no events, with a given probability):
49//!   - [`Binomial`] distribution
50//!   - [`Geometric`] distribution
51//!   - [`Hypergeometric`] distribution
52//! - Related to positive real-valued quantities that grow exponentially
53//!   (e.g. prices, incomes, populations):
54//!   - [`LogNormal`] distribution
55//! - Related to the occurrence of independent events at a given rate:
56//!   - [`Pareto`] distribution
57//!   - [`Poisson`] distribution
58//!   - [`Exp`]onential distribution, and [`Exp1`] as a primitive
59//!   - [`Weibull`] distribution
60//!   - [`Gumbel`] distribution
61//!   - [`Frechet`] distribution
62//!   - [`Zeta`] distribution
63//!   - [`Zipf`] distribution
64//! - Gamma and derived distributions:
65//!   - [`Gamma`] distribution
66//!   - [`ChiSquared`] distribution
67//!   - [`StudentT`] distribution
68//!   - [`FisherF`] distribution
69//! - Triangular distribution:
70//!   - [`Beta`] distribution
71//!   - [`Triangular`] distribution
72//! - Multivariate probability distributions
73//!   - [`multi::Dirichlet`] distribution
74//!   - [`UnitSphere`] distribution
75//!   - [`UnitBall`] distribution
76//!   - [`UnitCircle`] distribution
77//!   - [`UnitDisc`] distribution
78//! - Misc. distributions
79//!   - [`InverseGaussian`] distribution
80//!   - [`NormalInverseGaussian`] distribution
81
82#[cfg(feature = "alloc")]
83extern crate alloc;
84
85#[cfg(feature = "std")]
86extern crate std;
87
88// This is used for doc links:
89#[allow(unused)]
90use rand::Rng;
91
92pub use rand::distr::{
93    Alphanumeric, Bernoulli, BernoulliError, Distribution, Iter, Open01, OpenClosed01,
94    StandardUniform, Uniform, uniform,
95};
96
97pub use self::beta::{Beta, Error as BetaError};
98pub use self::binomial::{Binomial, Error as BinomialError};
99pub use self::cauchy::{Cauchy, Error as CauchyError};
100pub use self::chi_squared::{ChiSquared, Error as ChiSquaredError};
101pub use self::exponential::{Error as ExpError, Exp, Exp1};
102pub use self::fisher_f::{Error as FisherFError, FisherF};
103pub use self::frechet::{Error as FrechetError, Frechet};
104pub use self::gamma::{Error as GammaError, Gamma};
105pub use self::geometric::{Error as GeoError, Geometric, StandardGeometric};
106pub use self::gumbel::{Error as GumbelError, Gumbel};
107pub use self::hypergeometric::{Error as HyperGeoError, Hypergeometric};
108pub use self::inverse_gaussian::{Error as InverseGaussianError, InverseGaussian};
109pub use self::normal::{Error as NormalError, LogNormal, Normal, StandardNormal};
110pub use self::normal_inverse_gaussian::{
111    Error as NormalInverseGaussianError, NormalInverseGaussian,
112};
113pub use self::pareto::{Error as ParetoError, Pareto};
114pub use self::pert::{Pert, PertBuilder, PertError};
115pub use self::poisson::{Error as PoissonError, Poisson};
116pub use self::skew_normal::{Error as SkewNormalError, SkewNormal};
117pub use self::triangular::{Triangular, TriangularError};
118pub use self::unit_ball::UnitBall;
119pub use self::unit_circle::UnitCircle;
120pub use self::unit_disc::UnitDisc;
121pub use self::unit_sphere::UnitSphere;
122pub use self::weibull::{Error as WeibullError, Weibull};
123pub use self::zeta::{Error as ZetaError, Zeta};
124pub use self::zipf::{Error as ZipfError, Zipf};
125pub use student_t::StudentT;
126
127pub use num_traits;
128
129#[cfg(feature = "alloc")]
130pub mod multi;
131#[cfg(feature = "alloc")]
132pub mod weighted;
133
134#[cfg(test)]
135#[macro_use]
136mod test {
137    // Notes on testing
138    //
139    // Testing random number distributions correctly is hard. The following
140    // testing is desired:
141    //
142    // - Construction: test initialisation with a few valid parameter sets.
143    // - Erroneous usage: test that incorrect usage generates an error.
144    // - Vector: test that usage with fixed inputs (including RNG) generates a
145    //   fixed output sequence on all platforms.
146    // - Correctness at fixed points (optional): using a specific mock RNG,
147    //   check that specific values are sampled (e.g. end-points and median of
148    //   distribution).
149    // - Correctness of PDF (extra): generate a histogram of samples within a
150    //   certain range, and check this approximates the PDF. These tests are
151    //   expected to be expensive, and should be behind a feature-gate.
152    //
153    // TODO: Vector and correctness tests are largely absent so far.
154    // NOTE: Some distributions have tests checking only that samples can be
155    // generated. This is redundant with vector and correctness tests.
156
157    /// An RNG which panics on first use
158    pub struct VoidRng;
159    impl rand::TryRng for VoidRng {
160        type Error = rand::rand_core::Infallible;
161        fn try_next_u32(&mut self) -> Result<u32, Self::Error> {
162            panic!("usage of VoidRng")
163        }
164        fn try_next_u64(&mut self) -> Result<u64, Self::Error> {
165            panic!("usage of VoidRng")
166        }
167        fn try_fill_bytes(&mut self, _: &mut [u8]) -> Result<(), Self::Error> {
168            panic!("usage of VoidRng")
169        }
170    }
171
172    /// Construct a deterministic RNG with the given seed
173    pub fn rng(seed: u64) -> impl rand::RngExt {
174        // For tests, we want a statistically good, fast, reproducible RNG.
175        // PCG32 will do fine, and will be easy to embed if we ever need to.
176        const INC: u64 = 11634580027462260723;
177        rand_pcg::Pcg32::new(seed, INC)
178    }
179
180    /// Assert that two numbers are almost equal to each other.
181    ///
182    /// On panic, this macro will print the values of the expressions with their
183    /// debug representations.
184    macro_rules! assert_almost_eq {
185        ($a:expr, $b:expr, $prec:expr) => {
186            let diff = ($a - $b).abs();
187            assert!(
188                diff <= $prec,
189                "assertion failed: `abs(left - right) = {:.1e} < {:e}`, \
190                    (left: `{}`, right: `{}`)",
191                diff,
192                $prec,
193                $a,
194                $b
195            );
196        };
197    }
198}
199
200mod beta;
201mod binomial;
202mod cauchy;
203mod chi_squared;
204mod exponential;
205mod fisher_f;
206mod frechet;
207mod gamma;
208mod geometric;
209mod gumbel;
210mod hypergeometric;
211mod inverse_gaussian;
212mod normal;
213mod normal_inverse_gaussian;
214mod pareto;
215mod pert;
216pub(crate) mod poisson;
217mod skew_normal;
218mod student_t;
219mod triangular;
220mod unit_ball;
221mod unit_circle;
222mod unit_disc;
223mod unit_sphere;
224mod utils;
225mod weibull;
226mod zeta;
227mod ziggurat_tables;
228mod zipf;