Skip to content

Commit 242a993

Browse files
committed
10802: digamma maps +/-0 to -/+inf
This adapts std.mathspecial.digamma so that it IEEE 754 way of handling +/-0.0, i.e., it treats them as values that are infinitesimally greater/less than zero. digamma(+0) = -inf and digamma(-0) = +inf. The DDOC and unittests were also updated.
1 parent 3e50ddb commit 242a993

File tree

2 files changed

+45
-5
lines changed

2 files changed

+45
-5
lines changed

std/internal/math/gammafunction.d

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1643,7 +1643,12 @@ real digamma(real x)
16431643
negative = 0;
16441644
nz = 0.0;
16451645

1646-
if ( x <= 0.0 )
1646+
if ( x == 0.0 )
1647+
{
1648+
return signbit(x) == 1 ? real.infinity : -real.infinity;
1649+
}
1650+
1651+
if ( x < 0.0 )
16471652
{
16481653
negative = 1;
16491654
q = x;
@@ -1718,6 +1723,10 @@ done:
17181723
assert(digamma(1.0)== -EULERGAMMA);
17191724
assert(feqrel(digamma(0.25), -PI/2 - 3* LN2 - EULERGAMMA) >= real.mant_dig-7);
17201725
assert(feqrel(digamma(1.0L/6), -PI/2 *sqrt(3.0L) - 2* LN2 -1.5*log(3.0L) - EULERGAMMA) >= real.mant_dig-7);
1726+
assert(digamma(-0.0) == real.infinity);
1727+
assert(!digamma(nextDown(-0.0)).isNaN());
1728+
assert(digamma(+0.0) == -real.infinity);
1729+
assert(!digamma(nextUp(+0.0)).isNaN());
17211730
assert(digamma(-5.0).isNaN());
17221731
assert(feqrel(digamma(2.5), -EULERGAMMA - 2*LN2 + 2.0 + 2.0L/3) >= real.mant_dig-9);
17231732
assert(isIdentical(digamma(NaN(0xABC)), NaN(0xABC)));

std/mathspecial.d

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
* NAN = $(RED NAN)
3030
* SUP = <span style="vertical-align:super;font-size:smaller">$0</span>
3131
* GAMMA = &#915;
32+
* PSI = &Psi;
3233
* THETA = &theta;
3334
* INTEGRAL = &#8747;
3435
* INTEGRATE = $(BIG &#8747;<sub>$(SMALL $1)</sub><sup>$2</sup>)
@@ -37,8 +38,10 @@
3738
* BIGSUM = $(BIG &Sigma; <sup>$2</sup><sub>$(SMALL $1)</sub>)
3839
* CHOOSE = $(BIG &#40;) <sup>$(SMALL $1)</sup><sub>$(SMALL $2)</sub> $(BIG &#41;)
3940
* PLUSMN = &plusmn;
41+
* MNPLUS = &mnplus;
4042
* INFIN = &infin;
4143
* PLUSMNINF = &plusmn;&infin;
44+
* MNPLUSINF = &mnplus;&infin;
4245
* PI = &pi;
4346
* LT = &lt;
4447
* GT = &gt;
@@ -166,19 +169,47 @@ real beta(real x, real y)
166169
assert(isIdentical(beta(2, NaN(0xABC)), NaN(0xABC)));
167170
}
168171

169-
/** Digamma function
172+
/** Digamma function, $(PSI)(x)
170173
*
171-
* The digamma function is the logarithmic derivative of the gamma function.
174+
* $(PSI)(x), is the logarithmic derivative of the gamma function, $(GAMMA)(x).
172175
*
173-
* digamma(x) = d/dx logGamma(x)
176+
* $(PSI)(x) = $(SUP d)$(SUB /, dx) ln|$(GAMMA)(x)| (the derivative of `logGamma(x)`)
174177
*
175-
* See_Also: $(LREF logmdigamma), $(LREF logmdigammaInverse).
178+
* Params:
179+
* x = the domain value
180+
*
181+
* Returns:
182+
* It returns $(PSI)(x).
183+
*
184+
* $(TABLE_SV
185+
* $(SVH x, digamma(x) )
186+
* $(SV integer < 0, $(NAN) )
187+
* $(SV $(PLUSMN)0.0, $(MNPLUSINF) )
188+
* $(SV +$(INFIN), +$(INFIN) )
189+
* $(SV -$(INFIN), $(NAN) )
190+
* $(SV $(NAN), $(NAN) )
191+
* )
192+
*
193+
* See_Also: $(LREF logmdigamma), $(LREF logmdigammaInverse).
176194
*/
177195
real digamma(real x)
178196
{
179197
return std.internal.math.gammafunction.digamma(x);
180198
}
181199

200+
///
201+
@safe unittest
202+
{
203+
const euler = 0.57721_56649_01532_86061L;
204+
205+
assert(digamma(1) == -euler);
206+
assert(digamma(+0.) == -real.infinity);
207+
assert(digamma(-0.) == +real.infinity);
208+
assert(digamma(+real.infinity) == +real.infinity);
209+
assert(isNaN(digamma(-1)));
210+
assert(isNaN(digamma(-real.infinity)));
211+
}
212+
182213
/** Log Minus Digamma function
183214
*
184215
* logmdigamma(x) = log(x) - digamma(x)

0 commit comments

Comments
 (0)