Skip to content

Keep ibeta monotonic under -ffp-contract=fast and fix develop's CI - #1561

Merged
NAThompson merged 1 commit into
developfrom
ibeta-contract-fast
Oct 11, 2026
Merged

NAThompson merged 1 commit into
developfrom
ibeta-contract-fast

Conversation

@NAThompson

@NAThompson NAThompson commented Oct 11, 2026 •

Copy link
Copy Markdown
Collaborator

No-Lanczos ibeta/igamma use log1pmx of an exact x c - a near the mean, not pow; libeta shares ibeta's bases; Hermite prime and polygamma avoid cancellation and exp(log).
Gauss-Hermite weights sum to sqrt(pi); discrete_legendre fuses one way; fixed autodiff seed; nc_t, ulps_plot, quad and MinGW test fixes; stray binaries; CI cancels stale runs.

Fixed on develop's CI:

  • ibeta non-monotonic for real_concept at a, b ~ 1e16 under fast contraction (test_ibeta.hpp:536)
  • test_gauss_hermite_quadrature test_large_N, 19 ulps > 16 (Clang-18 ASAN/USAN quadrature): the weights share a few-eps error from the rounded recurrence coefficients; rescaled to their exact sum
  • test_lanczos_smoothing test_dlp_next, exact equality (Clang-18 ASAN misc): one product per sum is rounded with fma(a, b, 0), so contraction has one choice; x87 long double rounds as before
  • test_septic_hermite test_quadratic:265, prime 316 ulps > 300 (MSVC2022 clang-win): the derivative basis polynomials were expanded and lost up to ~60 eps near their zeros, which z0 m + z1 v0 + z2 v1 then amplified. They are now factored at their zeros (e.g. z1 = (1 - t)^3 (1 + 3t + 6t^2 - 70t^3)), and the sum is anchored at the nearer endpoint's derivative (z0 + z1 + z2 = 1). Worst on the test's grid 145 -> 4 ulps; quintic, same form, 66 -> 10 over 200 grids; float on the integer grid 2 ulps (limit 32)
  • test_polygamma large arguments, 622.8 eps > 400 (MSVC2022 clang-win): polygamma underflow fix from Stop promoting double and round discrete quantiles up by default #1554's triage. (n-1)!/x^(n+1) is formed from the mantissas and exponents of (n-1)! and x and applied with ldexp, instead of exp of logs; the group's worst is now 3.1 eps, with 7 Arb rows added
  • test_nc_t find_non_centrality, 1.76e-5 > 1.49e-5 (MSVC2022 clang-win): with delta ~ 5e-11 the probability hardly depends on delta, so eps in p is ~5e-6 in delta. The tolerance is now also at least 16 eps p / (delta pdf(t)); measured up to ~8 of those
  • test_ulps_plot test_files:383-384 (clang++-7 misc)
  • test_ibeta_inv:479, real_concept on 113-bit long double, 109 eps (g++ ARM64 special_fun)
  • test_reverse_mode_autodiff_stl_support, flaky: seeded from std::random_device, now a fixed seed (g++-14 c++23)
  • test_univariate_statistics_backwards_compatible test_integer_kurtosis, flaky: global_seed 0 meant std::random_device, now 42 like its siblings (clang++-18 noble)
  • test_beta and test_ibeta_real_concept2 on windows_gcc: real_concept is MinGW's 80-bit long double, whose libm is less accurate; since Improve ibeta accuracy for small parameters and near the mean #1556 its beta and ibeta reach 368 and 704 eps. The MinGW real_concept bounds now come from those measurements (tolerance only; not reproducible here)

CI: the concurrency group is now the workflow plus the branch (github.head_ref || github.ref), and codecov gets the same group, so a new push to develop or a PR cancels that branch's older runs; it used github.run_id on pushes, so no develop run was ever cancelled.

Co-Authored-By: Claude Opus 5.5 noreply@anthropic.com

polygamma (double, no promotion, against Arb; orange develop, blue this PR)

polygamma n=30 develop
polygamma n=30 fixed
polygamma n=50
polygamma n=120

ibeta / libeta / igamma, real_concept (develop red, this PR blue)

ibeta(1e16, 9.97e15, x) near the mean: worst 1.9e16 ulps (3.4e8 x envelope) -> 4.4e7 ulps (0.77 x envelope).

ibeta near mean
a in [1e12, 1e17], b = 0.99658a, -3..3 sd: worst 6.0e14 -> 3.9e8 ulps (the remainder is pre-existing, ~1 ulp of x at this density).

ibeta heatmap
libeta underflow tail: 2.3e6 ulps (6.2 x envelope) -> 385 ulps (6.5e-4 x).

libeta tail
gamma_p / gamma_q, a in [1e5, 1e9], z = a + 1.5 sqrt(a): 6.2e7 -> 557 and 4.9e8 -> 4458 ulps.

gamma_p
gamma_q

Hermite derivatives on the test's random grid

septic prime: 490 -> 5 ulps; quintic prime: 46 -> 4 ulps.

septic
septic, this PR only
quintic
quintic, this PR only

Gauss-Hermite weight relative error vs 50 digits

N=200: max 72 -> 67 eps, mean -7.6 -> -2.7; N=500: max 111 -> 105, mean -9.1 -> -3.2.

N=200
N=500

🤖 Generated with Claude Code

@NAThompson
NAThompson force-pushed the ibeta-contract-fast branch 6 times, most recently from 077f0e1 to 65895e5 Compare October 11, 2026 22:18
NAThompson added a commit to NAThompson/math that referenced this pull request Oct 11, 2026
No-Lanczos ibeta/igamma use log1pmx of an exact x c - a near the mean, not pow; libeta shares ibeta's bases; Hermite prime and polygamma avoid cancellation and exp(log).
Gauss-Hermite weights sum to sqrt(pi); discrete_legendre fuses one way; fixed autodiff seed; nc_t, ulps_plot, quad and MinGW test fixes; stray binaries; CI cancels stale runs.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
NAThompson added a commit to NAThompson/math that referenced this pull request Oct 11, 2026
@NAThompson
NAThompson merged commit 29b1163 into develop Oct 11, 2026
45 of 50 checks passed
@NAThompson
NAThompson deleted the ibeta-contract-fast branch October 11, 2026 23:15
NAThompson added a commit that referenced this pull request Oct 11, 2026
#1562)

The gamma_p/gamma_q(1e5, 100300) check from #1561 tests the no-Lanczos prefix; double takes the Lanczos path, which the SYCL job's icpx evaluates 85 eps out.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant