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#![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#![cfg_attr(doc_cfg, feature(doc_cfg))]
24
25//! Generating random samples from probability distributions.
26//!
27//! ## Re-exports
28//!
29//! This crate is a super-set of the [`rand::distributions`] module. See the
30//! [`rand::distributions`] module documentation for an overview of the core
31//! [`Distribution`] trait and implementations.
32//!
33//! The following are re-exported:
34//!
35//! - The [`Distribution`] trait and [`DistIter`] helper type
36//! - The [`Standard`], [`Alphanumeric`], [`Uniform`], [`OpenClosed01`],
37//! [`Open01`], [`Bernoulli`], and [`WeightedIndex`] distributions
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//! - [`Dirichlet`] distribution
74//! - [`UnitSphere`] distribution
75//! - [`UnitBall`] distribution
76//! - [`UnitCircle`] distribution
77//! - [`UnitDisc`] distribution
78//! - Alternative implementation for weighted index sampling
79//! - [`WeightedAliasIndex`] 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::distributions::{
95 uniform, Alphanumeric, Bernoulli, BernoulliError, DistIter, Distribution, Open01, OpenClosed01,
96 Standard, Uniform,
97};
98
99pub use self::binomial::{Binomial, Error as BinomialError};
100pub use self::cauchy::{Cauchy, Error as CauchyError};
101#[cfg(feature = "alloc")]
102#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
103pub use self::dirichlet::{Dirichlet, Error as DirichletError};
104pub use self::exponential::{Error as ExpError, Exp, Exp1};
105pub use self::frechet::{Error as FrechetError, Frechet};
106pub use self::gamma::{
107 Beta, BetaError, ChiSquared, ChiSquaredError, Error as GammaError, FisherF, FisherFError,
108 Gamma, StudentT,
109};
110pub use self::geometric::{Error as GeoError, Geometric, StandardGeometric};
111pub use self::gumbel::{Error as GumbelError, Gumbel};
112pub use self::hypergeometric::{Error as HyperGeoError, Hypergeometric};
113pub use self::inverse_gaussian::{Error as InverseGaussianError, InverseGaussian};
114pub use self::normal::{Error as NormalError, LogNormal, Normal, StandardNormal};
115pub use self::normal_inverse_gaussian::{
116 Error as NormalInverseGaussianError, NormalInverseGaussian,
117};
118pub use self::pareto::{Error as ParetoError, Pareto};
119pub use self::pert::{Pert, PertError};
120pub use self::poisson::{Error as PoissonError, Poisson};
121pub use self::skew_normal::{Error as SkewNormalError, SkewNormal};
122pub use self::triangular::{Triangular, TriangularError};
123pub use self::unit_ball::UnitBall;
124pub use self::unit_circle::UnitCircle;
125pub use self::unit_disc::UnitDisc;
126pub use self::unit_sphere::UnitSphere;
127pub use self::weibull::{Error as WeibullError, Weibull};
128pub use self::zipf::{Zeta, ZetaError, Zipf, ZipfError};
129#[cfg(feature = "alloc")]
130#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
131pub use rand::distributions::{WeightedError, WeightedIndex};
132#[cfg(feature = "alloc")]
133#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
134pub use weighted_alias::WeightedAliasIndex;
135
136pub use num_traits;
137
138#[cfg(test)]
139#[macro_use]
140mod test {
141 // Notes on testing
142 //
143 // Testing random number distributions correctly is hard. The following
144 // testing is desired:
145 //
146 // - Construction: test initialisation with a few valid parameter sets.
147 // - Erroneous usage: test that incorrect usage generates an error.
148 // - Vector: test that usage with fixed inputs (including RNG) generates a
149 // fixed output sequence on all platforms.
150 // - Correctness at fixed points (optional): using a specific mock RNG,
151 // check that specific values are sampled (e.g. end-points and median of
152 // distribution).
153 // - Correctness of PDF (extra): generate a histogram of samples within a
154 // certain range, and check this approximates the PDF. These tests are
155 // expected to be expensive, and should be behind a feature-gate.
156 //
157 // TODO: Vector and correctness tests are largely absent so far.
158 // NOTE: Some distributions have tests checking only that samples can be
159 // generated. This is redundant with vector and correctness tests.
160
161 /// Construct a deterministic RNG with the given seed
162 pub fn rng(seed: u64) -> impl rand::RngCore {
163 // For tests, we want a statistically good, fast, reproducible RNG.
164 // PCG32 will do fine, and will be easy to embed if we ever need to.
165 const INC: u64 = 11634580027462260723;
166 rand_pcg::Pcg32::new(seed, INC)
167 }
168
169 /// Assert that two numbers are almost equal to each other.
170 ///
171 /// On panic, this macro will print the values of the expressions with their
172 /// debug representations.
173 macro_rules! assert_almost_eq {
174 ($a:expr, $b:expr, $prec:expr) => {
175 let diff = ($a - $b).abs();
176 assert!(diff <= $prec,
177 "assertion failed: `abs(left - right) = {:.1e} < {:e}`, \
178 (left: `{}`, right: `{}`)",
179 diff, $prec, $a, $b
180 );
181 };
182 }
183}
184
185#[cfg(feature = "alloc")]
186#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
187pub mod weighted_alias;
188
189mod binomial;
190mod cauchy;
191mod dirichlet;
192mod exponential;
193mod frechet;
194mod gamma;
195mod geometric;
196mod gumbel;
197mod hypergeometric;
198mod inverse_gaussian;
199mod normal;
200mod normal_inverse_gaussian;
201mod pareto;
202mod pert;
203mod poisson;
204mod skew_normal;
205mod triangular;
206mod unit_ball;
207mod unit_circle;
208mod unit_disc;
209mod unit_sphere;
210mod utils;
211mod weibull;
212mod ziggurat_tables;
213mod zipf;