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