Benchmarks and verification
Distribution and utility verification
The probability API has independent base-R, SciPy and 60-digit mpmath reference evidence. This page reads no runtime models; its tables are generated from the saved comparison report by python3 scripts/distribution-docs.py. The report records the native refresh date, versions, per-point errors and unavailable reference points. Tests use immutable expected values and never select a reference by looking at the native result.
Executed reference comparison
Native refresh: 2026-10-12T15:18:49.923101+00:00. PHP 8.5.10; R version 4.6.1 (2026-06-24); SciPy 1.18.1; mpmath 1.4.1 at 60 digits.
553 cases, 8,661 points, 27 unavailable independent reference points.
| Family | Worst native error | Worst R error | Worst SciPy error |
|---|---|---|---|
| beta | 1.49e-13 | 1.49e-13 | 1.6e+100 |
| binomial | 3.28e-14 | 0.0588 | 4.94e-05 |
| chisquare | 8.34e-13 | 1.5e-11 | 8.16e-09 |
| exponential | 5.64e-14 | 5.64e-14 | 5.64e-14 |
| f | 1.58e-13 | 1 | 2.17e-09 |
| gamma | 7.5e-13 | 4.24e-14 | 1.47e-11 |
| logistic | 1.45e-15 | 1.45e-15 | 1.45e-15 |
| lognormal | 9.13e-14 | 1 | 2.25e-14 |
| nbinom | 6.84e-14 | 0.0656 | 0.0556 |
| nbinom_mu | 5.1e-14 | 0.0652 | 0.00798 |
| normal | 2.86e-14 | 4.21e-09 | 4.3e-10 |
| poisson | 3.71e-13 | 0.0714 | 0.02 |
| t | 1.8e-13 | 0.392 | 1 |
The table uses finite, nonzero mpmath reference values and excludes quantile endpoints. Logs use error divided by max(1, |reference|), ordinary densities and probabilities use relative error (a normal-range floor for subnormal references), and quantiles use relative error with a 1e-300 floor. Zero/support/degenerate endpoints are checked separately below, rather than exaggerated by dividing a small absolute difference by an artificial tiny scale.
Typical native errors are below 1e-13. The worst saved native case is about 8.34e-13, in a large-df chi-square log tail; cdflib’s large-shape regime sets the tested accuracy there. R is somewhat better on that case. These are observed errors on specified inputs, not a guarantee for every shape/scale or tail.
Reference generation and limitations
tests/generate-distribution-fixtures.R produces 553 distribution cases: R d/p/q functions at saved explicit parameter sets and evaluation points, including tiny probabilities, large counts/shapes, support boundaries and point masses. The same generator writes eight univariate, three paired and two weighted descriptive cases using seed 20261012. Numeric JSON inputs are parsed with serde_json float-roundtrip support so that Rust and PHP use the intended binary64 values.
docs/verifications/compare_distributions.py evaluates closed-form densities and regularized incomplete-beta/gamma tails using mpmath at 60 digits. Continuous reference quantiles use independently evaluated log-tail Newton iterations, starting from native/R/SciPy candidates but accepting only a high-precision tail residual. Discrete references verify the CDF-step inequality. Values are rounded once to binary64. A computation timeout or unavailable reference is recorded as null, never replaced by the native value. The 27 unavailable points remain visible in the report; their ordinary tests use the saved R reference and explicit identities. Subnormal values have fewer significant bits, so relative-error claims are limited.
The provenance manifest indexes all R/SciPy/mpmath and descriptive inputs, quantities, versions, generators, tolerance policies and hashes. The independent reference fixture SHA-256 values are also recorded in the native refresh report. --stored-references re-evaluates PHP without changing those values.
# Intentional independent reference regeneration (may take substantial time):
Rscript tests/generate-distribution-fixtures.R
PHP=/path/to/matching/php .context/v02/python/bin/python docs/verifications/compare_distributions.py
# Routine native refresh against existing references:
PHP=/path/to/matching/php .context/v02/python/bin/python docs/verifications/compare_distributions.py --stored-references
python3 scripts/reference-manifest.py
python3 scripts/distribution-docs.pyThe optional Python environment needs NumPy, SciPy and mpmath; pins are in tests/benchmarks/distribution-requirements.txt. None are extension runtime or offline-test dependencies.
Release-gate tolerances and checks
| Quantity | Absolute/relative test tolerance |
|---|---|
| Density, mass, CDF and SF | 1e-300 + 1e-12 * abs(reference) |
| Log density/mass/tails | 1e-12 * max(1, abs(reference)) |
| Distribution quantiles | 1e-15 + 1e-12 * abs(reference) |
| Descriptive R quantities | Relative 1e-12, exact zero |
tests/distributions.php performs 8,618 comparisons under these original tolerances. When saved R and mpmath differ beyond tolerance, it uses the immutable mpmath value (25 independently adjudicated points). Forty-three documented boundary differences have separate conventions/identity checks. Scalar/batch values must be identical, including NAN/INF conventions where applicable. The suite also checks CDF/SF sums, quantile inverses and monotonicity, direct log functions, degenerate cases, argument names/defaults, array order and invalid input/error categories. An overflowing size-plus-mean NB conversion is checked to avoid a false point mass.
Rust independently checks extreme Student-t quantiles against mpmath, probability identities, validation and scaled-density underflow. The diagnostic R-comparison test reports raw worst errors including intended differences; it is not the sole correctness gate. PHP’s strict reference/identity suite is required as well.
tests/descriptive.php adds 145 R comparisons and missing/error checks. crates/stats-core/tests/descriptive.rs covers the same stored examples plus overflow and degenerate cases. The release gate includes both PHP suites, the Rust tests and the runnable distribution example. Descriptive conventions explain sample/population and frequency/reliability definitions.
Documented reference differences
- Discrete quantile p=1 for a point mass returns its mass location. R/SciPy may instead return the generic upper-support bound, including infinity.
- R’s F density at +INF is NAN; the native API returns zero there.
- R F quantiles can round to zero for tiny probabilities and small numerator df, where the native/mpmath value is a representable positive value.
- R’s Student-t quantile at df=0.5 has a small nonzero center and selected far-tail inaccuracies. Native centering and high-precision tail checks establish the chosen values.
- R’s discrete-quantile probability adjustment near
1 - 2^-52can shift the returned count. Native uses a relative64*EPSILONallowance on the smaller tail. - R’s mean-form negative-binomial mass approximation for size much larger than the observed count differs from the independent high-precision calculation.
- SciPy’s large-df chi-square CDF has about
8.16e-9relative error at the saved five-standard-deviation lower-tail point. The native and R results match mpmath much more closely. The benchmark records the same peer discrepancy without weakening native comparison tolerances.
Raw values and per-point errors remain in the fixtures/report. Intentional conventions and peer-library errors are distinct from unsupported reference points.
Backend and model-path audit
The raw statrs report and executable crates/stats-core/examples/statrs_audit.rs document why statrs alone is not used for the new distribution API. The reuse experiment compares the public Normal log-CDF and Student-t quantile with the existing probit and OLS formulas. Candidate t quantiles improve large-df reference error, but all six tested critical values and 17 tested normal log-CDF values differ in rounding. The current release retains the established regression paths and their behavior. This is an evaluated compatibility decision, not an untested refactor.
cargo run -p stats-core --release --locked --example statrs_audit
cargo run -p stats-core --release --locked --example distribution_reuse_audit
PHP=/path/to/matching/php PHP_CONFIG=/path/to/php-config ./scripts/checkThe v0.2 assessment records completed scope, RNG deferral and the remaining external release/platform gates.
From phpstats/phit@76b22f0.