From a9f0d0f892f7f57e0b84457d2ff4cb78b2be7f7e Mon Sep 17 00:00:00 2001 From: Tony Edgin Date: Thu, 6 Nov 2025 10:40:48 -0700 Subject: [PATCH 1/4] 10892 Implement std.mathspecial.betaIncompleteCompl This implements std.mathspecial.betaIncompleteCompl and updates the documentation for std.mathspecial.betaIncomplete accordingly. --- std/mathspecial.d | 59 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 45 insertions(+), 14 deletions(-) diff --git a/std/mathspecial.d b/std/mathspecial.d index d40ac9aa018..411bb50959c 100644 --- a/std/mathspecial.d +++ b/std/mathspecial.d @@ -264,32 +264,63 @@ real logmdigammaInverse(real x) return std.internal.math.gammafunction.logmdigammaInverse(x); } -/** Incomplete beta integral +/** Regularized incomplete beta function $(SUB I, x)(a,b) * - * Returns regularized incomplete beta integral of the arguments, evaluated - * from zero to x. The regularized incomplete beta function is defined as + * Mathematically, if a and b are positive real numbers, and 0 $(LE) x $(LE) 1, then + * $(SUB I, x)(a,b) = $(INTEGRATE 0, x)$(POWER t, a-1)$(POWER (1-t), b-1)dt/B(a,b) where B is the + * beta function. It is also the cumulative distribution function of the beta distribution. * - * betaIncomplete(a, b, x) = $(GAMMA)(a + b) / ( $(GAMMA)(a) $(GAMMA)(b) ) * - * $(INTEGRATE 0, x) $(POWER t, a-1)$(POWER (1-t), b-1) dt + * `betaIncomplete(a, b, x)` evaluates $(SUB I, `x`)(`a`,`b`). * - * and is the same as the cumulative distribution function of the Beta - * distribution. + * Params: + * a = the first argument of B, must be positive + * b = the second argument of B, must be positive + * x = the fraction of integration completion from below, 0 $(LE) x $(LE) 1 * - * The domain of definition is 0 <= x <= 1. In this - * implementation a and b are restricted to positive values. - * The integral from x to 1 may be obtained by the symmetry - * relation + * Returns: + * It returns $(SUB I, x)(a,b), an element of [0,1]. * - * betaIncompleteCompl(a, b, x ) = betaIncomplete( b, a, 1-x ) + * Note: + * The integral is evaluated by a continued fraction expansion or, when `b * x` is small, by a + * power series. * - * The integral is evaluated by a continued fraction expansion - * or, when b * x is small, by a power series. + * See_Also: $(LREF beta) $(LREF betaIncompleteCompl) */ real betaIncomplete(real a, real b, real x ) { return std.internal.math.gammafunction.betaIncomplete(a, b, x); } +/** Regularized incomplete beta function complement $(SUB I$(SUP C), x)(a,b) + * + * Mathematically, if a $(GT) 0, b $(GT) 0, and 0 $(LE) x $(LE) 1, then + * $(SUB I$(SUP C), x)(a,b) = $(INTEGRATE x, 1)$(POWER t, a-1)$(POWER (1-t), b-1)dt/B(a,b) where B + * is the beta function. It is also the complement of the cumulative distribution function of the + * beta distribution. It can be shown that $(SUB I$(SUP C), x)(a,b) = $(SUB I, 1-x)(b,a). + * + * `betaIncompleteCompl(a, b, x)` evaluates $(SUB I$(SUP C), `x`)(`a`,`b`). + * + * Params: + * a = the first argument of B, must be positive + * b = the second argument of B, must be positive + * x = the fraction of integration completion from above, 0 $(LE) x $(LE) 1 + * + * Returns: + * It returns $(SUB I$(SUP C), x)(a,b), an element of [0,1]. + * + * See_Also: $(LREF beta) $(LREF betaIncomplete) + */ +real betaIncompleteCompl(in real a, in real b, in real x) +{ + return std.internal.math.gammafunction.betaIncomplete(b, a, 1-x); +} + +/// +@safe unittest +{ + assert(betaIncompleteCompl(.1, .2, 0) == betaIncomplete(.2, .1, 1)); +} + /** Inverse of incomplete beta integral * * Given y, the function finds x such that From 548a98d2b01a3812f51045c965dcfb0c0f53ecd4 Mon Sep 17 00:00:00 2001 From: Tony Edgin Date: Thu, 6 Nov 2025 14:37:05 -0700 Subject: [PATCH 2/4] 10892 improve betaIncompleteCompl implementation 1) Remove in from function parameters. 2) Add contract to enforce preconditions. --- std/mathspecial.d | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/std/mathspecial.d b/std/mathspecial.d index 411bb50959c..7a2459c033e 100644 --- a/std/mathspecial.d +++ b/std/mathspecial.d @@ -310,7 +310,19 @@ real betaIncomplete(real a, real b, real x ) * * See_Also: $(LREF beta) $(LREF betaIncomplete) */ -real betaIncompleteCompl(in real a, in real b, in real x) +real betaIncompleteCompl(real a, real b, real x) +in +{ + // allow NaN input to pass through so that it can be addressed by the + // internal NaN payload propagation logic + if (!isNaN(a) && !isNaN(b) && !isNaN(x)) + { + assert(signbit(a) == 0, "a must be positive"); + assert(signbit(b) == 0, "b must be positive"); + assert(x >= 0 && x <= 1, "x must be in [0, 1]"); + } +} +body { return std.internal.math.gammafunction.betaIncomplete(b, a, 1-x); } From 9f500ef6f78549fbb7b0ab77bd55fa72091ec83c Mon Sep 17 00:00:00 2001 From: Tony Edgin Date: Fri, 7 Nov 2025 06:18:21 -0700 Subject: [PATCH 3/4] 10892 switched deprecated body to do --- std/mathspecial.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/std/mathspecial.d b/std/mathspecial.d index 7a2459c033e..a26434f6efe 100644 --- a/std/mathspecial.d +++ b/std/mathspecial.d @@ -322,7 +322,7 @@ in assert(x >= 0 && x <= 1, "x must be in [0, 1]"); } } -body +do { return std.internal.math.gammafunction.betaIncomplete(b, a, 1-x); } From 7912cd503a581b44ffda7cd03acab6e5824d48a6 Mon Sep 17 00:00:00 2001 From: Tony Edgin Date: Sat, 8 Nov 2025 06:48:21 -0700 Subject: [PATCH 4/4] Rerunning github actions because of timeout