Random — Random Numbers & Probability Distributions

Overview

The sangi random module has three layers.

  • Random enginesRandomEngine with reproducible seeding, plus a fast PRNG (xoshiro256++) and normal generators (Ziggurat, etc.).
  • Probability distributions — 30+ continuous and discrete distributions. Each exposes density (pdf) / cumulative (cdf) / quantile (quantile) / moments (mean, variance) and sampling (sample) under a unified interface.
  • Quasi-random — Halton / Sobol low-discrepancy sequences, improving Monte-Carlo convergence from $O(1/\sqrt{N})$ toward $O(1/N)$.

The type $T$ may be double/float or multiprecision Float. Sampling takes a standard std::mt19937&.

Random Engines

TypeDescription
RandomEnginestd::mt19937 wrapper: uniform(), uniform(a,b), normal(μ,σ), uniformInt(a,b), shuffle(c), choice(c), reproducible seeding
random::Xoshiro256pp256-bit fast PRNG (xoshiro256++, period $2^{256}{-}1$)
random::NormalGenerator<T>Ziggurat fast normal generator (>95% table-lookup)
random::MarsagliaPolarGenerator<T>Marsaglia polar method (no sin/cos)
random::BoxMullerGenerator<T>Box-Muller method (reference)
RandomEngine eng(42);              // seed 42
double u = eng.uniform();          // [0,1)
double x = eng.uniform(2.0, 5.0);  // [2,5)
int d = eng.uniformInt(1, 6);      // dice {1..6}
// The same seed reproduces the same stream (RandomEngine eng2(42); eng2.uniform() == u)

Common Distribution Interface

Each distribution class takes its parameters in the constructor and exposes these common members (discrete distributions provide a mass function pmf(int k) instead of pdf).

MemberDescription
pdf(x) / pmf(k)Probability density / mass
cdf(x)Cumulative distribution function
quantile(p)Quantile (inverse CDF); provided by many distributions
mean() / variance()Mean / variance
sample(std::mt19937& gen)Draw one sample
sample(std::mt19937& gen, size_t n)Draw $n$ samples as a std::vector
NormalDistribution<double> nd(0.0, 1.0);   // standard normal N(0,1)
nd.mean();            // Run output: 0
nd.variance();        // Run output: 1
nd.pdf(0.0);          // Run output: 0.398942280401433   (= 1/sqrt(2π))
nd.cdf(0.0);          // Run output: 0.5
nd.quantile(0.975);   // Run output: 1.95996398612019    (two-sided 95%)

Continuous Distributions

ClassParametersDescription
UniformDistribution<T>a, bUniform $U(a,b)$
NormalDistribution<T>μ, σNormal $N(\mu,\sigma^2)$ (Ziggurat sampling)
ExponentialDistribution<T>λExponential (rate $\lambda$)
GammaDistribution<T>α, βGamma (Marsaglia-Tsang)
BetaDistribution<T>α, βBeta (on $[0,1]$)
ChiSquaredDistribution<T>kChi-squared $\chi^2(k)$
FDistribution<T>d1, d2F distribution
StudentTDistribution<T>νStudent's $t$
CauchyDistribution<T>x0, γCauchy (mean/variance undefined)
RayleighDistribution<T>σRayleigh
WeibullDistribution<T>k, λWeibull
LognormalDistribution<T>μ, σLog-normal
LaplaceDistribution<T>μ, bLaplace (double exponential)
ParetoDistribution<T>α, xmPareto (power law)
LogisticDistribution<T>μ, sLogistic
GumbelDistribution<T>μ, βGumbel (extreme value)

Parameters (common):

SymbolTypeDomain / meaning
a, bTInterval bounds ($a < b$)
μ, σTMean / standard deviation ($\sigma > 0$)
λTRate parameter ($\lambda > 0$)
α, βTShape / rate-or-scale parameters ($> 0$)
k / νTDegrees of freedom ($> 0$)
UniformDistribution<double> ud(0.0, 1.0);
ud.mean();        // Run output: 0.5
ud.variance();    // Run output: 0.0833333333333333   (= 1/12)
ud.pdf(0.5);      // Run output: 1

ExponentialDistribution<double> ed(2.0);  // rate λ = 2
ed.mean();        // Run output: 0.5
ed.variance();    // Run output: 0.25

Discrete Distributions

ClassParametersDescription
BernoulliDistribution<T>pBernoulli (single trial {0,1})
PoissonDistribution<T>λPoisson (counts)
BinomialDistribution<T>n, pBinomial (successes in $n$ trials)
GeometricDistribution<T>pGeometric (failures before first success)
NegativeBinomialDistribution<T>r, pNegative binomial (failures until $r$-th success)
PoissonDistribution<double> pd(3.0);
pd.mean();        // Run output: 3
pd.variance();    // Run output: 3

BinomialDistribution<double> bd(10, 0.5);
bd.mean();        // Run output: 5
bd.variance();    // Run output: 2.5
bd.pmf(5);        // Run output: 0.24609375   (= C(10,5)/2^10)

Multivariate & Special Distributions

ClassParametersDescription
MultivariateNormal<T>mean, covarianceMultivariate normal (Cholesky-precomputed pdf/sample)
DirichletDistribution<T>alpha[]Dirichlet (on the $K$-simplex)
ArcsineDistribution<T>a, bArcsine (U-shaped)
InverseGammaDistribution<T>α, βInverse-gamma
InverseGaussianDistribution<T>μ, λInverse Gaussian (Wald)
SkewNormalDistribution<T>ξ, ω, αSkew-normal
TriangularDistribution<T>a, b, cTriangular (mode $c$)
NoncentralChiSquaredDistribution<T>k, λNoncentral chi-squared
NoncentralTDistribution<T>ν, δNoncentral $t$
NoncentralFDistribution<T>d1, d2, λNoncentral F

Quasi-Random Sequences

Quasi-random sequences are highly uniform and improve Monte-Carlo convergence from the $O(1/\sqrt{N})$ of pseudo-random sampling toward $O((\log N)^D / N)$.

ClassDescription
HaltonSequence<Dim>Halton sequence (prime-base van der Corput, $1 \le \text{Dim} \le 50$)
SobolSequence<Dim>Sobol sequence (Gray code, Joe-Kuo direction numbers, $1 \le \text{Dim} \le 8$)

Members: next() (next point as std::array<double, Dim>), generate(n) ($n$ points), index(), reset().

HaltonSequence<2> h;     // bases (2, 3)
auto p0 = h.next();      // Run output: (0, 0)
auto p1 = h.next();      // Run output: (0.5, 0.333333333333333)
auto p2 = h.next();      // Run output: (0.25, 0.666666666666667)
auto p3 = h.next();      // Run output: (0.75, 0.111111111111111)

Example

#include <math/random/random.hpp>
#include <math/random/distributions.hpp>
#include <random>
#include <iostream>
using namespace sangi;

int main() {
    // Closed-form (deterministic) values
    NormalDistribution<double> nd(0.0, 1.0);
    std::cout << nd.pdf(0.0) << "\n";       // 0.398942280401433
    std::cout << nd.quantile(0.975) << "\n"; // 1.95996398612019

    // Monte Carlo: sample mean of 100k draws from N(2, 0.5) ≈ 2.0
    std::mt19937 gen(12345);
    NormalDistribution<double> g(2.0, 0.5);
    double s = 0.0;
    for (int i = 0; i < 100000; ++i) s += g.sample(gen);
    std::cout << s / 100000 << "\n";        // ≈ 2.0 (seed dependent)
}

Related Modules

Probability distributions are built on special functions and linear algebra.

  • Float — gamma-function family and other special functions used by the distributions
  • LinAlg — Cholesky decomposition for the multivariate normal
  • Matrix — covariance-matrix representation