Distributions
Densities, CDFs, quantiles and samplers for twenty probability distributions, with the special functions (ln Γ, incomplete gamma and beta, erf) beneath them.
This module provides the probability distributions used across statistics and simulation: the normal, uniform, Cauchy, exponential, Laplace, logistic, Gumbel, Pareto, Weibull, Rayleigh, log-normal, χ², gamma, beta, Student’s t and F for continuous data, and Bernoulli, geometric, Poisson and binomial for counts. For each you get a density (for a discrete distribution, the probability mass), a cumulative distribution function and, for most, a quantile function. Beneath them sit the special functions they are built from: the log-gamma function, the regularised incomplete gamma and beta functions, and the error function.
Two functions carry most of the weight. The regularised lower incomplete gamma \(P(a, x)\) gives
erf, χ², gamma and Poisson; the regularised incomplete beta \(I_x(a, b)\) gives Student’s t, F,
beta and binomial. Both are evaluated by a fixed number of iterations — a series where it converges
and a continued fraction where it does not. erf is defined here rather than being an intrinsic, so
that every executor runs exactly the same arithmetic and returns the same digits.
Conventions. Parameters come first and the point of evaluation last: normalCdf(m, s, x),
normalQuantile(m, s, p). Every argument may be a tensor and broadcasts, so a vector of x gives a
vector of densities; the statements below are written for real numbers and apply entrywise. A
quantile takes a probability p in (0, 1). Nothing here generates random
numbers: to sample, pass uniform draws in [0, 1) to a quantile function (normalSample is exactly
that), which turns them into draws from the distribution. Parameter names follow the source — for
example the gamma distribution takes a shape and a scale (not a rate), while the exponential takes
a rate; each entry says which.
Limitations. Choices between regions are made with 0/1 masks, not branches, so both sides of every choice are evaluated (on arguments clamped to their own domain so the discarded side cannot overflow). Iteration counts are fixed, which gives predictable cost and good accuracy for moderate parameters but no convergence test. Upper-tail probabilities obtained as one minus a CDF lose relative accuracy once they fall below about \(10^{-16}\). Log-gamma is valid for positive arguments.
open Prelude.Distributions
Guards
The masks used throughout this module evaluate both alternatives and multiply the unwanted one by zero; since \(0 \cdot \infty\) is NaN, not zero, each alternative is protected from division by zero, logarithms of zero, and arguments outside the region where it converges. These helpers are not meant to be called directly.
Throughout this page, \([\,\cdot\,]\) is the Iverson bracket (\([x \ge a] = 1\) if true, \(0\) otherwise), and \(v_+ = \operatorname{positive}(v) = \max(v, 10^{-300})\) is the floored argument a logarithm or a power is taken of.
Building blocks
guard(v)— Let \(v \in \mathbb{R}\). Then \(\operatorname{guard}(v) = v + 10^{-300}\,[\lvert v \rvert < 10^{-300}]\). Nudges a value whose magnitude is below 1e-300 away from zero, so it can be a denominator.positive(v)— Let \(v \in \mathbb{R}\). Then \(\operatorname{positive}(v) = v_+ = \max(v, 10^{-300})\). Clamps a value to at least 1e-300, so its logarithm is finite.clipLow(a, x)— Let \(a, x \in \mathbb{R}\). Then \(\operatorname{clipLow}(a, x) = \min(x, a + 1)\). Clamps x to at most a + 1, the region where the incomplete-gamma series converges.clipHigh(a, x)— Let \(a, x \in \mathbb{R}\). Then \(\operatorname{clipHigh}(a, x) = \max(x, a + 1)\). Clamps x to at least a + 1, the region where the incomplete-gamma continued fraction converges.
The log-gamma function
The gamma function \(\Gamma(a)\) grows too fast to compute directly, so its logarithm is used everywhere. It is computed with the Lanczos approximation (\(g = 7\), nine coefficients): a fixed rational sum with no iteration, accurate to about fifteen digits over the positive half-line.
lgamma
lgamma(a) · a argument, positive scalar or tensor → \(\ln \Gamma(a)\) same shape
Let \(a > 0\). Then
\[\operatorname{lgamma}(a) = \tfrac12 \ln(2\pi) + \left(a - \tfrac12\right) \ln(a + 6.5) - (a + 6.5) + \ln \operatorname{lanczos}(a - 1) \approx \ln \Gamma(a),\]where \(\tfrac12 \ln(2\pi)\) is the constant 0.9189385332046727 and lanczos is the rational sum below.
The natural logarithm of the gamma function. For a whole number, \(\ln \Gamma(n+1) = \ln n!\).
Intuition \(\Gamma(a)\) extends the factorial to real arguments (\(\Gamma(n+1) = n!\)), and it overflows a double once \(a\) passes about 171. Its logarithm grows only like \(a \ln a\), so products and ratios of gamma functions become sums and differences that stay finite.
Use it when you need a factorial, a binomial coefficient or a normalising constant with large arguments: \(\ln\binom{n}{k}\) is lgamma(n + 1) − lgamma(k + 1) − lgamma(n − k + 1), exactly as binomialPdf does it. Exponentiate only at the end. Arguments must be positive: there is no reflection formula, so zero or negative input is not supported.
combinatoricsnumerical-stabilitylikelihood-evaluation
def lgamma(a) ≔ 0.9189385332046727 + (a − 0.5) · ln(a + 6.5) − (a + 6.5) + ln(lanczos(a − 1))
lbeta
lbeta(a, b) · a first argument, positive · b second argument, positive → \(\ln B(a, b)\) same shape
Let \(a > 0\) and \(b > 0\). Then
\[\operatorname{lbeta}(a, b) = \operatorname{lgamma}(a) + \operatorname{lgamma}(b) - \operatorname{lgamma}(a + b) \approx \ln B(a, b).\]The logarithm of the beta function, \(\ln B(a, b) = \ln\Gamma(a) + \ln\Gamma(b) - \ln\Gamma(a + b)\).
Intuition \(B(a, b)\) is the area under \(x^{a-1}(1-x)^{b-1}\) on [0, 1]: the constant that turns that curve into a probability density. For whole numbers it is \((a-1)!\,(b-1)!/(a+b-1)!\), a continuous cousin of the reciprocal binomial coefficient.
Use it when you normalise a beta density, compute a beta-binomial likelihood, or do Bayesian updates of a proportion: the marginal likelihood of \(k\) successes in \(n\) trials under a Beta\((a, b)\) prior contains lbeta(a + k, b + n − k) − lbeta(a, b). Stay in logs. betaPdf, fPdf and betaI already call it for you.
bayesian-updatinglikelihood-evaluationnumerical-stability
def lbeta(a, b) ≔ lgamma(a) + lgamma(b) − lgamma(a + b)
Building blocks
lanczos(z)— Let \(z > -1\). Then \(\operatorname{lanczos}(z) = c_0 + \sum_{k=1}^{8} \frac{c_k}{z + k}\), where \(c_0 = 0.99999999999980993\), \(c_1 = 676.5203681218851\), \(c_2 = -1259.1392167224028\), \(c_3 = 771.32342877765313\), \(c_4 = -176.61502916214059\), \(c_5 = 12.507343278686905\), \(c_6 = -0.13857109526572012\), \(c_7 = 9.9843695780195716 \times 10^{-6}\) and \(c_8 = 1.5056327351493116 \times 10^{-7}\). The Lanczos rational sum with g = 7; used bylgamma.
The regularised incomplete gamma function
The regularised lower incomplete gamma function is
\[P(a, x) = \frac{1}{\Gamma(a)} \int_0^x t^{a-1} e^{-t}\, dt\]and \(Q(a, x) = 1 - P(a, x)\) is its upper counterpart. For \(x < a + 1\) it is summed as a power series, each term the previous times \(x/(a+n)\) (201 terms: the first and 200 more); for \(x \ge a + 1\) it is evaluated as a continued fraction by the modified Lentz method (200 turns).
lowerGamma
lowerGamma(a, x) · a shape, positive · x upper limit, non-negative → \(P(a, x)\) in [0, 1] same shape
Let \(a > 0\) and \(x \ge 0\). Then
\[\operatorname{lowerGamma}(a, x) = [x < a + 1]\; \operatorname{gammaSeries}\big(a, \min(x, a + 1)\big) + [x \ge a + 1]\; \Big(1 - \operatorname{gammaFraction}\big(a, \max(x, a + 1)\big)\Big) \approx P(a, x),\]where, away from the guard thresholds,
\[\operatorname{gammaSeries}(a, x) = \frac{e^{-x} x^{a}}{\Gamma(a)} \sum_{n=0}^{200} \frac{x^{n}}{a(a+1)\cdots(a+n)}, \qquad \operatorname{gammaFraction}(a, x) = \frac{e^{-x} x^{a}}{\Gamma(a)} \cdot \cfrac{1}{x + 1 - a - \cfrac{1 \cdot (1 - a)}{x + 3 - a - \cfrac{2 (2 - a)}{x + 5 - a - \cdots}}}\]with the fraction cut after 200 turns (see the building blocks for the exact recurrences).
The regularised lower incomplete gamma function, choosing the series or the continued fraction by the mask \(x < a + 1\). It is the CDF of a gamma distribution with shape a and unit scale.
Intuition For whole \(a\), \(P(a, x)\) is the probability that a unit-rate Poisson process has produced at least \(a\) events by time \(x\), i.e. the CDF of the wait for the \(a\)-th event. For any \(a > 0\) it is the CDF of a gamma variable with shape \(a\) and unit scale, and χ², gamma, Poisson and erf are all this function after a change of variable.
Use it when you need a gamma-family CDF the module does not name, or a building block for your own distribution. Prefer gammaCdf, chiCdf, poissonCdf or erf when one fits, since they handle scaling and supports. The iteration counts are fixed (201 series terms, 200 fraction turns) with no convergence test, so check very large shapes against a reference value.
waiting-timestail-probabilitiesprobabilistic-modelling
def lowerGamma(a, x) ≔ (x < a + 1) · gammaSeries(a, clipLow(a, x)) + (x ≥ a + 1) · (1 − gammaFraction(a, clipHigh(a, x)))
upperGamma
upperGamma(a, x) · a shape, positive · x lower limit, non-negative → \(Q(a, x)\) in [0, 1] same shape
Let \(a > 0\) and \(x \ge 0\). Then
\[\operatorname{upperGamma}(a, x) = 1 - \operatorname{lowerGamma}(a, x) \approx Q(a, x).\]The regularised upper incomplete gamma function, \(1 - P(a, x)\). Because it is formed by subtraction, very small values lose relative accuracy.
Intuition \(Q(a, x)\) asks the complementary question: the probability that the \(a\)-th event has not happened by time \(x\). For whole \(a\) it equals the probability that a Poisson count with mean \(x\) is at most \(a - 1\), which is how poissonCdf uses it.
Use it when you want an upper-tail (survival) probability of a gamma or χ² variable, or a Poisson CDF. It is computed as \(1 - P\), so its absolute error is around \(10^{-16}\): a result of \(10^{-12}\) has only a few correct digits, and smaller tails come out as 0. It is fine for ordinary p-values, not for rare-event probabilities.
tail-probabilitiescount-datahypothesis-testing
def upperGamma(a, x) ≔ 1 − lowerGamma(a, x)
Building blocks
gsTerm(a, x, n, t)— Let \(a, x, n, t \in \mathbb{R}\). Then \(\operatorname{gsTerm}(a, x, n, t) = t\,x / \operatorname{guard}(a + n)\). The next series term: the previous term t times x / (a + n).gsLoop(k, a, x, n, t, s)— Let \(k \in \mathbb{N}\) and \(a, x, n, t, s \in \mathbb{R}\), and write \(t' = \operatorname{gsTerm}(a, x, n + 1, t)\). Then \(\operatorname{gsLoop}(0, a, x, n, t, s) = s\) and \(\operatorname{gsLoop}(k, a, x, n, t, s) = \operatorname{gsLoop}(k - 1, a, x, n + 1, t', s + t')\). Adds k further series terms, carrying the term and the running sum.gammaSeries(a, x)— Let \(a > 0\) and \(x \in \mathbb{R}\). Let \(t_0 = 1/\operatorname{guard}(a)\) and \(t_n = t_{n-1}\,x / \operatorname{guard}(a + n)\) for \(n = 1, \dots, 200\). Then \(\operatorname{gammaSeries}(a, x) = \Big(\sum_{n=0}^{200} t_n\Big) \exp\big(-x + a \ln x_+ - \operatorname{lgamma}(a)\big)\). P(a, x) by the power series (201 terms) times its exponential prefactor; used where x < a + 1.cfA(a, i)— Let \(a, i \in \mathbb{R}\). Then \(\operatorname{cfA}(a, i) = -i\,(i - a)\). The i-th partial numerator of the continued fraction.cfB(b)— Let \(b \in \mathbb{R}\). Then \(\operatorname{cfB}(b) = b + 2\). The next partial denominator: the previous one plus 2.cfD(a, i, b, d)— Let \(a, i, b, d \in \mathbb{R}\). Then \(\operatorname{cfD}(a, i, b, d) = 1 / \operatorname{guard}\big(-i(i - a)\,d + b + 2\big)\). The Lentz D update, carried already inverted.cfC(a, i, b, c)— Let \(a, i, b, c \in \mathbb{R}\). Then \(\operatorname{cfC}(a, i, b, c) = \operatorname{guard}\big(b + 2 - i(i - a) / \operatorname{guard}(c)\big)\). The Lentz C update.cfLoop(k, a, i, b, c, d, h)— Let \(k \in \mathbb{N}\) and \(a, i, b, c, d, h \in \mathbb{R}\), and write \(c' = \operatorname{cfC}(a, i + 1, b, c)\) and \(d' = \operatorname{cfD}(a, i + 1, b, d)\). Then \(\operatorname{cfLoop}(0, a, i, b, c, d, h) = h\) and \(\operatorname{cfLoop}(k, a, i, b, c, d, h) = \operatorname{cfLoop}(k - 1, a, i + 1, b + 2, c', d', h\,d'\,c')\). Runs k Lentz turns, multiplying the running value h by C·D each turn.gammaFraction(a, x)— Let \(a > 0\) and \(x \in \mathbb{R}\). Let \(b_0 = x + 1 - a\), \(c_0 = 10^{300}\), \(d_0 = h_0 = 1/\operatorname{guard}(b_0)\), and for \(i = 1, \dots, 200\) let \(b_i = b_{i-1} + 2\), \(d_i = 1/\operatorname{guard}(-i(i - a)\,d_{i-1} + b_i)\), \(c_i = \operatorname{guard}(b_i - i(i - a)/\operatorname{guard}(c_{i-1}))\) and \(h_i = h_{i-1}\,d_i\,c_i\). Then \(\operatorname{gammaFraction}(a, x) = h_{200} \exp\big(-x + a \ln x_+ - \operatorname{lgamma}(a)\big)\). Q(a, x) by the continued fraction (200 turns) times its exponential prefactor; used where x ≥ a + 1.
The error function
The error function is an incomplete gamma function in disguise: \(\operatorname{erf}(x) = \operatorname{sign}(x)\, P(\tfrac12, x^2)\).
erf
erf(x) · x argument scalar or tensor → \(\operatorname{erf}(x)\) in (−1, 1) same shape
Let \(x \in \mathbb{R}\). Then
\[\operatorname{erf}(x) = \operatorname{sign}(x)\; \operatorname{lowerGamma}\!\left(\tfrac12,\; x^2\right) \approx \frac{2}{\sqrt{\pi}} \int_0^x e^{-t^2}\, dt .\]The error function, computed from the lower incomplete gamma function. It is odd: \(\operatorname{erf}(-x) = -\operatorname{erf}(x)\).
Intuition \(\operatorname{erf}(x)\) is the probability that a normal variable with mean 0 and variance \(\tfrac12\) lands in \([-x, x]\). Rescaled, \(\operatorname{erf}(z/\sqrt2)\) is the chance a standard normal lies within \(z\) standard deviations of its mean: about 0.683 at \(z = 1\) and 0.954 at \(z = 2\).
Use it when you need a symmetric “within \(k\) sigma” probability, a Gaussian integral from physics (diffusion or heat-conduction profiles), or the same digits on every executor. For a one-sided probability with a mean and a standard deviation, normalCdf is this function already rescaled.
measurement-errortail-probabilitiesuncertainty-quantification
def erf(x) ≔ sign(x) · lowerGamma(0.5, x · x)
erfc
erfc(x) · x argument scalar or tensor → \(1 - \operatorname{erf}(x)\) in (0, 2) same shape
Let \(x \in \mathbb{R}\). Then
\[\operatorname{erfc}(x) = 1 - \operatorname{erf}(x).\]The complementary error function. Because it is formed by subtraction, for large positive x it loses digits steadily and returns exactly 0 beyond about 6.
Intuition The mass outside \([-x, x]\) for the same variance-\(\tfrac12\) normal: \(\operatorname{erfc}(z/\sqrt2)\) is the probability that a standard normal falls more than \(z\) standard deviations from its mean, in either direction.
Use it when you want a two-sided normal tail, such as a two-sided z-test p-value, \(\operatorname{erfc}(\lvert z \rvert/\sqrt2)\), or a bit-error rate in a communications model. Because it is computed as \(1 - \operatorname{erf}\), it is unreliable for very small tails and is exactly 0 beyond about 6, so do not use it for far-tail or rare-event probabilities.
hypothesis-testingtail-probabilitieserror-analysis
def erfc(x) ≔ 1 − erf(x)
The normal distribution
The normal distribution with mean m and standard deviation s has density \(\frac{1}{s\sqrt{2\pi}} e^{-(x-m)^2 / 2s^2}\). Its quantile uses Wichura’s algorithm AS 241 (PPND16): three rational approximations — one for the centre, \(\lvert p - \tfrac12 \rvert \le 0.425\), and two for the tails — accurate to about sixteen digits with no iteration.
normalPdf
normalPdf(m, s, x) · m mean · s standard deviation, positive · x point → density broadcast shape
Let \(m \in \mathbb{R}\) be the mean, \(s > 0\) the standard deviation and \(x \in \mathbb{R}\) the point. Then
\[\operatorname{normalPdf}(m, s, x) = \frac{1}{s\sqrt{2\pi}} \exp\!\left(-\frac{(x - m)^2}{2 s^2}\right),\]with \(\sqrt{2\pi}\) written as the constant 2.5066282746310002.
The normal probability density at x.
Intuition The bell curve is what you get when many small independent effects add up (the central limit theorem), which makes it the default model for measurement noise and for averages. \(m\) sets the centre and \(s\) the width, with about 68% of the mass within one \(s\) of \(m\). The density is a height, not a probability: it exceeds 1 when \(s\) is small.
Use it when you evaluate the likelihood of data under a Gaussian model, weight points in a Gaussian kernel or mixture, or draw the curve. For the probability of a range use normalCdf. When you combine many observations, add log-densities written directly as \(-\tfrac12\big((x-m)/s\big)^2 - \ln s\) plus a constant, rather than multiplying densities that underflow to 0.
likelihood-evaluationprobabilistic-modellingmeasurement-error
def normalPdf(m, s, x) ≔ exp(0 − (x − m) · (x − m) / (2 · s · s)) / (s · 2.5066282746310002)
normalCdf
normalCdf(m, s, x) · m mean · s standard deviation, positive · x point → probability broadcast shape
Let \(m \in \mathbb{R}\), \(s > 0\) and \(x \in \mathbb{R}\). Then
\[\operatorname{normalCdf}(m, s, x) = \Phi\!\left(\frac{x - m}{s}\right) = \frac12\left(1 + \operatorname{erf}\frac{x - m}{s\sqrt2}\right).\]The probability that a normal variable is at most x.
Intuition The area under the bell curve to the left of \(x\): the fraction of the population at or below that value. Any interval probability is a difference of two of these, \(P(a < X \le b) = F(b) - F(a)\).
Use it when you need the share of a normal population inside a limit (a specification limit, a pass mark, a service threshold), a one-sided p-value for a z statistic, or a percentile rank. Upper tails are \(1 - F\) and lose accuracy below about \(10^{-16}\), so extreme-tail risks come out as 0. To go from a probability back to a value, use normalQuantile.
tail-probabilitieshypothesis-testingpercentiles
def normalCdf(m, s, x) ≔ 0.5 · (1 + erf((x − m) / (s · 1.4142135623730951)))
standardQuantile
standardQuantile(p) · p probability in (0, 1) scalar or tensor → standard normal quantile same shape
Let \(p \in [0, 1]\) and \(q = p - \tfrac12\). Then
\[\operatorname{standardQuantile}(p) = [\,\lvert q \rvert \le 0.425\,]\; \operatorname{midQ}(p) + [\,\lvert q \rvert > 0.425\,]\; \operatorname{tailQ}(p) \approx \Phi^{-1}(p),\]where midQ and tailQ are the central and tail rational approximations of AS 241 given in the
building blocks.
The inverse of the standard normal CDF, \(\Phi^{-1}(p)\), by AS 241. At exactly 0 or 1 it returns a large finite value rather than an infinity.
Intuition Given a probability, the z-score that cuts it off from below. It is the ruler that converts “the top 2.5%” into “1.96 standard deviations”, with no mean or scale attached.
Use it when you need a z critical value (\(z_{1-\alpha/2}\) for a two-sided interval or test), normal scores for a Q-Q plot or a rank-based transform, or a starting point for another quantile (the module seeds studentQuantile, chiQuantile and gammaQuantile from it). It is a fixed rational formula, so it is cheap. Keep \(p\) strictly inside (0, 1): at the ends it returns a large finite number, not an infinity.
confidence-intervalshypothesis-testingpercentiles
def standardQuantile(p) ≔ (abs(qOf(p)) ≤ 0.425) · midQ(p) + (abs(qOf(p)) > 0.425) · tailQ(p)
normalQuantile
normalQuantile(m, s, p) · m mean · s standard deviation, positive · p probability in (0, 1) → quantile broadcast shape
Let \(m \in \mathbb{R}\), \(s > 0\) and \(0 < p < 1\). Then
\[\operatorname{normalQuantile}(m, s, p) = m + s\, \operatorname{standardQuantile}(p) \approx m + s\,\Phi^{-1}(p).\]The value below which a normal variable falls with probability p.
Intuition The standard z-score placed on your scale: shifted to the mean \(m\) and stretched by \(s\). It answers “below which value does a fraction \(p\) of the population fall?”
Use it when you set a threshold from a target probability: a tolerance or control limit, a reorder point for a service level, or a normal value-at-risk on a loss distribution. The bounds of a central \(1 - \alpha\) interval are the quantiles at \(\alpha/2\) and \(1 - \alpha/2\). To turn a batch of uniform draws into samples, normalSample is the same call under the name that says so.
confidence-intervalsrisk-measurementpercentiles
def normalQuantile(m, s, p) ≔ m + s · standardQuantile(p)
normalSample
normalSample(m, s, u) · m mean · s standard deviation, positive · u uniform draws in [0, 1) tensor → normal draws shape of u
Let \(m \in \mathbb{R}\), \(s > 0\), and let \(u \in [0, 1)^n\) be independent uniform draws. Then, for \(i = 1, \dots, n\),
\[\operatorname{normalSample}(m, s, u)_i = \operatorname{normalQuantile}(m, s, u_i) = m + s\, \operatorname{standardQuantile}(u_i).\]Turns uniform draws into normal draws by the inverse-CDF method. Supply the uniforms yourself (for example from a seeded generator in C#); the same uniforms always give the same normals.
Intuition Inverse-transform sampling: if \(U\) is uniform on [0, 1), then \(F^{-1}(U)\) has CDF \(F\). Each uniform is read as “a random percentile” and mapped to the value at that percentile, with no rejection loop and no hidden random state.
Use it when you simulate from a normal model (Monte Carlo risk, noise injection, perturbation studies) and want reproducible results: seed the uniform generator in C#, and the same uniforms always give the same normals. Stratified or quasi-random uniforms (Latin hypercube, Sobol points) pass straight through with their structure intact. A uniform of exactly 0 maps to a large negative finite value rather than minus infinity.
simulationrandom-variate-generationuncertainty-quantification
def normalSample(m, s, u) ≔ normalQuantile(m, s, u)
Building blocks
qOf(p)— Let \(p \in \mathbb{R}\). Then \(\operatorname{qOf}(p) = q = p - \tfrac12\). The centred probability p − 0.5.midR(p)— Let \(p \in \mathbb{R}\) and \(q = p - \tfrac12\). Then \(\operatorname{midR}(p) = 0.180625 - q^2\). The variable of the central rational approximation.midNum(r)— Let \(r \in \mathbb{R}\). Then \(\operatorname{midNum}(r) = \sum_{k=0}^{7} a_k r^k\) (evaluated in Horner form), where \(a_0 = 3.387132872796366608\), \(a_1 = 133.14166789178437745\), \(a_2 = 1971.5909503065514427\), \(a_3 = 13731.693765509461125\), \(a_4 = 45921.953931549871457\), \(a_5 = 67265.770927008700853\), \(a_6 = 33430.575583588128105\) and \(a_7 = 2509.0809287301226727\). Numerator polynomial of the central approximation.midDen(r)— Let \(r \in \mathbb{R}\). Then \(\operatorname{midDen}(r) = \sum_{k=0}^{7} b_k r^k\) (Horner form), where \(b_0 = 1\), \(b_1 = 42.313330701600911252\), \(b_2 = 687.1870074920579083\), \(b_3 = 5394.1960214247511077\), \(b_4 = 21213.794301586595867\), \(b_5 = 39307.89580009271061\), \(b_6 = 28729.085735721942674\) and \(b_7 = 5226.495278852854561\). Denominator polynomial of the central approximation.midQ(p)— Let \(p \in \mathbb{R}\), \(q = p - \tfrac12\) and \(r = 0.180625 - q^2\). Then \(\operatorname{midQ}(p) = q\, \operatorname{midNum}(r) / \operatorname{midDen}(r)\). The standard normal quantile for the central region.tailR(p)— Let \(p \in \mathbb{R}\). Then \(\operatorname{tailR}(p) = \rho = \sqrt{-\ln\big(\min(p, 1 - p)\big)_+}\). The tail variable, the square root of minus the log of the smaller tail probability.nearR(p)— Let \(p \in \mathbb{R}\) and \(\rho = \operatorname{tailR}(p)\). Then \(\operatorname{nearR}(p) = \rho - 1.6\). The tail variable shifted for the near-tail approximation.nearNum(r)— Let \(r \in \mathbb{R}\). Then \(\operatorname{nearNum}(r) = \sum_{k=0}^{7} c_k r^k\) (Horner form), where \(c_0 = 1.42343711074968357734\), \(c_1 = 4.6303378461565452959\), \(c_2 = 5.7694972214606914055\), \(c_3 = 3.64784832476320460504\), \(c_4 = 1.27045825245236838258\), \(c_5 = 0.24178072517745061177\), \(c_6 = 0.0227238449892691845833\) and \(c_7 = 7.7454501427834140764 \times 10^{-4}\). Numerator polynomial of the near-tail approximation.nearDen(r)— Let \(r \in \mathbb{R}\). Then \(\operatorname{nearDen}(r) = \sum_{k=0}^{7} d_k r^k\) (Horner form), where \(d_0 = 1\), \(d_1 = 2.05319162663775882187\), \(d_2 = 1.6763848301838038494\), \(d_3 = 0.689767334985100004550\), \(d_4 = 0.148103976427480074590\), \(d_5 = 0.0151986665636164571966\), \(d_6 = 5.47593808499534494600 \times 10^{-4}\) and \(d_7 = 1.05075007164441684324 \times 10^{-9}\). Denominator polynomial of the near-tail approximation.farR(p)— Let \(p \in \mathbb{R}\) and \(\rho = \operatorname{tailR}(p)\). Then \(\operatorname{farR}(p) = \rho - 5\). The tail variable shifted for the far-tail approximation.farNum(r)— Let \(r \in \mathbb{R}\). Then \(\operatorname{farNum}(r) = \sum_{k=0}^{7} e_k r^k\) (Horner form), where \(e_0 = 6.65790464350110377720\), \(e_1 = 5.46378491116411436990\), \(e_2 = 1.78482653991729133580\), \(e_3 = 0.296560571828504891230\), \(e_4 = 0.0265321895265761230930\), \(e_5 = 0.00124266094738807843860\), \(e_6 = 2.71155556874348757815 \times 10^{-5}\) and \(e_7 = 2.01033439929228813265 \times 10^{-7}\). Numerator polynomial of the far-tail approximation.farDen(r)— Let \(r \in \mathbb{R}\). Then \(\operatorname{farDen}(r) = \sum_{k=0}^{7} f_k r^k\) (Horner form), where \(f_0 = 1\), \(f_1 = 0.599832206555887937690\), \(f_2 = 0.136929880922735805310\), \(f_3 = 0.0148753612908506148525\), \(f_4 = 7.86869131145613259100 \times 10^{-4}\), \(f_5 = 1.84631831751005468180 \times 10^{-5}\), \(f_6 = 1.4215117583164458887 \times 10^{-7}\) and \(f_7 = 2.04426310338993978564 \times 10^{-15}\). Denominator polynomial of the far-tail approximation.tailQ(p)— Let \(p \in \mathbb{R}\), \(q = p - \tfrac12\) and \(\rho = \operatorname{tailR}(p)\). Then \(\operatorname{tailQ}(p) = \operatorname{sign}(q)\Big([\rho \le 5]\,\frac{\operatorname{nearNum}(\rho - 1.6)}{\operatorname{nearDen}(\rho - 1.6)} + [\rho > 5]\,\frac{\operatorname{farNum}(\rho - 5)}{\operatorname{farDen}(\rho - 5)}\Big)\). The standard normal quantile for both tails, signed by the side of 0.5.
Closed-form distributions
These distributions have densities, CDFs and quantiles in closed form, so they need no series at
all. Each family has three functions — …Pdf, …Cdf and …Quantile — with the same leading
parameters. Supports are enforced with masks: outside the support the density and CDF are 0 (or the
CDF is 1 above it), with no error. Every quantile, applied to uniform draws, samples the distribution.
As in the Guards section, \(v_+ = \max(v, 10^{-300})\).
uniformPdf
uniformPdf(a, b, x) · a lower bound · b upper bound, greater than a · x point → density broadcast shape
Let \(a < b\) be the bounds and \(x \in \mathbb{R}\). Then
\[\operatorname{uniformPdf}(a, b, x) = \frac{[x \ge a]\,[x \le b]}{b - a}.\]\(1/(b - a)\) for \(a \le x \le b\), and 0 elsewhere.
Intuition “Anywhere in \([a, b]\), nothing preferred”: a flat density whose height \(1/(b-a)\) makes the area one. It is the model you reach for when all you know is the bounds.
Use it when you model a quantity known only to lie in a range (rounding error, a tolerance band, an arrival somewhere in a known window), write a flat prior, or evaluate the likelihood of bounded data. The density is 0 outside the bounds, so a log-likelihood there is minus infinity. When values near the middle are likelier, a beta rescaled to the interval (betaPdf) is the usual next step.
probabilistic-modellinglikelihood-evaluationmeasurement-error
def uniformPdf(a, b, x) ≔ (x ≥ a) · (x ≤ b) / (b − a)
uniformCdf
uniformCdf(a, b, x) · a lower bound · b upper bound · x point → probability broadcast shape
Let \(a < b\) and \(x \in \mathbb{R}\). Then
\[\operatorname{uniformCdf}(a, b, x) = \min\!\left(\max\!\left(\frac{x - a}{b - a},\, 0\right),\, 1\right).\]\((x - a)/(b - a)\) clamped to [0, 1].
Intuition The fraction of the interval already covered at \(x\): a straight ramp from 0 at \(a\) to 1 at \(b\), flat on either side.
Use it when you need the probability that a uniformly distributed quantity is below a threshold (a timer that fires somewhere in a window, a random offset), or you map a value in \([a, b]\) to a percentile in [0, 1] before passing it to another distribution’s quantile. Values outside \([a, b]\) are clamped to 0 or 1, not rejected.
tail-probabilitiespercentiles
def uniformCdf(a, b, x) ≔ min(max((x − a) / (b − a), 0), 1)
uniformQuantile
uniformQuantile(a, b, p) · a lower bound · b upper bound · p probability → quantile broadcast shape
Let \(a < b\) and \(p \in [0, 1]\). Then
\[\operatorname{uniformQuantile}(a, b, p) = a + p\,(b - a).\]It rescales draws in [0, 1) to [a, b).
Intuition A linear rescaling: the point a fraction \(p\) of the way from \(a\) to \(b\). Applied to standard uniform draws, it gives uniform draws on any interval.
Use it when you draw random values in a range (initial weights, jitter, random search over a hyperparameter interval) from the uniforms your C# generator supplies. It does not clamp: \(p\) outside [0, 1] gives a value outside \([a, b]\). For a range searched on a log scale, such as a learning rate, apply it to the logarithms of the bounds and exponentiate the result.
random-variate-generationsimulationhyperparameter-choice
def uniformQuantile(a, b, p) ≔ a + p · (b − a)
cauchyPdf
cauchyPdf(x0, g, x) · x0 location (median) · g scale, positive · x point → density broadcast shape
Let \(x_0 \in \mathbb{R}\) (the argument x0) be the location, \(\gamma > 0\) (the argument g) the scale and \(x \in \mathbb{R}\). Then
The Cauchy distribution has no mean or variance, which makes it a standard test case for robust statistics.
Intuition The ratio of two independent standard normals is Cauchy, and so is the point where a ray fired at a uniformly random angle hits a line. Its tails decay like \(1/x^2\), so slowly that the mean and variance do not exist: averages of Cauchy samples never settle down. \(x_0\) is the median and the peak; \(\gamma\) is the half-width at half the peak height.
Use it when you model resonance line shapes (the Lorentzian profile in spectroscopy), need a heavy-tailed likelihood that shrugs off outliers, or want a stress test for an estimator. Summarise it with the median and quantiles, never the sample mean. For heavy tails with a tunable weight, use studentPdf (one degree of freedom is the standard Cauchy).
heavy-tailsrobust-statisticslikelihood-evaluation
def cauchyPdf(x0, g, x) ≔ g / (3.141592653589793 · (g · g + (x − x0) · (x − x0)))
cauchyCdf
cauchyCdf(x0, g, x) · x0 location · g scale, positive · x point → probability broadcast shape
Let \(x_0 \in \mathbb{R}\), \(\gamma > 0\) (the argument g) and \(x \in \mathbb{R}\). Then
Intuition An arctangent: half the mass lies on each side of \(x_0\), and the quartiles sit exactly at \(x_0 \pm \gamma\). It creeps towards 0 and 1 so slowly that about 6% of the mass lies more than \(10\gamma\) from the centre.
Use it when you need the probability that a Cauchy-distributed quantity exceeds a threshold, or a percentile rank under a heavy-tailed model. Set beside normalCdf at the same threshold, it shows how much more probability a heavy-tailed model gives to extreme values.
heavy-tailstail-probabilities
def cauchyCdf(x0, g, x) ≔ 0.5 + atan((x − x0) / g) / 3.141592653589793
cauchyQuantile
cauchyQuantile(x0, g, p) · x0 location · g scale, positive · p probability → quantile broadcast shape
Let \(x_0 \in \mathbb{R}\), \(\gamma > 0\) (the argument g) and \(0 < p < 1\). Then
Intuition A tangent: uniform angles in \((-\pi/2, \pi/2)\) projected onto a line. The tangent blows up near the ends of that range, so quantiles near 0 or 1 are enormous, which is the heavy tail seen from the other side.
Use it when you generate Cauchy draws from uniforms (outlier-heavy test data, robustness experiments), or you need interval bounds under a Cauchy model: the central 50% interval is \(x_0 \pm \gamma\). There is no guard, so at \(p = 0\) or very close to 1 the tangent returns huge values; keep the uniforms strictly inside (0, 1).
random-variate-generationheavy-tailsrobust-statistics
def cauchyQuantile(x0, g, p) ≔ x0 + g · tan(3.141592653589793 · (p − 0.5))
exponentialPdf
exponentialPdf(r, x) · r rate, positive · x point → density broadcast shape
Let \(r > 0\) be the rate and \(x \in \mathbb{R}\). Then
\[\operatorname{exponentialPdf}(r, x) = [x \ge 0]\; r\, e^{-rx}.\]\(r\,e^{-rx}\) for \(x \ge 0\), and 0 for negative x. The mean is \(1/r\).
Intuition The waiting time until the first event when events happen independently at a constant rate \(r\). It is memoryless: however long you have already waited, the remaining wait has the same distribution. The mean wait is \(1/r\), so the parameter is events per unit time, not a scale.
Use it when you model inter-arrival times (requests, customers, decays), lifetimes with a constant failure rate, or evaluate the likelihood of observed gaps (the maximum-likelihood rate is one over the mean gap). If the failure rate rises or falls with age, use weibullPdf; for the wait until the \(k\)-th event, use gammaPdf.
waiting-timesreliability-analysislikelihood-evaluation
def exponentialPdf(r, x) ≔ (x ≥ 0) · r · exp(0 − r · x)
exponentialCdf
exponentialCdf(r, x) · r rate, positive · x point → probability broadcast shape
Let \(r > 0\) and \(x \in \mathbb{R}\). Then
\[\operatorname{exponentialCdf}(r, x) = [x \ge 0]\,\big(1 - e^{-rx}\big).\]Intuition The probability that the event has happened by time \(x\). Its complement \(e^{-rx}\) is the survival probability, which halves every \(\ln 2 / r\) time units, like radioactive decay.
Use it when you need the chance that a wait ends within a deadline (a queue served within a time limit under a constant rate, a component failing before its warranty ends) or, as \(1 - F\), the probability of surviving past a time. For the time by which a given fraction of waits have ended, use exponentialQuantile.
waiting-timesreliability-analysistail-probabilities
def exponentialCdf(r, x) ≔ (x ≥ 0) · (1 − exp(0 − r · x))
exponentialQuantile
exponentialQuantile(r, p) · r rate, positive · p probability → quantile broadcast shape
Let \(r > 0\) and \(p \in [0, 1]\). Then
\[\operatorname{exponentialQuantile}(r, p) = -\frac{\ln (1 - p)_+}{r},\]which is \(-\ln(1 - p)/r\) for \(p < 1\) and a large finite value at \(p = 1\).
Intuition The time by which a fraction \(p\) of waits have ended. At \(p = \tfrac12\) it is the median wait \(\ln 2 / r\), shorter than the mean \(1/r\) because a few long waits pull the mean up.
Use it when you simulate arrivals or lifetimes from uniforms (add successive draws to get the event times of a Poisson process), or set a timeout that a target fraction of waits will beat. At \(p = 1\) the guarded logarithm gives a large finite value instead of infinity.
random-variate-generationwaiting-timessimulation
def exponentialQuantile(r, p) ≔ 0 − ln(positive(1 − p)) / r
laplacePdf
laplacePdf(m, b, x) · m location · b scale, positive · x point → density broadcast shape
Let \(m \in \mathbb{R}\) be the location, \(b > 0\) the scale and \(x \in \mathbb{R}\). Then
\[\operatorname{laplacePdf}(m, b, x) = \frac{1}{2b}\, e^{-\lvert x - m \rvert / b}.\]The double-exponential density.
Intuition Two exponentials placed back to back around \(m\): a sharp peak, and tails that fall like \(e^{-\lvert x - m \rvert/b}\), heavier than the normal’s. It is also the difference of two independent exponential waits with the same rate. Maximising a Laplace likelihood minimises absolute error, which is why its location estimate is the median.
Use it when you model errors with occasional large deviations (L1 regression, robust fitting), put a sparsity-inducing prior on weights (the Bayesian reading of the lasso), or add noise for differential privacy (the Laplace mechanism uses scale = sensitivity / ε). For rarer, larger outliers use cauchyPdf or studentPdf.
robust-statisticslikelihood-evaluationdifferential-privacy
def laplacePdf(m, b, x) ≔ exp(0 − abs(x − m) / b) / (2 · b)
laplaceCdf
laplaceCdf(m, b, x) · m location · b scale, positive · x point → probability broadcast shape
Let \(m \in \mathbb{R}\), \(b > 0\) and \(x \in \mathbb{R}\). Then
\[\operatorname{laplaceCdf}(m, b, x) = \frac12 + \frac12 \operatorname{sign}(x - m)\,\big(1 - e^{-\lvert x - m \rvert / b}\big).\]Intuition Half the mass lies on each side of \(m\), and each tail beyond a distance \(d\) holds \(\tfrac12 e^{-d/b}\): exponential decay in both directions.
Use it when you need the probability that Laplace noise exceeds a bound, e.g. how often a differentially private count is off by more than \(d\), which is \(e^{-d/b}\) for both sides together. It also gives percentile ranks of residuals under an L1 error model.
tail-probabilitiesdifferential-privacyrobust-statistics
def laplaceCdf(m, b, x) ≔ 0.5 + 0.5 · sign(x − m) · (1 − exp(0 − abs(x − m) / b))
laplaceQuantile
laplaceQuantile(m, b, p) · m location · b scale, positive · p probability → quantile broadcast shape
Let \(m \in \mathbb{R}\), \(b > 0\) and \(p \in [0, 1]\). Then
\[\operatorname{laplaceQuantile}(m, b, p) = m - b\, \operatorname{sign}\!\big(p - \tfrac12\big) \ln \Big(1 - 2\,\big\lvert p - \tfrac12 \big\rvert\Big)_+ .\]Intuition The inverse of that two-sided decay: the distance from \(m\) grows with the logarithm of one over the tail probability, so extreme quantiles grow only slowly.
Use it when you draw Laplace noise from uniforms (the Laplace mechanism, simulated robust residuals) or need a symmetric error bound: the interval \(m \pm b \ln(1/\alpha)\) holds \(1 - \alpha\) of the mass. At \(p = 0\) or 1 the guarded logarithm gives large finite values.
random-variate-generationdifferential-privacyconfidence-intervals
def laplaceQuantile(m, b, p) ≔ m − b · sign(p − 0.5) · ln(positive(1 − 2 · abs(p − 0.5)))
logisticPdf
logisticPdf(m, s, x) · m location · s scale, positive · x point → density broadcast shape
Let \(m \in \mathbb{R}\) be the location, \(s > 0\) the scale, \(x \in \mathbb{R}\) and \(z = (x - m)/s\). Then
\[\operatorname{logisticPdf}(m, s, x) = \frac{e^{-z}}{s\,(1 + e^{-z})^2}.\]Intuition The derivative of the sigmoid: a bell shape like the normal’s, with somewhat heavier exponential tails. It is the noise behind logistic regression: if \(y = 1\) exactly when a score plus logistic noise is positive, then \(P(y = 1)\) is a sigmoid of the score. Its variance is \(\pi^2 s^2/3\), so \(s\) is not the standard deviation.
Use it when you need a normal-like likelihood whose CDF has a closed form, model latent-utility noise, or fit growth and dose-response data. For probabilities use logisticCdf. The formula exponentiates \(-(x - m)/s\), so more than about 709 scales below \(m\) that exponential overflows and the result is NaN.
classificationprobabilistic-modellinglikelihood-evaluation
def logisticPdf(m, s, x) ≔ exp(0 − (x − m) / s) / (s · (1 + exp(0 − (x − m) / s)) · (1 + exp(0 − (x − m) / s)))
logisticCdf
logisticCdf(m, s, x) · m location · s scale, positive · x point → probability broadcast shape
Let \(m \in \mathbb{R}\), \(s > 0\) and \(x \in \mathbb{R}\). Then
\[\operatorname{logisticCdf}(m, s, x) = \frac{1}{1 + e^{-(x - m)/s}}.\]The logistic (sigmoid) function.
Intuition The sigmoid squashes any real score into a probability: it crosses one half at \(m\), and \(s\) sets how gradually it rises. Each step of \(s\) in \(x\) multiplies the odds by \(e\).
Use it when you turn a linear score into a class probability (logistic regression, Elo-style win probabilities), or model an S-shaped curve such as dose-response or adoption over time. It stays finite for large scores in either direction. For the reverse map from probability to score, use logisticQuantile.
classificationbinary-outcomesdose-response
def logisticCdf(m, s, x) ≔ 1 / (1 + exp(0 − (x − m) / s))
logisticQuantile
logisticQuantile(m, s, p) · m location · s scale, positive · p probability → quantile broadcast shape
Let \(m \in \mathbb{R}\), \(s > 0\) and \(p \in [0, 1]\). Then
\[\operatorname{logisticQuantile}(m, s, p) = m + s \ln \frac{p_+}{(1 - p)_+}.\]The logit, \(m + s \ln\big(p/(1 - p)\big)\) for \(0 < p < 1\).
Intuition The logit: a probability turned into log-odds, stretched by \(s\) and shifted by \(m\). Probabilities near 0 and 1 are pulled far apart, which is why log-odds are the natural scale for adding up evidence.
Use it when you convert a probability into a score (a base rate turned into a model’s bias term, a calibrated probability back into its linear predictor), or draw logistic noise from uniforms. Probabilities of exactly 0 or 1 are floored at \(10^{-300}\), giving about \(m \pm 690\,s\) rather than an infinity.
classificationrandom-variate-generation
def logisticQuantile(m, s, p) ≔ m + s · ln(positive(p) / positive(1 − p))
gumbelPdf
gumbelPdf(m, b, x) · m location · b scale, positive · x point → density broadcast shape
Let \(m \in \mathbb{R}\) be the location, \(b > 0\) the scale, \(x \in \mathbb{R}\) and \(z = (x - m)/b\). Then
\[\operatorname{gumbelPdf}(m, b, x) = \frac1b\, e^{-(z + e^{-z})}.\]The Gumbel (maximum extreme value) density.
Intuition The distribution of the largest of many independent values with light (exponential-type) tails: the highest flood of the year, the worst latency of the day, the peak load on a structure. It leans right, because a maximum can overshoot far more easily than undershoot. \(m\) is the mode and \(b\) the spread.
Use it when you fit block maxima (annual peak rainfall, wind speed, daily worst response time) by likelihood, or model random utilities in discrete-choice models. For maxima of heavy-tailed data (insurance claims, market losses) it understates the tail; a Pareto tail (paretoPdf) is safer. For minima, apply it to the negated values.
extreme-valueslikelihood-evaluationrisk-measurement
def gumbelPdf(m, b, x) ≔ exp(0 − (x − m) / b − exp(0 − (x − m) / b)) / b
gumbelCdf
gumbelCdf(m, b, x) · m location · b scale, positive · x point → probability broadcast shape
Let \(m \in \mathbb{R}\), \(b > 0\) and \(x \in \mathbb{R}\). Then
\[\operatorname{gumbelCdf}(m, b, x) = \exp\!\big(-e^{-(x - m)/b}\big).\]Intuition A double exponential, \(\exp(-e^{-z})\). If one period’s maximum has this CDF, the maximum over \(n\) independent periods is Gumbel again with \(m\) moved up by \(b \ln n\), so the family is stable under taking maxima.
Use it when you need the probability that a period’s maximum stays below a design level (a levee height, a capacity limit), or the return period of a level, \(1/(1 - F)\) periods on average between exceedances.
extreme-valuestail-probabilitiesrisk-measurement
def gumbelCdf(m, b, x) ≔ exp(0 − exp(0 − (x − m) / b))
gumbelQuantile
gumbelQuantile(m, b, p) · m location · b scale, positive · p probability → quantile broadcast shape
Let \(m \in \mathbb{R}\), \(b > 0\) and \(p \in [0, 1]\). Then
\[\operatorname{gumbelQuantile}(m, b, p) = m - b \ln \big(-\ln p_+\big)_+ ,\]which is \(m - b \ln(-\ln p)\) for \(0 < p < 1\).
Intuition Turns a non-exceedance probability into a level: the value a period’s maximum stays below with probability \(p\). For long return periods the level grows with the logarithm of the period: each tenfold longer period adds about the same amount, \(b \ln 10\).
Use it when you compute the design level for a return period of \(T\) periods, gumbelQuantile(m, b, 1 − 1/T), or draw Gumbel noise from uniforms: with \(m = 0\) and \(b = 1\), the argmax of log-probabilities plus independent Gumbel draws samples a categorical choice (the Gumbel-max trick).
extreme-valuesrisk-measurementrandom-variate-generation
def gumbelQuantile(m, b, p) ≔ m − b · ln(positive(0 − ln(positive(p))))
paretoPdf
paretoPdf(xm, a, x) · xm minimum (scale), positive · a shape, positive · x point → density broadcast shape
Let \(x_m > 0\) (the argument xm) be the minimum, \(a > 0\) the shape and \(x \in \mathbb{R}\). Then
\(\dfrac{a\, x_m^a}{x^{a+1}}\) for \(x \ge x_m\), and 0 below it.
Intuition The power law behind “a few account for most”: wealth, city sizes, file sizes, insurance losses above a threshold. The density falls like \(x^{-(a+1)}\), so doubling a value divides its density by the same factor \(2^{a+1}\) at every scale. Smaller \(a\) means heavier tails: the mean is infinite for \(a \le 1\) and the variance for \(a \le 2\).
Use it when you fit the tail of heavy-tailed data above a threshold \(x_m\) (large-loss models, bursty network traffic), or evaluate a power-law likelihood. The density is 0 below \(x_m\), so choose the threshold before fitting. When data are skewed but all moments are finite, lognormalPdf is often the better model.
heavy-tailsrisk-measurementlikelihood-evaluation
def paretoPdf(xm, a, x) ≔ (x ≥ xm) · a · xm^a / positive(x)^(a + 1)
paretoCdf
paretoCdf(xm, a, x) · xm minimum (scale), positive · a shape, positive · x point → probability broadcast shape
Let \(x_m > 0\) (the argument xm), \(a > 0\) and \(x \in \mathbb{R}\). Then
Intuition The survival probability is a pure power, \((x_m/x)^a\): the share of values above \(x\) drops by the factor \(2^a\) each time \(x\) doubles. The 80/20 rule corresponds to \(a \approx 1.16\).
Use it when you estimate exceedance probabilities for heavy-tailed quantities: how likely a claim above a large amount is, or a traffic burst above a link’s capacity. On a plot of \(\ln(1 - F)\) against \(\ln x\), a straight line of slope \(-a\) is the signature of a Pareto tail, which is a quick check before relying on this model.
heavy-tailstail-probabilitiesrisk-measurement
def paretoCdf(xm, a, x) ≔ (x ≥ xm) · (1 − (xm / positive(x))^a)
paretoQuantile
paretoQuantile(xm, a, p) · xm minimum (scale), positive · a shape, positive · p probability → quantile broadcast shape
Let \(x_m > 0\) (the argument xm), \(a > 0\) and \(p \in [0, 1]\). Then
which is \(x_m (1 - p)^{-1/a}\) for \(p < 1\).
Intuition The level exceeded with probability \(1 - p\). As \(p \to 1\) it grows like a power of \(1/(1 - p)\), not a logarithm, which is why heavy-tail risk estimates explode at high confidence levels.
Use it when you compute a value-at-risk or a capacity level for heavy-tailed losses or loads, or draw power-law samples from uniforms (synthetic wealth, file sizes, workloads). At \(p = 1\) the result is huge, and for small \(a\) the floored power underflows and the result is infinite, so draw uniforms in [0, 1).
risk-measurementheavy-tailsrandom-variate-generation
def paretoQuantile(xm, a, p) ≔ xm / positive(1 − p)^(1 / a)
weibullPdf
weibullPdf(l, k, x) · l scale λ, positive · k shape, positive · x point → density broadcast shape
Let \(\lambda > 0\) (the argument l) be the scale, \(k > 0\) the shape and \(x \in \mathbb{R}\). Then
Intuition A lifetime whose hazard (instantaneous failure rate) changes as a power of age: \(k < 1\) is infant mortality (failures thin out with age), \(k = 1\) is the exponential with rate \(1/\lambda\), and \(k > 1\) is wear-out. It also arises as the weakest link, the minimum of many independent strengths. About 63.2% of lifetimes end before \(\lambda\), whatever \(k\) is.
Use it when you model component lifetimes, material strength or wind speeds, and fit them by likelihood from failure data. For a constant hazard, exponentialPdf is the simpler special case; for data produced by multiplicative growth, compare with lognormalPdf.
reliability-analysiswaiting-timeslikelihood-evaluation
def weibullPdf(l, k, x) ≔ (x ≥ 0) · (k / l) · (positive(x) / l)^(k − 1) · exp(0 − (positive(x) / l)^k)
weibullCdf
weibullCdf(l, k, x) · l scale λ, positive · k shape, positive · x point → probability broadcast shape
Let \(\lambda > 0\) (the argument l), \(k > 0\) and \(x \in \mathbb{R}\). Then
Intuition The fraction of units failed by age \(x\). Because \(\ln(-\ln(1 - F))\) is a straight line in \(\ln x\) with slope \(k\), a Weibull plot of failure data reads the shape straight off the slope.
Use it when you estimate the probability that a part fails within its warranty or maintenance interval, the reliability \(1 - F\) at a mission time, or the share of wind speeds below a turbine’s cut-in speed.
reliability-analysistail-probabilities
def weibullCdf(l, k, x) ≔ (x ≥ 0) · (1 − exp(0 − (positive(x) / l)^k))
weibullQuantile
weibullQuantile(l, k, p) · l scale λ, positive · k shape, positive · p probability → quantile broadcast shape
Let \(\lambda > 0\) (the argument l), \(k > 0\) and \(p \in [0, 1]\). Then
Intuition The age by which a fraction \(p\) of units have failed. Reliability engineers call weibullQuantile(l, k, 0.1) the B10 life: the age at which 10% have failed.
Use it when you set maintenance or replacement intervals from a failure-fraction target, quote B-lives, or draw Weibull lifetimes from uniforms for a reliability simulation. With \(k = 1\) it reduces to the exponential quantile with rate \(1/\lambda\).
reliability-analysisrandom-variate-generationsimulation
def weibullQuantile(l, k, p) ≔ l · (0 − ln(positive(1 − p)))^(1 / k)
rayleighPdf
rayleighPdf(s, x) · s scale σ, positive · x point → density broadcast shape
Let \(\sigma > 0\) (the argument s) be the scale and \(x \in \mathbb{R}\). Then
Intuition The length of a 2-D vector whose two components are independent normals with mean 0 and standard deviation \(\sigma\): a shot’s distance from the bullseye, the amplitude of a noisy signal, a speed built from two orthogonal components. The density is 0 at the centre and peaks at \(\sigma\), because a ring of small radius has little room in it.
Use it when you model radial miss distances, the envelope of narrowband noise or fading amplitudes, or wave heights, and evaluate their likelihood. It is the Weibull with \(k = 2\) and \(\lambda = \sigma\sqrt2\). If the vector has a non-zero mean (a direct signal path), the Rice distribution applies instead, and this module does not provide it.
signal-amplitudemeasurement-errorlikelihood-evaluation
def rayleighPdf(s, x) ≔ (x ≥ 0) · x · exp(0 − x · x / (2 · s · s)) / (s · s)
rayleighCdf
rayleighCdf(s, x) · s scale σ, positive · x point → probability broadcast shape
Let \(\sigma > 0\) (the argument s) and \(x \in \mathbb{R}\). Then
Intuition The probability that the vector’s length is at most \(x\), i.e. that a point lands inside the circle of radius \(x\) around the centre.
Use it when you compute a hit probability within a target radius, the chance that a fading signal’s amplitude drops below a receiver threshold (the outage probability), or, as \(1 - F\), the share of wave heights above a level.
tail-probabilitiessignal-amplitude
def rayleighCdf(s, x) ≔ (x ≥ 0) · (1 − exp(0 − x · x / (2 · s · s)))
rayleighQuantile
rayleighQuantile(s, p) · s scale σ, positive · p probability → quantile broadcast shape
Let \(\sigma > 0\) (the argument s) and \(p \in [0, 1]\). Then
Intuition The radius of the circle that contains a fraction \(p\) of the points. At \(p = \tfrac12\) it is the circular error probable, \(\sigma\sqrt{2 \ln 2} \approx 1.177\,\sigma\).
Use it when you size a target or tolerance circle for a positioning error (the CEP of a GPS fix), set a detection threshold on a noise envelope for a target false-alarm rate (\(p = 1 -\) that rate), or draw Rayleigh variates from uniforms.
confidence-intervalssignal-amplituderandom-variate-generation
def rayleighQuantile(s, p) ≔ s · sqrt(0 − 2 · ln(positive(1 − p)))
lognormalPdf
lognormalPdf(m, s, x) · m mean of ln X · s standard deviation of ln X, positive · x point → density broadcast shape
Let \(m \in \mathbb{R}\) be the mean and \(s > 0\) the standard deviation of \(\ln X\), and let \(x \in \mathbb{R}\). Then
\[\operatorname{lognormalPdf}(m, s, x) = [x > 0]\; \frac{\operatorname{normalPdf}(m, s, \ln x_+)}{x_+} = [x > 0]\; \frac{1}{x_+\, s\sqrt{2\pi}} \exp\!\left(-\frac{(\ln x_+ - m)^2}{2s^2}\right).\]A variable whose logarithm is normal with mean m and standard deviation s. The density is the normal density of \(\ln x\) divided by x, for \(x > 0\).
Intuition What you get when many small independent effects multiply instead of add: incomes, compounded prices, particle sizes, response times. Its logarithm is normal, so it is positive and skewed to the right. \(m\) and \(s\) describe \(\ln X\), not \(X\): the median is \(e^{m}\) and the mean \(e^{m + s^2/2}\).
Use it when you model positive quantities whose spread grows with their size, or evaluate a likelihood for them; the fitted \(m\) and \(s\) are the mean and standard deviation of the logged data. Passing the raw data’s mean and standard deviation is the classic mistake. For power-law tails use paretoPdf.
probabilistic-modellinglikelihood-evaluationskewed-data
def lognormalPdf(m, s, x) ≔ (x > 0) · normalPdf(m, s, ln(positive(x))) / positive(x)
lognormalCdf
lognormalCdf(m, s, x) · m mean of ln X · s standard deviation of ln X, positive · x point → probability broadcast shape
Let \(m \in \mathbb{R}\), \(s > 0\) and \(x \in \mathbb{R}\). Then
\[\operatorname{lognormalCdf}(m, s, x) = [x > 0]\; \operatorname{normalCdf}(m, s, \ln x_+).\]The normal CDF of \(\ln x\), for \(x > 0\).
Intuition The normal CDF read on a log axis: being below \(x\) is the same event as \(\ln X\) being below \(\ln x\), because the logarithm preserves order.
Use it when you need the share of a skewed positive quantity under a threshold: the fraction of requests faster than a latency target, of loans below a size, of particles passing a sieve. As \(1 - F\) it gives the exceedance probability for a latency or loss budget, subject to the usual \(10^{-16}\) limit on upper tails.
tail-probabilitiesskewed-data
def lognormalCdf(m, s, x) ≔ (x > 0) · normalCdf(m, s, ln(positive(x)))
lognormalQuantile
lognormalQuantile(m, s, p) · m mean of ln X · s standard deviation of ln X, positive · p probability → quantile broadcast shape
Let \(m \in \mathbb{R}\), \(s > 0\) and \(0 < p < 1\). Then
\[\operatorname{lognormalQuantile}(m, s, p) = \exp\big(\operatorname{normalQuantile}(m, s, p)\big) \approx e^{m + s\,\Phi^{-1}(p)}.\]The exponential of the normal quantile.
Intuition The normal quantile of \(\ln X\), exponentiated. Percentiles carry over directly, but intervals become lopsided: the upper bound sits further from the median than the lower bound.
Use it when you quote percentiles of a log-normal model (p95 or p99 latency, a price level under geometric Brownian motion at a horizon), build bounds for a positive quantity, or draw log-normal samples from uniforms.
percentilesconfidence-intervalsrandom-variate-generation
def lognormalQuantile(m, s, p) ≔ exp(normalQuantile(m, s, p))
bernoulliPdf
bernoulliPdf(q, x) · q probability of success · x outcome, 0 or 1 → probability broadcast shape
Let \(q \in [0, 1]\) be the probability of success and \(x \in \mathbb{R}\). Then
\[\operatorname{bernoulliPdf}(q, x) = [x = 1]\, q + [x = 0]\,(1 - q).\]The probability mass: q at 1, \(1 - q\) at 0, and 0 for any other value.
Intuition One yes/no trial that succeeds with probability \(q\): a coin flip, a click, a defective part. It is the building block of the geometric and binomial distributions.
Use it when you evaluate the likelihood of binary outcomes under predicted probabilities: the sum of the logs over observations is minus the log-loss (binary cross-entropy) a classifier minimises. Outcomes must be exactly 0 or 1; any other value gets probability 0. If a predicted \(q\) can be exactly 0 or 1, clamp it before taking logs. For the number of successes in \(n\) trials use binomialPdf.
binary-outcomeslikelihood-evaluationclassification
def bernoulliPdf(q, x) ≔ (x = 1) · q + (x = 0) · (1 − q)
bernoulliCdf
bernoulliCdf(q, x) · q probability of success · x point → probability broadcast shape
Let \(q \in [0, 1]\) and \(x \in \mathbb{R}\). Then
\[\operatorname{bernoulliCdf}(q, x) = [x \ge 0]\,(1 - q) + [x \ge 1]\, q .\]0 below 0, \(1 - q\) on [0, 1), and 1 from 1 upwards.
Intuition A two-step staircase: probability \(1 - q\) sits at 0 and the rest at 1, so the CDF jumps to \(1 - q\) at 0 and to 1 at 1.
Use it when a generic code path needs a CDF for every family, for example a randomised probability integral transform that checks the calibration of binary predictions. In most binary work you want bernoulliPdf (likelihoods) or bernoulliQuantile (simulation) instead.
binary-outcomesmodel-calibration
def bernoulliCdf(q, x) ≔ (x ≥ 0) · (1 − q) + (x ≥ 1) · q
bernoulliQuantile
bernoulliQuantile(q, p) · q probability of success · p probability → outcome 0 or 1 broadcast shape
Let \(q \in [0, 1]\) and \(p \in [0, 1]\). Then
\[\operatorname{bernoulliQuantile}(q, p) = [\,p > 1 - q\,].\]1 when \(p > 1 - q\), otherwise 0. Applied to uniform draws it produces Bernoulli trials.
Intuition Cuts [0, 1) at \(1 - q\): a uniform landing above the cut is a success, which happens with probability \(q\). Raising \(q\) lowers the cut, so with the same uniform a success never turns into a failure.
Use it when you simulate yes/no events (a customer converts, a packet is dropped, a unit is dropped out) from supplied uniforms. Reusing the same uniforms across scenarios gives common random numbers, which makes the differences between scenarios far less noisy than independent runs would.
simulationrandom-variate-generationbinary-outcomes
def bernoulliQuantile(q, p) ≔ (p > 1 − q)
geometricPdf
geometricPdf(q, x) · q probability of success per trial · x number of failures before the first success, a whole number → probability broadcast shape
Let \(q \in (0, 1]\) be the probability of success per trial and \(x \in \mathbb{R}\) (normally \(x \in \mathbb{N}\)). Then
\[\operatorname{geometricPdf}(q, x) = [x \ge 0]\; q\,(1 - q)^{x}.\]\(q\,(1 - q)^x\) for \(x = 0, 1, 2, \ldots\). The support starts at 0 (failures counted, not trials). A fractional x is not rounded.
Intuition The number of failures before the first success in independent trials that each succeed with probability \(q\): calls before a sale, retries before a packet gets through. It is the discrete waiting time and, like the exponential, memoryless. Counting starts at 0, and the mean is \((1 - q)/q\).
Use it when you model retry counts or run lengths, or evaluate the likelihood of observed failure counts. If your data count attempts including the success, subtract 1 first. A fractional \(x\) is not rounded, so pass whole numbers. For successes in a fixed number of trials use binomialPdf.
waiting-timescount-datalikelihood-evaluation
def geometricPdf(q, x) ≔ (x ≥ 0) · q · (1 − q)^x
geometricCdf
geometricCdf(q, x) · q probability of success per trial · x point → probability broadcast shape
Let \(q \in (0, 1]\) and \(x \in \mathbb{R}\). Then
\[\operatorname{geometricCdf}(q, x) = [x \ge 0]\,\Big(1 - (1 - q)^{\lfloor x \rfloor + 1}\Big).\]Intuition The probability that the first success comes within the first \(\lfloor x \rfloor + 1\) trials: one minus the chance that all of them fail.
Use it when you ask how many attempts are enough: the probability that a policy allowing up to 5 retries (6 attempts) eventually succeeds is geometricCdf(q, 5), and the same call gives the chance a user converts within a number of visits. Unlike geometricPdf, a fractional \(x\) is floored here.
waiting-timescount-datatail-probabilities
def geometricCdf(q, x) ≔ (x ≥ 0) · (1 − (1 − q)^(floor(x) + 1))
geometricQuantile
geometricQuantile(q, p) · q probability of success per trial · p probability → whole number broadcast shape
Let \(q \in (0, 1)\) and \(p \in (0, 1)\). Then
\[\operatorname{geometricQuantile}(q, p) = \left\lceil \frac{\ln (1 - p)_+}{\ln (1 - q)_+} - 1 \right\rceil .\]The smallest count k with \(P(X \le k) \ge p\). At \(p = 0\) the formula gives \(-1\) rather than 0.
Intuition The smallest failure count \(k\) whose CDF reaches \(p\), solved in closed form: take logarithms of \((1 - q)^{k+1} \le 1 - p\) and round up, with no search.
Use it when you size a retry budget for a target success probability, or draw geometric counts from uniforms. One edge case follows from the formula: at \(p = 0\) (a uniform draw of exactly 0) the ceiling of \(0 - 1\) gives \(-1\), not 0, so clamp the result at 0 when sampling.
random-variate-generationwaiting-timessimulation
def geometricQuantile(q, p) ≔ ceil(ln(positive(1 − p)) / ln(positive(1 − q)) − 1)
The regularised incomplete beta function
The regularised incomplete beta function is
\[I_x(a, b) = \frac{1}{B(a, b)} \int_0^x t^{a-1} (1 - t)^{b-1}\, dt\]It is evaluated by Lentz’s continued fraction (240 sub-steps). The fraction converges quickly for \(x < (a+1)/(a+b+2)\); on the other side the symmetry \(I_x(a, b) = 1 - I_{1-x}(b, a)\) is used.
betaI
betaI(a, b, x) · a first shape, positive · b second shape, positive · x point in [0, 1] → \(I_x(a, b)\) in [0, 1] broadcast shape
Let \(a > 0\), \(b > 0\), \(x \in [0, 1]\) and \(\xi = (a + 1)/(a + b + 2)\). Then
\[\operatorname{betaI}(a, b, x) = [x < \xi]\; \operatorname{betaNear}\big(a, b, \min(x, \xi)\big) + [x \ge \xi]\; \operatorname{betaFar}\big(a, b, \max(x, \xi)\big) \approx I_x(a, b),\]where
\[\operatorname{betaNear}(a, b, x) = \frac{x^{a} (1 - x)^{b}}{a\, B(a, b)}\, \operatorname{betacf}(a, b, x), \qquad \operatorname{betaFar}(a, b, x) = 1 - \frac{(1 - x)^{b}\, x^{a}}{b\, B(a, b)}\, \operatorname{betacf}(b, a, 1 - x),\]away from the guard thresholds, and \(\operatorname{betacf}\) is the continued fraction
\[\operatorname{betacf}(a, b, x) \approx \cfrac{1}{1 + \cfrac{\tau_0}{1 + \cfrac{\tau_1}{1 + \cfrac{\tau_2}{1 + \cdots}}}}, \qquad \tau_{2m-1} = \frac{m(b - m)\,x}{(a + 2m - 1)(a + 2m)}, \quad \tau_{2m} = -\frac{(a + m)(a + b + m)\,x}{(a + 2m)(a + 2m + 1)} \quad (m \ge 1 \text{ and } m \ge 0 \text{ respectively}),\]cut after 240 sub-steps (see the building blocks for the exact recurrence).
The regularised incomplete beta function, choosing the direct fraction or the symmetric one by the mask \(x < (a+1)/(a+b+2)\). It is the CDF of a beta distribution.
Intuition For whole \(a\) and \(b\), \(I_x(a, b)\) is the probability of at least \(a\) successes in \(a + b - 1\) trials with success probability \(x\); equivalently, the chance that the \(a\)-th smallest of \(a + b - 1\) uniform draws is at most \(x\). That is why beta, binomial, Student’s t and F probabilities all reduce to it.
Use it when you need a probability built on it that the module does not name, such as an order-statistic probability or a binomial upper tail. Prefer betaCdf, binomialCdf, studentCdf or fCdf when one fits. The continued fraction runs a fixed 240 sub-steps with no convergence test, so check very large shapes against a reference value.
proportionstail-probabilitieshypothesis-testing
def betaI(a, b, x) ≔ (x < betaEdge(a, b)) · betaNear(a, b, min(x, betaEdge(a, b))) + (x ≥ betaEdge(a, b)) · betaFar(a, b, max(x, betaEdge(a, b)))
Building blocks
bcOdd(j)— Let \(j \in \mathbb{N}\). Then \(\operatorname{bcOdd}(j) = j - 2\lfloor j/2 \rfloor = [\,j \text{ odd}\,]\). 1 when sub-step j is odd, 0 when even; selects the coefficient formula.bcFirst(a, b, x, m)— Let \(a, b > 0\), \(x \in [0, 1]\) and \(m \in \mathbb{R}\). Then \(\operatorname{bcFirst}(a, b, x, m) = m(b - m)\,x / \operatorname{guard}\big((a - 1 + 2m)(a + 2m)\big)\). The odd-step coefficient of the continued fraction.bcSecond(a, b, x, m)— Let \(a, b > 0\), \(x \in [0, 1]\) and \(m \in \mathbb{R}\). Then \(\operatorname{bcSecond}(a, b, x, m) = -(a + m)(a + b + m)\,x / \operatorname{guard}\big((a + 2m)(a + 1 + 2m)\big)\). The even-step coefficient of the continued fraction.bcTerm(a, b, x, j)— Let \(a, b > 0\), \(x \in [0, 1]\), \(j \in \mathbb{N}\) and \(\omega = j - 2\lfloor j/2 \rfloor\). Then \(\operatorname{bcTerm}(a, b, x, j) = \tau_j = \omega\, \operatorname{bcFirst}\big(a, b, x, \tfrac{j+1}{2}\big) + (1 - \omega)\, \operatorname{bcSecond}\big(a, b, x, \tfrac{j}{2}\big)\). The coefficient of sub-step j, chosen by parity.bcD(t, d)— Let \(t, d \in \mathbb{R}\). Then \(\operatorname{bcD}(t, d) = 1 / \operatorname{guard}(1 + t\,d)\). The Lentz D update for coefficient t.bcC(t, c)— Let \(t, c \in \mathbb{R}\). Then \(\operatorname{bcC}(t, c) = \operatorname{guard}\big(1 + t / \operatorname{guard}(c)\big)\). The Lentz C update for coefficient t.bcLoop(k, a, b, x, j, c, d, h, t)— Let \(k \in \mathbb{N}\), \(a, b > 0\), \(x \in [0, 1]\), \(j \in \mathbb{N}\) and \(c, d, h, t \in \mathbb{R}\), and write \(c' = \operatorname{bcC}(t, c)\) and \(d' = \operatorname{bcD}(t, d)\). Then \(\operatorname{bcLoop}(0, a, b, x, j, c, d, h, t) = h\) and \(\operatorname{bcLoop}(k, a, b, x, j, c, d, h, t) = \operatorname{bcLoop}(k - 1, a, b, x, j + 1, c', d', h\,d'\,c', \tau_{j+2})\) with \(\tau_{j+2} = \operatorname{bcTerm}(a, b, x, j + 2)\). Runs k Lentz sub-steps, carrying the current coefficient and the running value h.bcSeed(a, b, x)— Let \(a, b > 0\) and \(x \in [0, 1]\). Then \(\operatorname{bcSeed}(a, b, x) = 1 / \operatorname{guard}\big(1 - (a + b)\,x / \operatorname{guard}(a + 1)\big)\). The starting D (and value) of the fraction.betacf(a, b, x)— Let \(a, b > 0\) and \(x \in [0, 1]\), and \(\tau_j = \operatorname{bcTerm}(a, b, x, j)\). Let \(c_0 = 1\), \(d_0 = h_0 = \operatorname{bcSeed}(a, b, x)\), and for \(i = 1, \dots, 240\) let \(c_i = \operatorname{guard}(1 + \tau_i / \operatorname{guard}(c_{i-1}))\), \(d_i = 1/\operatorname{guard}(1 + \tau_i\, d_{i-1})\) and \(h_i = h_{i-1}\, d_i\, c_i\). Then \(\operatorname{betacf}(a, b, x) = h_{240}\). The continued fraction itself, 240 sub-steps.betaEdge(a, b)— Let \(a, b > 0\). Then \(\operatorname{betaEdge}(a, b) = \xi = (a + 1)/(a + b + 2)\). The switch-over point.betaFront(a, b, x)— Let \(a, b > 0\) and \(x \in [0, 1]\). Then \(\operatorname{betaFront}(a, b, x) = \exp\big(a \ln x_+ + b \ln (1 - x)_+ - \operatorname{lbeta}(a, b)\big)\). The prefactor x to the a, times (1 − x) to the b, divided by B(a, b).betaNear(a, b, x)— Let \(a, b > 0\) and \(x \in [0, 1]\). Then \(\operatorname{betaNear}(a, b, x) = \operatorname{betaFront}(a, b, x)\, \operatorname{betacf}(a, b, x) / \operatorname{guard}(a)\). The incomplete beta by the direct fraction; used below the switch-over point.betaFar(a, b, x)— Let \(a, b > 0\) and \(x \in [0, 1]\). Then \(\operatorname{betaFar}(a, b, x) = 1 - \operatorname{betaFront}(b, a, 1 - x)\, \operatorname{betacf}(b, a, 1 - x) / \operatorname{guard}(b)\). The incomplete beta by the symmetric fraction; used at or above the switch-over point.
Distributions from the incomplete gamma: χ², gamma, Poisson
The χ² distribution with v degrees of freedom is a gamma distribution with shape \(v/2\) and scale 2; the Poisson CDF is an upper incomplete gamma, \(P(X \le k) = Q(k + 1, \lambda)\), which turns a count distribution into a continuous computation.
chiPdf
chiPdf(v, x) · v degrees of freedom, positive · x point → density broadcast shape
Let \(v > 0\) be the degrees of freedom and \(x \in \mathbb{R}\). Then
\[\operatorname{chiPdf}(v, x) = [x > 0]\; \exp\!\left(\left(\frac v2 - 1\right) \ln x_+ - \frac x2 - \frac v2 \ln 2 - \operatorname{lgamma}\!\left(\frac v2\right)\right) \approx [x > 0]\; \frac{x^{v/2-1} e^{-x/2}}{2^{v/2}\,\Gamma(v/2)},\]with \(\ln 2\) written as the constant 0.6931471805599453.
The χ² density for \(x > 0\), and 0 otherwise.
Intuition The sum of \(v\) squared independent standard normals: the total squared deviation of \(v\) independent standardised errors. Its mean is \(v\), so a statistic near \(v\) is unremarkable. It is the gamma distribution with shape \(v/2\) and scale 2.
Use it when you evaluate the likelihood of a sum of squared standardised residuals or of a scaled sample variance (\((n-1)S^2/\sigma^2\) has \(n - 1\) degrees of freedom), or draw the reference curve of a χ² test. For p-values you need chiCdf, not the density.
hypothesis-testinglikelihood-evaluationgoodness-of-fit
def chiPdf(v, x) ≔ (x > 0) · exp((v / 2 − 1) · ln(positive(x)) − x / 2 − (v / 2) · 0.6931471805599453 − lgamma(v / 2))
chiCdf
chiCdf(v, x) · v degrees of freedom, positive · x point → probability broadcast shape
Let \(v > 0\) and \(x \in \mathbb{R}\). Then
\[\operatorname{chiCdf}(v, x) = [x > 0]\; \operatorname{lowerGamma}\!\left(\frac v2,\; \frac{\max(x, 0)}{2}\right) \approx [x > 0]\; P\!\left(\frac v2, \frac x2\right).\]For the p-value of a χ² statistic use 1 − chiCdf(v, x).
Intuition The probability that a sum of \(v\) squared standard normals is at most \(x\). A statistic far above \(v\) is unlikely under the null model, and the upper tail \(1 - F\) measures how unlikely.
Use it when you turn a χ² statistic into a p-value, 1 − chiCdf(v, x): a contingency-table test (chiSquared and freedom in Categorical), a goodness-of-fit test, or a likelihood-ratio test (\(2\,\Delta \ln L\), with as many degrees of freedom as constrained parameters). p-values below about \(10^{-16}\) come out as 0.
hypothesis-testinggoodness-of-fittail-probabilities
def chiCdf(v, x) ≔ (x > 0) · lowerGamma(v / 2, max(x, 0) / 2)
gammaPdf
gammaPdf(s, r, x) · s shape, positive · r scale θ, positive · x point → density broadcast shape
Let \(s > 0\) be the shape, \(\theta > 0\) (the argument r) the scale and \(x \in \mathbb{R}\). Then
The gamma density with shape s and scale θ (mean \(s\theta\)). For a rate β, pass \(1/\beta\).
Intuition The waiting time until the \(s\)-th event of a Poisson process whose mean gap is θ: a sum of \(s\) independent exponential waits. Non-integer \(s\) interpolates smoothly; small \(s\) is sharply skewed and large \(s\) looks normal. The mean is \(s\theta\) and the variance \(s\theta^2\).
Use it when you model positive, right-skewed totals (repair times, rainfall amounts, claim sizes) or use it as the conjugate prior for a Poisson rate. Watch the parameterisation: the argument r is the scale θ, so a rate β must be passed as \(1/\beta\). For a single wait, exponentialPdf takes the rate \(1/\theta\).
waiting-timesbayesian-updatinglikelihood-evaluation
def gammaPdf(s, r, x) ≔ (x > 0) · exp((s − 1) · ln(positive(x)) − x / r − s · ln(r) − lgamma(s))
gammaCdf
gammaCdf(s, r, x) · s shape, positive · r scale θ, positive · x point → probability broadcast shape
Let \(s > 0\), \(\theta > 0\) (the argument r) and \(x \in \mathbb{R}\). Then
Intuition The probability that the \(s\)-th event has arrived by time \(x\), or that a gamma-distributed total stays below \(x\).
Use it when you need the chance that \(s\) sequential exponential stages finish within a deadline (a multi-step job, a chain of repairs), a posterior probability from a gamma posterior on a rate (“the rate is below 2 per day”), or, as \(1 - F\), the tail probability of a gamma-modelled claim. As with gammaPdf, pass the scale, not the rate.
waiting-timestail-probabilitiesbayesian-updating
def gammaCdf(s, r, x) ≔ (x > 0) · lowerGamma(s, max(x, 0) / r)
poissonPdf
poissonPdf(l, x) · l mean λ, positive · x count, a whole number → probability broadcast shape
Let \(\lambda > 0\) (the argument l) be the mean and \(x \in \mathbb{R}\) (normally \(x \in \mathbb{N}\)). Then
The Poisson probability mass, computed through lgamma. It is intended for whole-number x; a
fractional x is not rounded and gives a smooth interpolation rather than 0.
Intuition The number of events in a fixed window when events occur independently at a constant average rate: calls per hour, defects per metre, arrivals per minute. \(\lambda\) is both the mean and the variance, and the distribution is the limit of a binomial with many trials and a small success probability.
Use it when you evaluate the likelihood of counts (Poisson regression, rare-event rates, anomaly scores on event counts). If counts vary more than their mean (overdispersion), a Poisson fit understates the uncertainty; the usual alternative, the negative binomial, is not in this module. The mass is computed in logs, so large λ and counts are safe; pass whole numbers.
count-datalikelihood-evaluationrare-events
def poissonPdf(l, x) ≔ (x ≥ 0) · exp(x · ln(positive(l)) − l − lgamma(x + 1))
poissonCdf
poissonCdf(l, x) · l mean λ, positive · x point → probability broadcast shape
Let \(\lambda > 0\) (the argument l) and \(x \in \mathbb{R}\). Then
Intuition The probability of at most \(\lfloor x \rfloor\) events when \(\lambda\) are expected, computed as one upper incomplete gamma rather than a sum of masses.
Use it when you ask whether an observed count is surprisingly high (the p-value for “at least \(k\)” is 1 − poissonCdf(l, k − 1)), plan capacity for peak counts, or set stock against random demand. Note the floor: poissonCdf(l, 2.9) equals poissonCdf(l, 2).
count-datahypothesis-testingcapacity-planning
def poissonCdf(l, x) ≔ (x ≥ 0) · upperGamma(floor(x) + 1, l)
Distributions from the incomplete beta: beta, Student’s t, F, binomial
Student’s t, F and the binomial CDF are all incomplete beta functions after a change of variable, so they share one continued fraction. The binomial identity is the discrete twin of the Poisson one: \(P(X \le k) = I_{1-q}(n - k,\; k + 1)\).
betaPdf
betaPdf(a, b, x) · a first shape, positive · b second shape, positive · x point → density broadcast shape
Let \(a > 0\) and \(b > 0\) be the shapes and \(x \in \mathbb{R}\). Then
\[\operatorname{betaPdf}(a, b, x) = [x > 0]\,[x < 1]\; \exp\!\big((a - 1) \ln x_+ + (b - 1) \ln (1 - x)_+ - \operatorname{lbeta}(a, b)\big) \approx [0 < x < 1]\; \frac{x^{a-1}(1 - x)^{b-1}}{B(a, b)}.\]The beta density for \(0 < x < 1\), and 0 otherwise.
Intuition A distribution over a probability or proportion in (0, 1). Read \(a - 1\) and \(b - 1\) as successes and failures already seen: for \(a, b > 1\) the peak is at \((a-1)/(a+b-2)\), and the curve narrows as \(a + b\) grows. \(a = b = 1\) is uniform, and \(a, b < 1\) is U-shaped.
Use it when you represent uncertainty about a rate: after \(k\) successes in \(n\) trials, a Beta\((a, b)\) prior becomes Beta\((a + k,\; b + n - k)\), the basis of Bayesian A/B testing and Thompson sampling. It also models bounded fractions such as a budget share. The density is set to 0 at the endpoints, even where the true density diverges.
proportionsbayesian-updatinguncertainty-quantification
def betaPdf(a, b, x) ≔ (x > 0) · (x < 1) · exp((a − 1) · ln(positive(x)) + (b − 1) · ln(positive(1 − x)) − lbeta(a, b))
betaCdf
betaCdf(a, b, x) · a first shape, positive · b second shape, positive · x point → probability broadcast shape
Let \(a > 0\), \(b > 0\) and \(x \in \mathbb{R}\). Then
\[\operatorname{betaCdf}(a, b, x) = [x > 0]\,\Big([x \ge 1] + [x < 1]\; \operatorname{betaI}\big(a, b, \min(\max(x, 0), 1)\big)\Big).\]\(I_x(a, b)\) on (0, 1), 0 at or below 0 and 1 at or above 1.
Intuition The probability that an unknown proportion is at most \(x\), for a belief described by Beta\((a, b)\).
Use it when you need a posterior probability such as “the conversion rate is below 5%” or “variant B beats a fixed target”, or the probability that a bounded fraction stays under a limit. Credible-interval bounds go the other way and come from betaQuantile. Arguments outside (0, 1) are safe: 0 at or below 0, 1 at or above 1.
proportionsbayesian-updatingtail-probabilities
def betaCdf(a, b, x) ≔ (x > 0) · ((x ≥ 1) + (x < 1) · betaI(a, b, min(max(x, 0), 1)))
studentPdf
studentPdf(v, t) · v degrees of freedom, positive · t point → density broadcast shape
Let \(v > 0\) be the degrees of freedom and \(t \in \mathbb{R}\). Then
\[\operatorname{studentPdf}(v, t) = \exp\!\Big(\operatorname{lgamma}\!\big(\tfrac{v+1}{2}\big) - \operatorname{lgamma}\!\big(\tfrac v2\big) - \tfrac12 \ln(v\pi)\Big) \left(1 + \frac{t^2}{v}\right)^{-\frac{v+1}{2}} \approx \frac{\Gamma\!\left(\frac{v+1}{2}\right)}{\sqrt{v\pi}\;\Gamma\!\left(\frac{v}{2}\right)} \left(1 + \frac{t^2}{v}\right)^{-\frac{v+1}{2}}.\]Student’s t density.
Intuition A standardised mean when the standard deviation is itself estimated from the data: the \(v\) degrees of freedom of that estimate set how much the tails are fattened. With \(v = 1\) it is the standard Cauchy; as \(v\) grows it approaches the standard normal. It takes no location or scale arguments.
Use it when you want a heavy-tailed likelihood that down-weights outliers (robust regression, noise models in Bayesian fits): standardise as \((x - m)/\sigma\) and divide the density by \(\sigma\). It also draws the reference curve of a t test. For probabilities use studentCdf.
heavy-tailsrobust-statisticslikelihood-evaluation
def studentPdf(v, t) ≔ exp(lgamma((v + 1) / 2) − lgamma(v / 2) − 0.5 · ln(v · 3.141592653589793)) · (1 + t · t / v)^(0 − (v + 1) / 2)
studentCdf
studentCdf(v, t) · v degrees of freedom, positive · t point → probability broadcast shape
Let \(v > 0\) and \(t \in \mathbb{R}\). Then
\[\operatorname{studentCdf}(v, t) = \frac12 + \operatorname{sign}(t)\left(\frac12 - \operatorname{studentTail}(v, t)\right), \qquad \operatorname{studentTail}(v, t) = \frac12\, \operatorname{betaI}\!\left(\frac v2,\; \frac12,\; \frac{v}{v + t^2}\right).\]The probability that a t variable is at most t, from the one-sided tail \(\tfrac12 I_{v/(v+t^2)}(v/2, \tfrac12)\). A two-sided p-value for a statistic t is \(2\,(1 - \operatorname{studentCdf}(v, \lvert t \rvert))\).
Intuition The probability that a t statistic with \(v\) degrees of freedom is at most \(t\). With few degrees of freedom the tails are heavier, so the same statistic is weaker evidence than it would be under the normal.
Use it when you compute a p-value for a one- or two-sample t test, a regression coefficient, or any mean comparison with a small sample and an estimated variance. The two-sided p-value is \(2\,(1 - F(\lvert t \rvert))\), as in the Examples. As \(v\) grows the answer approaches normalCdf(0, 1, t).
hypothesis-testingcomparing-groupstail-probabilities
def studentCdf(v, t) ≔ 0.5 + sign(t) · (0.5 − studentTail(v, t))
fPdf
fPdf(d1, d2, x) · d1 numerator degrees of freedom, positive · d2 denominator degrees of freedom, positive · x point → density broadcast shape
Let \(d_1 > 0\) and \(d_2 > 0\) (the arguments d1, d2) be the degrees of freedom and \(x \in \mathbb{R}\). Then
which for \(x > 0\) is
\[\frac{d_1^{d_1/2}\, d_2^{d_2/2}\, x^{d_1/2 - 1}}{(d_1 x + d_2)^{(d_1+d_2)/2}\, B(d_1/2,\, d_2/2)} .\]The F density, computed in logarithms.
Intuition The ratio of two independent variance estimates, each a χ² divided by its degrees of freedom: \(d_1\) above the line, \(d_2\) below. When the true variances are equal the ratio sits near 1; values far above 1 mean the numerator’s source of variation dominates.
Use it when you evaluate the likelihood or draw the null curve of an ANOVA, regression or variance-ratio statistic. For p-values use fCdf. The density is computed in logs, so large degrees of freedom are safe.
hypothesis-testingcomparing-variances
def fPdf(d1, d2, x) ≔ (x > 0) · exp((d1 / 2) · ln(d1) + (d2 / 2) · ln(d2) + (d1 / 2 − 1) · ln(positive(x)) − ((d1 + d2) / 2) · ln(d1 · positive(x) + d2) − lbeta(d1 / 2, d2 / 2))
fCdf
fCdf(d1, d2, x) · d1 numerator degrees of freedom · d2 denominator degrees of freedom · x point → probability broadcast shape
Let \(d_1, d_2 > 0\) (the arguments d1, d2) and \(x \in \mathbb{R}\), and write \(x^{*} = \max(x, 0)\). Then
\(I_{d_1 x/(d_1 x + d_2)}(d_1/2,\; d_2/2)\) for \(x > 0\).
Intuition The probability that a variance ratio is at most \(x\) when the two underlying variances are truly equal.
Use it when you turn an F statistic into a p-value, 1 − fCdf(d1, d2, x): one-way ANOVA (between-group over within-group mean squares), the overall F test of a regression, a nested-model comparison, or a test of equal variances. Order matters: swapping \(d_1\) and \(d_2\) describes \(1/F\), not \(F\).
hypothesis-testingcomparing-variancescomparing-groups
def fCdf(d1, d2, x) ≔ (x > 0) · betaI(d1 / 2, d2 / 2, d1 · max(x, 0) / (d1 · max(x, 0) + d2))
binomialPdf
binomialPdf(n, q, x) · n number of trials · q probability of success · x number of successes, a whole number → probability broadcast shape
Let \(n \in \mathbb{N}\) be the number of trials, \(q \in [0, 1]\) the probability of success and \(x \in \mathbb{R}\) (normally \(x \in \{0, \dots, n\}\)). Then
\[\operatorname{binomialPdf}(n, q, x) = [x \ge 0]\,[x \le n]\; \exp\!\big(\operatorname{lgamma}(n + 1) - \operatorname{lgamma}(x + 1) - \operatorname{lgamma}(n - x + 1) + x \ln q_+ + (n - x) \ln (1 - q)_+\big),\]which for whole \(x\) is \(\binom{n}{x} q^x (1 - q)^{n-x}\).
The binomial probability mass for \(0 \le x \le n\), computed through lgamma. Like poissonPdf, it
expects whole-number x and does not round.
Intuition The number of successes in \(n\) independent trials that each succeed with probability \(q\): a sum of \(n\) Bernoulli outcomes. The mean is \(nq\); the shape is symmetric at \(q = \tfrac12\) and skewed otherwise.
Use it when you evaluate the likelihood of \(k\) successes out of \(n\) (conversions from visitors, defects in a batch, correct answers on a test), or need exact probabilities where a normal approximation is crude: small \(n\), or \(q\) near 0 or 1. It is computed in logs, so large \(n\) is safe; pass a whole-number \(x\). For a rare event over very many trials, poissonPdf is the simpler limit.
count-dataproportionslikelihood-evaluation
def binomialPdf(n, q, x) ≔ (x ≥ 0) · (x ≤ n) · exp(lgamma(n + 1) − lgamma(x + 1) − lgamma(n − x + 1) + x · ln(positive(q)) + (n − x) · ln(positive(1 − q)))
binomialCdf
binomialCdf(n, q, x) · n number of trials · q probability of success · x point → probability broadcast shape
Let \(n \in \mathbb{N}\), \(q \in [0, 1]\) and \(x \in \mathbb{R}\). Then
\[\operatorname{binomialCdf}(n, q, x) = [x \ge n] + [x \ge 0]\,[x < n]\; \operatorname{betaI}\big(n - \lfloor x \rfloor,\; \lfloor x \rfloor + 1,\; 1 - q\big).\]\(P(X \le \lfloor x \rfloor)\), via \(I_{1-q}(n - \lfloor x \rfloor,\; \lfloor x \rfloor + 1)\); 1 for \(x \ge n\).
Intuition The probability of at most \(\lfloor x \rfloor\) successes, obtained from one incomplete beta instead of adding up to \(n + 1\) masses.
Use it when you run an exact binomial test (are 9 defects in 100 more than a 5% process allows? The p-value is 1 − binomialCdf(100, 0.05, 8)), check an acceptance-sampling plan, or compute the chance that a quorum or majority is reached. Arguments at or past \(n\) give 1, and negative ones give 0.
hypothesis-testingproportionsquality-control
def binomialCdf(n, q, x) ≔ (x ≥ n) + (x ≥ 0) · (x < n) · betaI(n − floor(x), floor(x) + 1, 1 − q)
Building blocks
studentTail(v, t)— Let \(v > 0\) and \(t \in \mathbb{R}\). Then \(\operatorname{studentTail}(v, t) = \tfrac12\, \operatorname{betaI}\big(v/2,\; \tfrac12,\; v/(v + t^2)\big)\). The probability beyond the absolute value of t in one tail; used bystudentCdf.
Quantiles without a closed form
For Student’s t, χ² and gamma the quantile is found by Newton’s method on the CDF, \(x \leftarrow x - (F(x) - p)/f(x)\), for a fixed 60 steps from a starting point that is already close. The beta quantile uses bisection instead, which cannot fail; the F quantile is obtained from the beta quantile.
studentQuantile
studentQuantile(v, p) · v degrees of freedom, positive · p probability in (0, 1) → quantile broadcast shape
Let \(v > 0\) and \(0 < p < 1\). Let \(x_0 = \operatorname{standardQuantile}(p)\) and
\[x_{k+1} = x_k - \frac{\operatorname{studentCdf}(v, x_k) - p}{\operatorname{guard}\big(\operatorname{studentPdf}(v, x_k)\big)}, \qquad k = 0, 1, \dots, 59 .\]Then \(\operatorname{studentQuantile}(v, p) = x_{60}\).
The value t with \(P(T \le t) = p\). Newton’s method starts from the standard normal quantile, which
t approaches as the degrees of freedom grow. For a two-sided test at level α use
studentQuantile(v, 1 − α/2).
Intuition The t critical value: how many estimated standard errors to step away from an estimate to capture probability \(p\). For small \(v\) it exceeds the normal value (2.228 against 1.96 at \(v = 10\) and \(p = 0.975\)); that gap is the price of estimating the variance.
Use it when you build a confidence interval for a mean or a regression coefficient, \(\hat\mu \pm t_{v,\,1-\alpha/2}\,\mathrm{SE}\), or need a critical value for a t test. Each call runs 60 Newton steps, each one an incomplete-beta evaluation, so compute it once per \((v, p)\) rather than once per observation.
confidence-intervalshypothesis-testing
def studentQuantile(v, p) ≔ tLoop(60, v, p, standardQuantile(p))
chiQuantile
chiQuantile(v, p) · v degrees of freedom, positive · p probability in (0, 1) → quantile broadcast shape
Let \(v > 0\) and \(0 < p < 1\). Let \(x_0 = \max\big(\operatorname{wilson}(v, p),\, 10^{-6}\big)\) and
\[x_{k+1} = \max\!\left(x_k - \frac{\operatorname{chiCdf}(v, x_k) - p}{\operatorname{guard}\big(\operatorname{chiPdf}(v, x_k)\big)},\; 10^{-12}\right), \qquad k = 0, 1, \dots, 59 .\]Then \(\operatorname{chiQuantile}(v, p) = x_{60}\).
The χ² critical value with \(P(X \le x) = p\). Newton’s method starts from the Wilson–Hilferty approximation (the cube root of \(\chi^2/v\) is nearly normal) and keeps every iterate positive.
Intuition The value that a sum of \(v\) squared standard normals stays below with probability \(p\): the rejection threshold of a χ² test, and the squared radius of a Gaussian confidence ellipsoid in \(v\) dimensions.
Use it when you need a critical value (reject independence when chiSquared exceeds chiQuantile(freedom, 0.95)), a confidence interval for a normal variance, \(\big[(n-1)S^2/\chi^2_{1-\alpha/2},\; (n-1)S^2/\chi^2_{\alpha/2}\big]\) on \(n - 1\) degrees of freedom, or the size of a confidence ellipse. Like studentQuantile it runs 60 Newton steps, so compute it once rather than per data point.
confidence-intervalshypothesis-testinggoodness-of-fit
def chiQuantile(v, p) ≔ chiLoop(60, v, p, max(wilson(v, p), 1e-6))
gammaQuantile
gammaQuantile(s, r, p) · s shape, positive · r scale θ, positive · p probability in (0, 1) → quantile broadcast shape
Let \(s > 0\), \(\theta > 0\) (the argument r) and \(0 < p < 1\). Let \(x_0 = \theta \max\big(\operatorname{wilson}(2s, p)/2,\, 10^{-6}\big)\) and
Then \(\operatorname{gammaQuantile}(s, \theta, p) = x_{60}\).
The gamma quantile, by Newton’s method from the Wilson–Hilferty starting point for the matching χ² (2s degrees of freedom), scaled by θ.
Intuition The time by which the \(s\)-th event of a process with mean gap θ has arrived with probability \(p\). It equals θ/2 times the χ² quantile with \(2s\) degrees of freedom, which is where its starting point comes from.
Use it when you need a credible interval for a Poisson rate from a gamma posterior, a duration that a multi-stage process meets with a given probability, or an exact (Garwood) confidence interval for a Poisson mean, whose bounds are gamma quantiles with unit scale. Pass the scale θ, not a rate. At 60 Newton steps per value it is too slow to use as a per-draw sampler in large simulations.
confidence-intervalsbayesian-updatingwaiting-times
def gammaQuantile(s, r, p) ≔ gammaLoop(60, s, r, p, r · max(wilson(2 · s, p) / 2, 1e-6))
betaQuantile
betaQuantile(a, b, p) · a first shape, positive · b second shape, positive · p probability in [0, 1] → quantile in [0, 1] broadcast shape
Let \(a > 0\), \(b > 0\) and \(p \in [0, 1]\). Let \(\ell_0 = 0\) and \(u_0 = 1\), and for \(k = 0, 1, \dots, 59\) let \(\mu_k = (\ell_k + u_k)/2\), \(\omega_k = [\operatorname{betaCdf}(a, b, \mu_k) < p]\) and
\[\ell_{k+1} = \omega_k\, \mu_k + (1 - \omega_k)\, \ell_k, \qquad u_{k+1} = \omega_k\, u_k + (1 - \omega_k)\, \mu_k .\]Then \(\operatorname{betaQuantile}(a, b, p) = \mu_{60} = (\ell_{60} + u_{60})/2\).
The beta quantile by bisection on [0, 1]: 60 halvings, which exhausts double precision. Bisection is used because densities such as Beta(½, ½) diverge at the ends, where Newton’s method stalls. The price is several incomplete-beta evaluations per step, so this is the most expensive quantile in the module.
Intuition The proportion below which a Beta\((a, b)\) belief places probability \(p\). It is found by halving [0, 1] sixty times, which cannot fail even for U-shaped densities where Newton’s method stalls.
Use it when you report a Bayesian credible interval for a rate (the posterior quantiles at \(\alpha/2\) and \(1 - \alpha/2\)), compute an exact Clopper–Pearson interval for a binomial proportion (its bounds are beta quantiles), or feed fQuantile. It is the most expensive quantile in the module, so avoid it as a per-draw sampler in large simulations.
confidence-intervalsproportionsbayesian-updating
def betaQuantile(a, b, p) ≔ betaLoop(60, a, b, p, 0, 1)
fQuantile
fQuantile(d1, d2, p) · d1 numerator degrees of freedom · d2 denominator degrees of freedom · p probability in (0, 1) → quantile broadcast shape
Let \(d_1, d_2 > 0\) (the arguments d1, d2), \(0 < p < 1\) and \(y = \operatorname{betaQuantile}(d_1/2, d_2/2, p)\). Then
The F critical value. The F CDF is an incomplete beta, so the beta quantile y of \((d_1/2, d_2/2)\) is transformed back as \(d_2\, y / \big(d_1 (1 - y)\big)\).
Intuition The F critical value, with no iteration of its own: an F ratio \(x\) corresponds to the beta variable \(d_1 x/(d_1 x + d_2)\), so inverting the beta and mapping the answer back inverts the F.
Use it when you need the rejection threshold of an ANOVA or regression F test at level α, fQuantile(d1, d2, 1 − α), or confidence bounds for the ratio of two normal variances. It inherits the cost of betaQuantile, so compute it once per test.
hypothesis-testingcomparing-variancesconfidence-intervals
def fQuantile(d1, d2, p) ≔ d2 · betaQuantile(d1 / 2, d2 / 2, p) / guard(d1 · (1 − betaQuantile(d1 / 2, d2 / 2, p)))
Building blocks
tTurn(v, p, x)— Let \(v > 0\), \(p \in (0, 1)\) and \(x \in \mathbb{R}\). Then \(\operatorname{tTurn}(v, p, x) = x - \big(\operatorname{studentCdf}(v, x) - p\big) / \operatorname{guard}\big(\operatorname{studentPdf}(v, x)\big)\). One Newton step on the Student CDF.tLoop(k, v, p, x)— Let \(k \in \mathbb{N}\), \(v > 0\), \(p \in (0, 1)\) and \(x \in \mathbb{R}\). Then \(\operatorname{tLoop}(0, v, p, x) = x\) and \(\operatorname{tLoop}(k, v, p, x) = \operatorname{tLoop}(k - 1, v, p, \operatorname{tTurn}(v, p, x))\). RepeatstTurnk times; used bystudentQuantile.wilson(v, p)— Let \(v > 0\), \(p \in (0, 1)\) and \(z = \operatorname{standardQuantile}(p)\). Then \(\operatorname{wilson}(v, p) = v \Big(1 - \frac{2}{9v} + z \sqrt{\frac{2}{9v}}\Big)^{3}\). The Wilson–Hilferty approximation to the χ² quantile; the starting point for χ² and gamma.chiTurn(v, p, x)— Let \(v > 0\), \(p \in (0, 1)\) and \(x \in \mathbb{R}\). Then \(\operatorname{chiTurn}(v, p, x) = \max\big(x - (\operatorname{chiCdf}(v, x) - p) / \operatorname{guard}(\operatorname{chiPdf}(v, x)),\; 10^{-12}\big)\). One Newton step on the χ² CDF, kept positive.chiLoop(k, v, p, x)— Let \(k \in \mathbb{N}\), \(v > 0\), \(p \in (0, 1)\) and \(x \in \mathbb{R}\). Then \(\operatorname{chiLoop}(0, v, p, x) = x\) and \(\operatorname{chiLoop}(k, v, p, x) = \operatorname{chiLoop}(k - 1, v, p, \operatorname{chiTurn}(v, p, x))\). RepeatschiTurnk times; used bychiQuantile.gammaTurn(s, r, p, x)— Let \(s > 0\), \(\theta > 0\) (the argumentr), \(p \in (0, 1)\) and \(x \in \mathbb{R}\). Then \(\operatorname{gammaTurn}(s, \theta, p, x) = \max\big(x - (\operatorname{gammaCdf}(s, \theta, x) - p) / \operatorname{guard}(\operatorname{gammaPdf}(s, \theta, x)),\; 10^{-12}\big)\). One Newton step on the gamma CDF, kept positive.gammaLoop(k, s, r, p, x)— Let \(k \in \mathbb{N}\), \(s > 0\), \(\theta > 0\) (the argumentr), \(p \in (0, 1)\) and \(x \in \mathbb{R}\). Then \(\operatorname{gammaLoop}(0, s, \theta, p, x) = x\) and \(\operatorname{gammaLoop}(k, s, \theta, p, x) = \operatorname{gammaLoop}(k - 1, s, \theta, p, \operatorname{gammaTurn}(s, \theta, p, x))\). RepeatsgammaTurnk times; used bygammaQuantile.betaMid(lo, hi)— Let \(\ell, u \in \mathbb{R}\) (the argumentslo,hi). Then \(\operatorname{betaMid}(\ell, u) = (\ell + u)/2\). The midpoint of the bisection interval.betaUnder(a, b, p, lo, hi)— Let \(a, b > 0\), \(p \in [0, 1]\), \(\ell, u \in [0, 1]\) (the argumentslo,hi) and \(\mu = (\ell + u)/2\). Then \(\operatorname{betaUnder}(a, b, p, \ell, u) = [\operatorname{betaCdf}(a, b, \mu) < p]\). 1 when the beta CDF at the midpoint is below p, else 0.betaLow(a, b, p, lo, hi)— Let \(a, b, p, \ell, u, \mu\) be as inbetaUnderand \(\omega = \operatorname{betaUnder}(a, b, p, \ell, u)\). Then \(\operatorname{betaLow}(a, b, p, \ell, u) = \omega\,\mu + (1 - \omega)\,\ell\). The new lower end of the interval.betaHigh(a, b, p, lo, hi)— Let \(a, b, p, \ell, u, \mu\) and \(\omega\) be as inbetaLow. Then \(\operatorname{betaHigh}(a, b, p, \ell, u) = \omega\,u + (1 - \omega)\,\mu\). The new upper end of the interval.betaLoop(k, a, b, p, lo, hi)— Let \(k \in \mathbb{N}\) and \(a, b, p, \ell, u\) be as inbetaUnder. Then \(\operatorname{betaLoop}(0, a, b, p, \ell, u) = (\ell + u)/2\) and \(\operatorname{betaLoop}(k, a, b, p, \ell, u) = \operatorname{betaLoop}\big(k - 1, a, b, p, \operatorname{betaLow}(a, b, p, \ell, u), \operatorname{betaHigh}(a, b, p, \ell, u)\big)\). Runs k bisection steps and returns the final midpoint; used bybetaQuantile.
Quantiles of counts
A discrete CDF is a step function, so Newton’s method cannot invert it. The quantile of a count is the smallest k whose CDF reaches p, found by counting upwards from 0 and stopping on the data. The cost therefore grows with the answer.
poissonQuantile
poissonQuantile(l, p) · l mean λ, positive · p probability in (0, 1) → whole number scalar
Let \(\lambda > 0\) (the argument l) and \(0 < p < 1\). Then
The smallest k with \(P(X \le k) \ge p\) for a Poisson variable with mean λ.
Intuition The smallest count \(k\) that covers probability \(p\): stock \(k\) units and Poisson demand exceeds the stock with probability at most \(1 - p\). It is found by trying \(k = 0, 1, 2, \dots\) until the CDF reaches \(p\).
Use it when you size capacity or inventory for a service level, set an alert threshold on event counts, or draw Poisson counts from uniforms. The cost grows with the answer (about λ steps for central \(p\), each an incomplete-gamma evaluation), so large λ is slow; there normalQuantile(l, sqrt(l), p) is a close approximation. A \(p\) very close to 1 makes the search long.
capacity-planningcount-datarandom-variate-generation
def poissonQuantile(l, p) ≔ poissonFrom(0, l, p)
binomialQuantile
binomialQuantile(n, q, p) · n number of trials · q probability of success · p probability in (0, 1] → whole number scalar
Let \(n \in \mathbb{N}\), \(q \in [0, 1]\) and \(0 < p \le 1\). Then
\[\operatorname{binomialQuantile}(n, q, p) = \operatorname{binomialFrom}(0, n, q, p) = \min\{\, k \in \{0, 1, 2, \dots\} : \operatorname{binomialCdf}(n, q, k) \ge p \,\}.\]The smallest k with \(P(X \le k) \ge p\) for a binomial variable; never more than n, because \(\operatorname{binomialCdf}(n, q, n) = 1\).
Intuition The smallest number of successes \(k\) out of \(n\) whose cumulative probability reaches \(p\), found by counting up from 0; it never passes \(n\).
Use it when you set an acceptance threshold (reject a batch whose defects exceed binomialQuantile(n, q, 0.95)), plan overbooking (how many of \(n\) booked customers show up, at 99% confidence), or draw binomial counts from uniforms. The cost grows with the answer, up to \(n + 1\) CDF evaluations.
quality-controlcapacity-planningrandom-variate-generation
def binomialQuantile(n, q, p) ≔ binomialFrom(0, n, q, p)
Building blocks
poissonFrom(k, l, p)— Let \(k \in \mathbb{N}\), \(\lambda > 0\) (the argumentl) and \(p \in (0, 1)\). Then \(\operatorname{poissonFrom}(k, \lambda, p) = k\) if \(\operatorname{poissonCdf}(\lambda, k) \ge p\), and \(\operatorname{poissonFrom}(k, \lambda, p) = \operatorname{poissonFrom}(k + 1, \lambda, p)\) otherwise. Returns k if the Poisson CDF at k has reached p, otherwise tries k + 1.binomialFrom(k, n, q, p)— Let \(k, n \in \mathbb{N}\), \(q \in [0, 1]\) and \(p \in (0, 1]\). Then \(\operatorname{binomialFrom}(k, n, q, p) = k\) if \(\operatorname{binomialCdf}(n, q, k) \ge p\), and \(\operatorname{binomialFrom}(k, n, q, p) = \operatorname{binomialFrom}(k + 1, n, q, p)\) otherwise. Returns k if the binomial CDF at k has reached p, otherwise tries k + 1.
Examples
All examples below are compiled from one file, Probability.hb, so the C# class is Probability.
Each snippet shows only the doorways that example uses.
Probabilities and cut-offs of the normal
What fraction of a normal population with mean 100 and standard deviation 15 lies below 130, and which score marks the top 10%?
open Prelude.Distributions
fn belowNormal(m, s, x) ↦ normalCdf(m, s, x)
fn normalCut(m, s, p) ↦ normalQuantile(m, s, p)
using Examples;
double below = Probability.BelowNormal(100.0, 15.0, 130.0);
double top10 = Probability.NormalCut(100.0, 15.0, 0.9);
double z975 = Probability.NormalCut(0.0, 1.0, 0.975);
Output (verified, rounded to ten significant digits):
normalCdf(100, 15, 130) = 0.9772498681
normalQuantile(100, 15, 0.9) = 119.2232734832
normalQuantile(0, 1, 0.975) = 1.9599639845
130 is two standard deviations above the mean, so the answer is \(\Phi(2) \approx 0.97725\); the familiar 1.96 is the 97.5% point of the standard normal.
Turn uniform draws into samples
Sampling is a quantile applied to uniform draws. Here the draws are chosen by hand so the results can be checked: 0.5 is the median, 0.8413447 is \(\Phi(1)\) and 0.0227501 is \(\Phi(-2)\).
open Prelude.Distributions
fn normalDraws(m, s, u) ↦ normalSample(m, s, u)
fn exponentialDraws(r, u) ↦ exponentialQuantile(r, u)
var normals = Probability.NormalDraws(10.0, 2.0, new[] { 0.5, 0.8413447, 0.0227501, 0.975 });
var waits = Probability.ExponentialDraws(2.0, new[] { 0.0, 0.5, 0.75 });
Output (verified, rounded to six decimal places):
normalSample(10, 2, u) = [10, 12, 5.999999, 13.919928]
exponentialQuantile(2, u) = [0, 0.346574, 0.693147]
The normal draws are the mean, one and minus two standard deviations away (the 5.999999 reflects the rounded input), and the 97.5% point. The exponential draws with rate 2 are \(-\ln(1-u)/2\): 0, \(\ln 2 / 2\) and \(\ln 4 / 2\).
A t-test p-value and critical value
A t statistic of 2.228 on 10 degrees of freedom, and the critical values for a two-sided 5% test at 10 and a one-sided 5% test at 3 degrees of freedom.
open Prelude.Distributions
fn tTwoSided(v, t) ↦ 2 · (1 − studentCdf(v, abs(t)))
fn tCritical(v, p) ↦ studentQuantile(v, p)
double pValue = Probability.TTwoSided(10.0, 2.228);
double crit10 = Probability.TCritical(10.0, 0.975);
double crit3 = Probability.TCritical(3.0, 0.95);
Output (verified, rounded to six significant digits):
two-sided p (v = 10, t = 2.228) = 0.0500118
studentQuantile(10, 0.975) = 2.22814
studentQuantile(3, 0.95) = 2.35336
These match the printed t tables (2.228 and 2.353).
A χ² p-value and critical value
open Prelude.Distributions
fn chiPValue(v, x) ↦ 1 − chiCdf(v, x)
fn chiCritical(v, p) ↦ chiQuantile(v, p)
double p = Probability.ChiPValue(2.0, 5.991);
double crit = Probability.ChiCritical(4.0, 0.95);
Output (verified, rounded to six significant digits):
1 − chiCdf(2, 5.991) = 0.0500116
chiQuantile(4, 0.95) = 9.48773
With 2 degrees of freedom the χ² upper tail is \(e^{-x/2}\), and \(e^{-5.991/2} \approx 0.05\); 9.488 is the tabulated 5% point for 4 degrees of freedom.
Counts: Poisson and binomial
The chance of at most 2 events when 3 are expected, the 90% point of that Poisson, and binomial probabilities for fair coin tosses.
open Prelude.Distributions
fn poissonAtMost(l, k) ↦ poissonCdf(l, k)
fn poissonCut(l, p) ↦ poissonQuantile(l, p)
fn binomialAtMost(n, q, k) ↦ binomialCdf(n, q, k)
fn binomialMass(n, q, k) ↦ binomialPdf(n, q, k)
double atMost2 = Probability.PoissonAtMost(3.0, 2.0);
double cut90 = Probability.PoissonCut(3.0, 0.9);
double heads3 = Probability.BinomialAtMost(10.0, 0.5, 3.0);
var masses = Probability.BinomialMass(4.0, 0.5, new[] { 0d, 1d, 2d, 3d, 4d });
Output (verified, rounded to six significant digits):
poissonCdf(3, 2) = 0.423190
poissonQuantile(3, 0.9) = 5
binomialCdf(10, 0.5, 3) = 0.171875
binomialPdf(4, 0.5, 0..4) = [0.0625, 0.25, 0.375, 0.25, 0.0625]
By hand: \(e^{-3}(1 + 3 + 4.5) \approx 0.42319\); at most 3 heads in 10 tosses is \((1 + 10 + 45 + 120)/1024 = 0.171875\); and four tosses give \(\tfrac{1}{16}(1, 4, 6, 4, 1)\).
Special functions and a U-shaped beta
open Prelude.Distributions
fn errorFunction(x) ↦ erf(x)
fn logGamma(a) ↦ lgamma(a)
fn betaCut(a, b, p) ↦ betaQuantile(a, b, p)
double erf1 = Probability.ErrorFunction(1.0);
double lg5 = Probability.LogGamma(5.0);
double lgHalf = Probability.LogGamma(0.5);
double q99 = Probability.BetaCut(0.5, 0.5, 0.99);
Output (verified, rounded to ten significant digits):
erf(1) = 0.8427007929
lgamma(5) = 3.1780538303
lgamma(0.5) = 0.5723649429
betaQuantile(0.5, 0.5, 0.99) = 0.9997532802
\(\ln\Gamma(5) = \ln 24\) and \(\ln\Gamma(\tfrac12) = \ln\sqrt\pi\). Beta(½, ½) is the arcsine distribution, whose quantile is \(\sin^2(\pi p / 2)\); at \(p = 0.99\) that is 0.99975328.