Guides
Probability distributions
The extension provides 182 probability-evaluation functions: 13 parameterizations, seven operations each, and scalar plus native _array forms, plus 13 explicitly seeded batch sampling functions. Uniform, categorical and permutation samplers have no probability functions and are described there. These return ordinary PHP numbers and arrays. Distribution evaluation is separate from regression fitting; fit_poisson() still fits a count model, while dist_poisson_pmf() evaluates a specified Poisson distribution. Descriptive statistics add ten functions for supplied numeric slices. Posterior-draw kernels handle literal draw matrices.
Families and parameterizations
Replace {family} in the operation names below with one of these names. PHP numeric arguments accept integers or floats; binomial size specifically requires an integer. All parameters must be finite and satisfy their domains.
| Family | Parameters in call order | Support and conventions |
|---|---|---|
normal |
mean = 0, sd = 1 |
Real line; sd > 0 |
t |
df |
Standard Student t; df > 0, no location/scale arguments |
chisquare |
df |
Nonnegative; df > 0 |
f |
df1, df2 |
Nonnegative; numerator/denominator df both positive |
beta |
alpha, beta |
[0,1]; both shape parameters positive |
gamma |
shape, scale = 1 |
Nonnegative; both positive; mean shape * scale |
exponential |
rate = 1 |
Nonnegative; positive rate; mean 1/rate |
lognormal |
meanlog = 0, sdlog = 1 |
Positive; log X is Normal(meanlog, sdlog); sdlog > 0 |
logistic |
location = 0, scale = 1 |
Real line; positive scale |
binomial |
size, prob |
Integer successes 0..size; size 0..2^53, prob [0,1] |
poisson |
lambda |
Nonnegative integer counts; lambda nonnegative |
nbinom |
size, prob |
Failures before size-th success; real size > 0, prob (0,1] |
nbinom_mu |
size, mu |
Same negative binomial; size > 0, mu ≥ 0; variance mu + mu^2/size |
Gamma’s second parameter is scale, exponential’s is rate. Negative-binomial size is a positive real dispersion/shape parameter, not a binomial trial count. The two NB forms are equivalent when prob = size/(size + mu). Poisson lambda zero, binomial size zero/prob zero/prob one, and NB prob one/mu zero represent point masses. Parameter conversion in the mean-form NB avoids overflowing size + mu.
Scalar and batch operations
| Operation | Scalar function | Definition |
|---|---|---|
| Density | dist_{family}_pdf(x, ...parameters) |
Continuous density f(x) |
| Log density | dist_{family}_logpdf(x, ...parameters) |
Natural log of density |
| Mass | dist_{family}_pmf(k, ...parameters) |
Discrete P(X = k) |
| Log mass | dist_{family}_logpmf(k, ...parameters) |
Natural log of mass |
| CDF | dist_{family}_cdf(x_or_k, ...parameters) |
P(X ≤ x) |
| Log CDF | dist_{family}_logcdf(x_or_k, ...parameters) |
ln P(X ≤ x) |
| Survival | dist_{family}_sf(x_or_k, ...parameters) |
P(X > x), evaluated directly |
| Log survival | dist_{family}_logsf(x_or_k, ...parameters) |
ln P(X > x) |
| Quantile | dist_{family}_quantile(p, ...parameters) |
Inverse CDF; p in [0,1] |
Continuous families expose pdf/logpdf; discrete families expose pmf/logpmf. Every operation has an _array function taking a PHP array as its first argument and the same parameters/defaults, for example:
$probability = Phit\dist_normal_cdf(x: 1.96); // Approximately 0.975.
$tails = Phit\dist_t_sf_array(values: [1, 2, 3], df: 12);
$logMass = Phit\dist_poisson_logpmf_array(counts: [0, 2, 5], lambda: 3.2);
$interval = Phit\dist_gamma_quantile_array(probabilities: [.025, .975], shape: 2, scale: 3);Scalar continuous evaluation uses argument x; discrete uses k. Batch continuous evaluation uses values; discrete uses counts; all batch quantiles use probabilities. Parameter names are part of the contract because PHP supports named arguments. The generated stubs/phit.php lists every exact signature. Loading the extension makes all functions available globally.
Batch evaluation constructs the distribution once, then streams input values through the same core evaluation policy. Output is a packed list in input iteration order; keys are not retained. Empty input returns [], but parameters are still validated. An invalid element rejects the entire call. No missing rows are dropped. The benchmarks quantify when batching saves PHP boundary overhead and when numerical evaluation dominates.
Tails and likelihoods
Use survival functions for upper tails rather than subtracting a rounded CDF from one. Use log functions directly rather than taking the log of a probability that may already have underflowed.
Phit\dist_normal_sf(10); // About 7.62e-24; 1 - Phit\dist_normal_cdf(10) is zero.
Phit\dist_normal_logsf(40); // About -804.61, even though the ordinary SF is zero.
$logLikelihood = array_sum(Phit\dist_poisson_logpmf_array([2, 5, 3, 0], lambda: 2.5));A density is not a probability at a point and may exceed one. Sum log densities or log masses for independent observations; likelihood underflow is avoided this way. Log probabilities at impossible events are -INF. PHP JSON encoding with JSON_THROW_ON_ERROR rejects nonfinite results; callers must choose their own serialization policy rather than silently replacing numerical values.
The runnable examples/distributions.php demonstrates a two-sided t test, a mean confidence interval, a Poisson likelihood, a central probability, extreme upper tails and equivalent NB parameterizations. The sample data are hypothetical and the computations illustrate the API.
Boundaries and errors
Evaluation points may be ±INF, but NAN raises 1003. Null, numeric strings, booleans and nested array elements are not numeric inputs; malformed batch elements raise 1001. Scalar argument-type failures follow Zend’s runtime conventions. There is no distribution missing option. Nonfinite parameters raise 1003; invalid domains and quantile probabilities outside [0,1] raise 1001. Binomial size above 2^53 raises 1007. A NAN numerical result raises 1006; it is not returned as a value. Parameters so extreme that the incomplete beta or gamma cannot be evaluated also raise 1006 promptly: a beta-type sum \(a + b\) beyond the double range, a beta-type parameter above \(10^{300}\) evaluated within \(10^{-300}\) of an end of the support, or a gamma-type shape or point above \(10^{300}\) (for example dist_f_cdf(2, 3, PHP_FLOAT_MAX) or dist_gamma_cdf(1e30, 1e30)). Earlier builds could hang or panic on such input.
Outside support, density/mass is zero and log density/mass is -INF. Boundary densities can be infinite, for example a beta shape below one at a support endpoint. Discrete PMFs at non-integer counts are zero, while CDF/SF use the floor of the evaluation point. SF always means strictly greater than that count.
Continuous quantile endpoints are the support bounds, including infinities. Discrete quantiles return the smallest support value whose CDF reaches the requested probability, using a documented 64 * EPSILON relative comparison allowance on the smaller tail to accommodate rounding at CDF steps. Endpoint p=0 follows the conventional lower support bound; p=1 follows the upper support bound for ordinary distributions. A point mass returns its actual mass location at p=1. This differs from R/SciPy in some degenerate cases. Returned count quantiles are PHP floats; precision is limited by binary64’s exact integer range.
Numerical implementation and dependency audit
The raw statrs audit evaluates the saved R cases with statrs 0.19, using log(CDF)/log(SF) because that crate has no log-tail API. In these cases it loses small tails, has roughly 4.8e-4 relative binomial CDF error at size one million, and suffers inaccurate extreme quantiles. Those findings motivated a separate distribution module while retaining existing estimator numerical paths.
| Families | Probability backend | Density and extreme-tail work |
|---|---|---|
| Normal, lognormal | cdflib Cody normal tails | Split normal density; Mills-ratio log tails; safeguarded quantiles |
| Student t, F, beta | cdflib TOMS 708 incomplete beta | Stable log beta/gamma terms; log-scale incomplete-beta fraction |
| Gamma, chi-square | cdflib TOMS 654 incomplete gamma | Stable densities; log-scale gamma series/fraction |
| Binomial, negative binomial | cdflib incomplete beta | Loader-style saddle-point mass calculations; direct log tails |
| Poisson | cdflib incomplete gamma | Loader Poisson mass; log-scale gamma tails |
| Exponential, logistic | Closed-form Rust calculations | expm1, log1p and stable softplus formulas |
The runtime pins MIT-licensed cdflib = 0.4.3; GPL nmath ports were excluded by the dependency audit. statrs remains the estimator dependency and a source of special functions/seeds where appropriate. The implementation forms both tails independently and uses custom log-scale expansions below 1e-280. Continuous quantiles use log-tail Newton steps protected by brackets. No R/Python/BLAS runtime dependency is introduced. Numerical failure is explicit; this is not proof of accuracy for every finite argument or arbitrarily extreme shape parameter.
Reference evidence and release scope
The executed comparison records R, SciPy and 60-digit mpmath references, documented boundary differences and quantity-specific tolerances. Scalar/batch identities and validation run in the offline release gate. Performance evidence covers 1,000, 100,000 and one million values, including peak process memory and regression preservation.
Random sampling uses explicitly seeded dist_{family}_rng(n, seed, ...parameters) calls with local ChaCha20 state. The sampling contract documents reproducibility, validation and independent reference vectors. The readiness assessment records this implementation, the estimator reuse experiment and remaining publication/platform gates.
From phpstats/phit@76b22f0.