lgamma_r and lgammaf_r return the wrong sign for -0.f

enh enh at google.com
Fri Sep 12 21:15:58 UTC 2014


if I pass -0.f to lgammaf_r, the sign returned in *signgamp is 1. this
is incorrect --- it should be -1.

both lgamma_r and lgammaf_r are affected, but the other special cases
in those functions look fine to me.

this is fixed in OpenBSD and glibc, but FreeBSD and NetBSD both have
the same bug.

patch below (whitespace mangled courtesy of gmail). i'd prefer to wait
for this to be fixed in FreeBSD and pull down the fix rather than just
fix it locally.

btw, it looks like you're missing coshl/sinhl/tanhl for ld128 now?
(they've been removed from imprecise.c without having ld128
implementations added afaics.)

 --elliott (Android libc maintainer)



Index: lib/msun/src/e_lgammaf_r.c
===================================================================
--- lib/msun/src/e_lgammaf_r.c (revision 271480)
+++ lib/msun/src/e_lgammaf_r.c (working copy)
@@ -140,7 +140,11 @@
  *signgamp = 1;
  ix = hx&0x7fffffff;
  if(ix>=0x7f800000) return x*x;
- if(ix==0) return one/vzero;
+ if(ix==0) {
+    if(hx<0)
+        *signgamp = -1;
+    return one/vzero;
+ }
  if(ix<0x35000000) { /* |x|<2**-21, return -log(|x|) */
     if(hx<0) {
         *signgamp = -1;
Index: lib/msun/src/e_lgamma_r.c
===================================================================
--- lib/msun/src/e_lgamma_r.c (revision 271480)
+++ lib/msun/src/e_lgamma_r.c (working copy)
@@ -212,7 +212,11 @@
  *signgamp = 1;
  ix = hx&0x7fffffff;
  if(ix>=0x7ff00000) return x*x;
- if((ix|lx)==0) return one/vzero;
+ if((ix|lx)==0) {
+    if(hx<0)
+        *signgamp = -1;
+    return one/vzero;
+ }
  if(ix<0x3b900000) { /* |x|<2**-70, return -log(|x|) */
     if(hx<0) {
         *signgamp = -1;


More information about the freebsd-numerics mailing list