Skip to content

Commit 55ac462

Browse files
committed
Add lgammal_r().
We already provide lgammaf_r() and lgamma_r(). It's not hard to also add lgammal_r(), for consistency. I am currently working on porting openlibm to an environment where global state, and thus signgam, is not available. By adding lgammal_r(), I can trivially disable support for signgam by just patching up src/e_lgamma{f,,l}.c. That way there is no need to patch up the actual algorithms.
1 parent 24cec16 commit 55ac462

6 files changed

Lines changed: 37 additions & 23 deletions

File tree

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,27 +16,26 @@
1616
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1717
*/
1818

19-
/* lgammal
19+
/* lgammal_r
2020
*
2121
* Natural logarithm of gamma function
2222
*
2323
*
2424
*
2525
* SYNOPSIS:
2626
*
27-
* long double x, y, lgammal();
28-
* extern int signgam;
27+
* long double x, y, lgammal_r();
28+
* int signgam;
2929
*
30-
* y = lgammal(x);
30+
* y = lgammal_r(x, &signgam);
3131
*
3232
*
3333
*
3434
* DESCRIPTION:
3535
*
3636
* Returns the base e (2.718...) logarithm of the absolute
3737
* value of the gamma function of the argument.
38-
* The sign (+1 or -1) of the gamma function is returned in a
39-
* global (extern) variable named signgam.
38+
* The sign (+1 or -1) of the gamma function is returned through signgamp.
4039
*
4140
* The positive domain is partitioned into numerous segments for approximation.
4241
* For x > 10,
@@ -757,20 +756,20 @@ deval (long double x, const long double *p, int n)
757756

758757

759758
long double
760-
lgammal(long double x)
759+
lgammal_r(long double x, int *signgamp)
761760
{
762761
long double p, q, w, z, nx;
763762
int i, nn;
764763

765-
signgam = 1;
764+
*signgamp = 1;
766765

767766
if (! finite (x))
768767
return x * x;
769768

770769
if (x == 0.0L)
771770
{
772771
if (signbit (x))
773-
signgam = -1;
772+
*signgamp = -1;
774773
return one / fabsl (x);
775774
}
776775

@@ -782,9 +781,9 @@ lgammal(long double x)
782781
return (one / (p - p));
783782
i = p;
784783
if ((i & 1) == 0)
785-
signgam = -1;
784+
*signgamp = -1;
786785
else
787-
signgam = 1;
786+
*signgamp = 1;
788787
z = q - p;
789788
if (z > 0.5L)
790789
{
@@ -793,7 +792,7 @@ lgammal(long double x)
793792
}
794793
z = q * sinl (PIL * z);
795794
if (z == 0.0L)
796-
return (signgam * huge * huge);
795+
return (*signgamp * huge * huge);
797796
w = lgammal (q);
798797
z = logl (PIL / z) - w;
799798
return (z);
@@ -1025,7 +1024,7 @@ lgammal(long double x)
10251024
}
10261025

10271026
if (x > MAXLGM)
1028-
return (signgam * huge * huge);
1027+
return (*signgamp * huge * huge);
10291028

10301029
q = ls2pi - x;
10311030
q = (x - 0.5L) * logl (x) + q;

ld80/Make.files

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
$(CUR_SRCS) += invtrig.c \
22
e_acoshl.c e_powl.c k_tanl.c s_exp2l.c \
3-
e_atanhl.c e_lgammal.c e_sinhl.c s_asinhl.c s_expm1l.c \
3+
e_atanhl.c e_lgammal_r.c e_sinhl.c s_asinhl.c s_expm1l.c \
44
e_coshl.c e_log10l.c e_tgammal.c \
55
e_expl.c e_log2l.c k_cosl.c s_log1pl.c s_tanhl.c \
66
e_logl.c k_sinl.c s_erfl.c

ld80/e_lgammal.c renamed to ld80/e_lgammal_r.c

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
2626
*/
2727

28-
/* lgammal(x)
28+
/* lgammal_r(x, signgamp)
2929
* Reentrant version of the logarithm of the Gamma function
3030
* with user provide pointer for the sign of Gamma(x).
3131
*
@@ -89,7 +89,6 @@
8989
#include <openlibm.h>
9090

9191
#include "math_private.h"
92-
extern int signgam;
9392

9493
static const long double
9594
half = 0.5L,
@@ -267,20 +266,20 @@ sin_pi(long double x)
267266

268267

269268
long double
270-
lgammal(long double x)
269+
lgammal_r(long double x, int *signgamp)
271270
{
272271
long double t, y, z, nadj, p, p1, p2, q, r, w;
273272
int i, ix;
274273
u_int32_t se, i0, i1;
275274

276-
signgam = 1;
275+
*signgamp = 1;
277276
GET_LDOUBLE_WORDS (se, i0, i1, x);
278277
ix = se & 0x7fff;
279278

280279
if ((ix | i0 | i1) == 0)
281280
{
282281
if (se & 0x8000)
283-
signgam = -1;
282+
*signgamp = -1;
284283
return one / fabsl (x);
285284
}
286285

@@ -294,7 +293,7 @@ lgammal(long double x)
294293
{ /* |x|<2**-63, return -log(|x|) */
295294
if (se & 0x8000)
296295
{
297-
signgam = -1;
296+
*signgamp = -1;
298297
return -logl (-x);
299298
}
300299
else
@@ -307,7 +306,7 @@ lgammal(long double x)
307306
return one / fabsl (t); /* -integer */
308307
nadj = logl (pi / fabsl (t * x));
309308
if (t < zero)
310-
signgam = -1;
309+
*signgamp = -1;
311310
x = -x;
312311
}
313312

src/Make.files

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ $(CUR_SRCS) = common.c \
44
e_expf.c e_fmod.c e_fmodf.c e_gamma.c e_gamma_r.c e_gammaf.c \
55
e_gammaf_r.c e_hypot.c e_hypotf.c e_j0.c e_j0f.c e_j1.c e_j1f.c \
66
e_jn.c e_jnf.c e_lgamma.c e_lgamma_r.c e_lgammaf.c e_lgammaf_r.c \
7-
e_log.c e_log10.c e_log10f.c e_log2.c e_log2f.c e_logf.c \
7+
e_lgammal.c e_log.c e_log10.c e_log10f.c e_log2.c e_log2f.c e_logf.c \
88
e_pow.c e_powf.c e_remainder.c e_remainderf.c e_scalb.c e_scalbf.c \
99
e_rem_pio2.c e_rem_pio2f.c \
1010
e_sinh.c e_sinhf.c e_sqrt.c e_sqrtf.c \

src/e_lgammal.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#include "cdefs-compat.h"
2+
#include "openlibm.h"
3+
#include "math_private.h"
4+
5+
extern int signgam;
6+
7+
DLLEXPORT long double
8+
lgammal(long double x)
9+
{
10+
11+
return (lgammal_r(x, &signgam));
12+
}

src/openlibm.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -558,9 +558,13 @@ long double tanhl(long double);
558558
long double tanl(long double);
559559
long double tgammal(long double);
560560
long double truncl(long double);
561-
562561
#endif /* __ISO_C_VISIBLE >= 1999 */
563562

563+
/* Reentrant version of lgammal. */
564+
#if __BSD_VISIBLE
565+
long double lgammal_r(long double, int *);
566+
#endif /* __BSD_VISIBLE */
567+
564568
#include "openlibm_complex.h"
565569

566570
#if defined(__cplusplus)

0 commit comments

Comments
 (0)