Random — Random Numbers & Probability Distributions
Overview
The sangi random module has three layers.
- Random engines —
RandomEnginewith 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&.
Build
#include <math/random/random.hpp> // RandomEngine, Uniform/Normal/MultivariateNormal
#include <math/random/distributions.hpp> // continuous & discrete distributions (Gamma, Beta, Poisson, ...)
#include <math/random/quasi_random.hpp> // Halton / Sobol sequences
Header-only; no library to link (linking the sangi_rational static libraries is recommended
because random.hpp uses linear algebra).
Random Engines
| Type | Description |
|---|---|
RandomEngine | std::mt19937 wrapper: uniform(), uniform(a,b), normal(μ,σ), uniformInt(a,b), shuffle(c), choice(c), reproducible seeding |
random::Xoshiro256pp | 256-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).
| Member | Description |
|---|---|
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
| Class | Parameters | Description |
|---|---|---|
UniformDistribution<T> | a, b | Uniform $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> | k | Chi-squared $\chi^2(k)$ |
FDistribution<T> | d1, d2 | F 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> | μ, b | Laplace (double exponential) |
ParetoDistribution<T> | α, xm | Pareto (power law) |
LogisticDistribution<T> | μ, s | Logistic |
GumbelDistribution<T> | μ, β | Gumbel (extreme value) |
Parameters (common):
| Symbol | Type | Domain / meaning |
|---|---|---|
a, b | T | Interval bounds ($a < b$) |
μ, σ | T | Mean / standard deviation ($\sigma > 0$) |
λ | T | Rate parameter ($\lambda > 0$) |
α, β | T | Shape / rate-or-scale parameters ($> 0$) |
k / ν | T | Degrees 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
| Class | Parameters | Description |
|---|---|---|
BernoulliDistribution<T> | p | Bernoulli (single trial {0,1}) |
PoissonDistribution<T> | λ | Poisson (counts) |
BinomialDistribution<T> | n, p | Binomial (successes in $n$ trials) |
GeometricDistribution<T> | p | Geometric (failures before first success) |
NegativeBinomialDistribution<T> | r, p | Negative 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
| Class | Parameters | Description |
|---|---|---|
MultivariateNormal<T> | mean, covariance | Multivariate normal (Cholesky-precomputed pdf/sample) |
DirichletDistribution<T> | alpha[] | Dirichlet (on the $K$-simplex) |
ArcsineDistribution<T> | a, b | Arcsine (U-shaped) |
InverseGammaDistribution<T> | α, β | Inverse-gamma |
InverseGaussianDistribution<T> | μ, λ | Inverse Gaussian (Wald) |
SkewNormalDistribution<T> | ξ, ω, α | Skew-normal |
TriangularDistribution<T> | a, b, c | Triangular (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)$.
| Class | Description |
|---|---|
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.