Skip to content

Fix #11133: preserve incomplete-beta accuracy near one - #11141

Merged
thewilsonator merged 1 commit into
dlang:masterfrom
jmh530:codex/fix-beta-small-shape-tail
Oct 22, 2026
Merged

thewilsonator merged 1 commit into
dlang:masterfrom
jmh530:codex/fix-beta-small-shape-tail

Conversation

@jmh530

@jmh530 jmh530 commented Oct 21, 2026

Copy link
Copy Markdown
Contributor

Rationale

betaIncomplete can lose substantial relative accuracy near x = 1 when the second shape is tiny. For a = 1, b = 1e-20, and the largest double below one, the expected result is approximately 3.673680056967710e-19, but the existing implementation returns approximately 1.314235314789e-19: about 64% relative error, although the absolute error is small.

Reuse the stable complementary series and coordinate handling already used by betaIncompleteComplSmallX. Both entry points now use a shared implementation with a runtime nearOne parameter. The ordinary path remains in use for x <= 0.95.

The regression tests cover the exact shape-one identity through the last representable real below one, together with independent high-precision references for fractional and larger first shapes.

Feature request or issue tracking

Closes #11133.

Performance

Compared three implementations: upstream master, an initial fix retaining separate template instantiations, and the final shared implementation. Measurements used Windows DMD 2.113.0 (-O -inline -release) and LDC 1.43.0 (-O3 -enable-inlining -release), without fast-math.

Each dataset contains 128 varied inputs. The benchmark runs all three implementations in the same process through equivalent function pointers, rotates their measurement order, and pins execution to one logical CPU. Results below are median nanoseconds per call across three process runs, with nine retained batches per run after warmup.

Compiler Dataset Original Initial fix Shared implementation
LDC Reported tiny-shape tail 2506.8 16.7 16.8
LDC Fractional first shape, tiny tail 2509.8 192.1 191.6
LDC Large first shape, tiny tail 2599.8 112.3 112.8
LDC Ordinary near-one inputs 33.4 34.5 33.2
LDC Inputs around the dispatch boundary 1058.8 1057.0 1064.0
LDC Ordinary power series 37.3 37.9 37.0
LDC Ordinary continued fraction 289.9 280.3 268.8
LDC Complementary CDF, tiny input 57.6 57.9 57.7
LDC Complementary CDF, ordinary input 35.4 35.4 35.4
LDC Inverse CDF, central probabilities 580.7 582.3 589.8
LDC Inverse CDF, upper probabilities 538.9 544.3 542.5
DMD Reported tiny-shape tail 26882.3 142.8 144.2
DMD Fractional first shape, tiny tail 26821.6 1372.3 1389.8
DMD Large first shape, tiny tail 26688.1 1027.1 1029.5
DMD Ordinary near-one inputs 421.9 413.2 426.6
DMD Inputs around the dispatch boundary 8241.0 7879.1 7599.0
DMD Ordinary power series 447.9 431.0 433.3
DMD Ordinary continued fraction 2047.7 2003.4 1980.3
DMD Complementary CDF, tiny input 492.0 501.2 498.0
DMD Complementary CDF, ordinary input 442.6 452.1 444.6
DMD Inverse CDF, central probabilities 3747.1 3797.1 3787.8
DMD Inverse CDF, upper probabilities 3580.3 3534.8 3505.2

Both fixes avoid the expensive, inaccurate continued-fraction calculation in the affected cases. The shared implementation performs similarly to the initial fix: median paired timing changes across datasets range from −2.7% to +0.6% with LDC and −0.6% to +2.2% with DMD. These are local microbenchmarks, and small differences vary between runs.

Sharing the implementation also reduces generated code size. Summed code-section sizes for the optimized module object, excluding data and metadata, are:

Compiler Original Initial fix Shared implementation
LDC 38,967 bytes 40,262 bytes 38,348 bytes
DMD 50,573 bytes 51,234 bytes 48,888 bytes

Validation

  • Full std.internal.math.gammafunction module tests pass with DMD.
  • Focused regression tests pass with LDC.
  • A separate 294-case sweep per compiler passes against 100-digit mpmath references, covering both sides of the dispatch boundary, tiny second shapes, and fractional through large first shapes. The comparison allows relative error of 1e-11 or one result ULP for rounded subnormal results.
  • The original implementation fails 24 DMD cases and 28 LDC cases in that sweep; the updated implementation passes all cases.
  • Benchmark result checksums agree between the initial fix and shared implementation.

The full Phobos suite was not run. Full-module LDC testing has a previously reproduced baseline assertion failure in igammaTemmeLarge; LDC validation here used focused tests. A platform with 113-bit real was not available.

Pre-review checklist

  • I have performed a self-review of my code.
  • If my PR fixes a bug or introduces a new feature, I have added thorough tests.
  • If my changes are non-trivial and do not concern a reported issue, I have added a changelog entry.

The changelog condition does not apply because this fixes a reported issue.

LLM/AI disclosure

This PR was written with the assistance of an LLM/AI.

AI-Assisted-By: Codex (GPT-6 Astra Medium)

betaIncomplete can lose substantial relative accuracy near x=1 when
the second shape is tiny. For a=1, b=1e-20, and the largest double below
one, the result has approximately 64% relative error.

Reuse the stable complementary series and coordinate handling already
used by betaIncompleteComplSmallX. Route both entry points through a
shared implementation with a runtime nearOne parameter, avoiding
separate template instantiations while retaining the ordinary path
for x <= 0.95.

Cover the exact shape-one identity through the last representable real
below one, plus independent high-precision references for fractional
and larger first shapes.

AI-Assisted-By: Codex (GPT-6 Astra Medium)
@thewilsonator
thewilsonator merged commit 36a897f into dlang:master Oct 22, 2026
9 checks passed
@0xEAB 0xEAB added math Severity:Bug Fix Review:AI Generated Code that is generated by an LLM AI — or suspected to be. labels Oct 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

math Review:AI Generated Code that is generated by an LLM AI — or suspected to be. Severity:Bug Fix

Projects

None yet

Development

Successfully merging this pull request may close these issues.

betaIncomplete loses accuracy near x=1 with a tiny second shape

3 participants