Add quantile accuracy sweep to differential-testing harness - #1401
Merged
Conversation
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YEuvn1C5GWjruZ3gj3cg6y
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a third sweep dimension to the differential-testing harness (
scripts/difftest-special.py/difftest-dist.py, ADR-0052): quantile accuracy. A newscripts/difftest-quantile.py+scripts/eval-quantile.jspair implements both metrics #1269 requires — a round-trip sweep (|cdf(q(p)) - p|) across every one of ranjs's ~146 distributions with log-uniform tail-focusedpsampling, and an absolute ULP accuracy sweep against an independent mpmath inverse-CDF reference for the #1265 pilot family (Gamma, Beta, Chi2, F, StudentT, InverseGamma) — plus closed-form-vs-numerical quantile source distinction and separate non-convergence/out-of-support/non-monotonicity hard-failure reporting.Closes #1269
Design decisions
No new ADR — this extends the harness pattern already governed by ADR-0052 (live mpmath, out-of-band from
npm test, standalone no-cross-script-imports), the same waydifftest-dist.pyrode on it without a fresh ADR. The architecture (new sibling script + bridge pair, catalog-mode population sourced fromtest/dist-cases-*.jsrather than a hand-maintained list) was settled via a design-propose/design-critique review during planning; seethoughts/plans/2026-08-11-1900-quantile-accuracy-sweep.mdin this branch's history for the full reasoning.Non-trivial changes
scripts/eval-quantile.js(new): Node/@babel-registerbridge with two modes —catalogenumerates every distribution's canonical valid parameter tuple, type, closed-form-vs-numerical quantile status (typeof instance._q === 'function'), and support bounds straight fromtest/dist-cases-continuous.js/-discrete.js;evalcomputesq(p)/cdf(q(p))at supplied points. Code Health 10.0.scripts/difftest-quantile.py(new): round-trip sweep (generate_roundtrip_ps,sweep_roundtrip,_hard_failures) and pilot-family absolute-ULP sweep (mpmath_quantile,sweep_pilot_absolute). Two genuinely new pieces of numerical logic worth a reviewer's attention:P_TAIL_LO = 1e-6, not1e-12): probing at1e-12hangs the harness indefinitely on several discrete distributions (e.g.BetaNegativeBinomial) whose_cdfis an O(k) recurrence sum that saturates in double precision before reaching that close to 1 — confirmed empirically and documented insolutions/tooling/2026-08-11-2026-quantile-sweep-tail-depth-hang-beta-negative-binomial.md.mpmath_quantile's log-space/logit-space bracket search: a first linear/additive bracket-and-bisect attempt silently returned wrong (even negative) reference values for extreme shape parameters, because the true root can sit hundreds of orders of magnitude from the seed and a fixed-precision linear bisection loses the far endpoint entirely. Fixed by bisecting in log-space (domains bounded at 0) / logit-space ((0,1) domains) instead. Documented insolutions/tooling/2026-08-11-2026-mpmath-quantile-reference-linear-bracket-magnitude-collapse.md. A self-check (_formula_self_check_quantile) forces genuine bracket expansion through all three reparameterization branches before any sweep result is trusted.LogCauchy's closed-form_qunderflows/overflows at extreme tails,StudentT's closed-form_qis non-monotonic and wrong-signed for smallnunearp=1,Beta's numerically-inverted_qunderflows to its boundary for extreme shape parameters, andGamma/InverseGamma's closed-form_qreturnsNaNfor extreme shape parameters. Each filed as its own follow-up issue: Fix Beta quantile underflow to 0 for extreme shape parameters #1394 (Beta), Fix StudentT quantile sign flip and non-monotonicity for small nu #1395 (StudentT), Fix LogCauchy quantile overflow/underflow in exp() step #1396 (LogCauchy), Fix Gamma/InverseGamma quantile NaN for extreme alpha #1397 (Gamma/InverseGamma).Comprehension checklist
Checklist
npm run standardpasses (no linter errors)npm testpasses (all tests green — 10176 passing; harness is out-of-band per ADR-0052, coverage thresholds unaffected)npm run typecheckpasses_self_check()for the ULP metric,_formula_self_check_quantile()for the mpmath reference formulas and the new bracket-search algorithm, both run at the start ofmain())test/dist-cases.js— N/A, no new distributiondist/ranjs.d.ts— N/A, no new distributionCHANGELOG.mdupdated under## [Unreleased]Trivial changes
package.json: two new npm scripts,difftest:quantileandaccuracy:quantile, mirroring the existingdifftest:dist/accuracy:distpair. Deliberately not wired into theaccuracyaggregate chain,accuracy:docs, ordifftest:ci-gate— those are Generate documented accuracy bounds table from differential-testing harness reports #1266/Add scheduled CI workflow running the differential-testing harness #1267 scope.CHANGELOG.md: one### Addedbullet under[Unreleased].solutions/tooling/*.md(2 new files): documentation of the two numerical bugs described above, for future-session searchability.Generated with Claude Code
Generated by Claude Code