Skip to content

Conversation

@tedgin
Copy link
Contributor

@tedgin tedgin commented Dec 6, 2025

This PR addresses #10889. It makes the following changes to std.mathspecial.betaIncomplete and std.mathspecial.betaIncompleteCompl.

  1. Bring NaN handling inline with how D operators like operator!"+" handle them. I.E., when multiple NaN arguments are provided, the one with the largest payload is returned.
  2. Add support for the degenerate cases defined in Add support for very small and very large shape parameter values to betaIncomplete #10889.
  3. Performed a sparse coverage test of the (a, b, x) parameter space where a and b were varied logarithmicly from 10^-38 to 10^38, and x was varied from 0 to 1, concentrating on values near 0 or near 1. This revealed several places in parameter space where betaIncomplete returned NaN or a value outside of its range [0, 1]. Its algorithm is modified to handle these places.
    1. A special case is added to handle the symmetry a=b and x=0.5.
    2. Instances of manual computation of B(a,b), e.g., gamma(a)*gamma(b) / gamma(a+b), are replaced with calls to beta(a, b) to all betaIncomplete to benefit from beta`s handling of special cases.
    3. Instances of manual computation of ln|B(a,b)|, e.g., logGamma(a) + logGamma(b) - logGamma(a+b), were replaced with a newly created function logBeta that improves the precision of the computation by reducing the impact of subtraction when a and b have an order of magnitude size difference and b is large.
    4. betaDistPowerSeries is modified to handle the case where naive subtraction results in an extreme loss of precision.
    5. Rounding issues can result in betaDistPowerSeries returning 1+real.epsilon instead of 1. Values that are slightly larger than 1 are clamped to 1. If a value that is more than slightly larger than 1 would be returned, this indicates betaDistPowerSeries failed, so NaN is returned.

tedgin added 10 commits December 6, 2025 06:49
Bring std.mathspecial.betaIncomplete's handling of NaN parameter values
in line with how D's operators like operator!"+" handle them. I.e., the
NaN with the largest payload is returned.
Support was added to betaIncomplete and betaIncompleteCompl
for the cases when a or b is +0 or infinity.
When x > 1/b and x is larger than the mean, the complement is computed
instead. x -> 1-x. If prior to reversal, x < real.epsilon, 1-x = 1, so
x = 1 after reversal. Since algorthm requires x < 1, the computation of
complement fails. To resolve this failure, when the reversal causes
x -> 1, use x -> nextDown(1-x) instead.

This fix resolved a problematic case for betaIncompleteInv that is
tracked by a unittest. The unittest was updated.
Combine the Stirling approximations of the individual log gamma terms
when one of them is large and the difference between the arguments is
significant. This reduces the impact of subtracting the two larger
terms.
In betaDistPowerSeries, when s*a is close to 1, extreme loss of
precision can occur when combining terms in log space. This fix resolves
this issue.
The Beta CDF has a hard upper limit of 1. Due to round-off error, the
result of betaDistPowerSeries can be very slightly larger than 1 when
it should be 1. In this case, a value of 1 is returned. To prevent
clamping from hiding a more serious bug, if the result would be greater
than 1 + 2 epsilon, NaN is returned to indicated the computation failed.
@tedgin tedgin requested a review from ibuclaw as a code owner December 6, 2025 15:02
@dlang-bot
Copy link
Contributor

Thanks for your pull request and interest in making D better, @tedgin! We are looking forward to reviewing it, and you should be hearing from a maintainer soon.
Please verify that your PR follows this checklist:

  • My PR is fully covered with tests (you can see the coverage diff by visiting the details link of the codecov check)
  • My PR is as minimal as possible (smaller, focused PRs are easier to review than big ones)
  • I have provided a detailed rationale explaining my changes
  • New or modified functions have Ddoc comments (with Params: and Returns:)

Please see CONTRIBUTING.md for more information.


If you have addressed all reviews or aren't sure how to proceed, don't hesitate to ping us with a simple comment.

Bugzilla references

Your PR doesn't reference any Bugzilla issue.

If your PR contains non-trivial changes, please reference a Bugzilla issue or create a manual changelog.

Testing this PR locally

If you don't have a local development environment setup, you can use Digger to test this PR:

dub run digger -- build "master + phobos#10909"

@thewilsonator thewilsonator merged commit c47daab into dlang:master Dec 7, 2025
10 checks passed
@tedgin tedgin deleted the 10889 branch December 7, 2025 16:58
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.

3 participants