This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Fix ldbl-128 / ldbl-128ibm lgamma overflow handling (bug 16347, bug 19046) [committed]


The ldbl-128 / ldbl-128ibm implementation of lgamma has problems with
its handling of large arguments.  It has an overflow threshold that is
correct only for ldbl-128, despite being used for both types - with
diagnostic control macros as a temporary measure to disable warnings
about that constant overflowing for ldbl-128ibm - and it has a
calculation that's roughly x * log(x) - x, resulting in overflows for
arguments that are roughly at most a factor 1/log(threshold) below the
overflow threshold.

This patch fixes both issues, using an overflow threshold appropriate
for the type in question and adding another case for large arguments
that avoids the possible intermediate overflow.

Tested for x86_64, x86, mips64 and powerpc.  Committed.

(auto-libm-test-out diffs omitted below.)

2015-10-01  Joseph Myers  <joseph@codesourcery.com>

	[BZ #16347]
	[BZ #19046]
	* sysdeps/ieee754/ldbl-128/e_lgammal_r.c: Do not include
	<libc-internal.h>.
	(MAXLGM): Do not use diagnostic control macros.
	[LDBL_MANT_DIG == 106] (MAXLGM): Change value to overflow
	threshold for ldbl-128ibm.
	(__ieee754_lgammal_r): For large arguments, multiply by log - 1
	instead of multiplying by log then subtracting.
	* math/auto-libm-test-in: Add more tests of lgamma.
	* math/auto-libm-test-out: Regenerated.

diff --git a/math/auto-libm-test-in b/math/auto-libm-test-in
index 25d6b9d..3399be1 100644
--- a/math/auto-libm-test-in
+++ b/math/auto-libm-test-in
@@ -2505,6 +2505,24 @@ lgamma -0x1p-16445
 lgamma 0x1p-16494
 lgamma -0x1p-16494
 
+# Values +/- 10ulp from overflow threshold.  (Values very close to
+# overflow threshold produce results very close of that threshold,
+# where a result inaccurate by a few ulp could differ from the ideal
+# result in whether it overflows; +/- 10ulp is sufficient for overflow
+# or its absence to be unambiguous under glibc's accuracy standards).
+# This also means the ldbl-128ibm inputs are XFAILed for dbl-64 and
+# the ldbl-128 inputs for ldbl-96, as too close to the threshold.
+lgamma 0x3.12be0cp+120
+lgamma 0x3.12be6p+120
+lgamma 0x5.d53649e2d4674p+1012
+lgamma 0x5.d53649e2d46c8p+1012
+lgamma 0x5.d53649e2d469dbc1f01e99fd52p+1012 xfail:dbl-64
+lgamma 0x5.d53649e2d469dbc1f01e99fd7cp+1012 xfail:dbl-64
+lgamma 0x5.c6aa645fffef5f5p+16368
+lgamma 0x5.c6aa645fffef5ff8p+16368
+lgamma 0x5.c6aa645fffef5fa912b9b480f7acp+16368 xfail:ldbl-96-intel xfail:ldbl-96-m68k
+lgamma 0x5.c6aa645fffef5fa912b9b480f8p+16368 xfail:ldbl-96-intel xfail:ldbl-96-m68k
+
 lgamma -0x1.fa471547c2fe5p+1
 lgamma -0x1.9260dcp+1
 
diff --git a/sysdeps/ieee754/ldbl-128/e_lgammal_r.c b/sysdeps/ieee754/ldbl-128/e_lgammal_r.c
index ab5a96e..5b513ea 100644
--- a/sysdeps/ieee754/ldbl-128/e_lgammal_r.c
+++ b/sysdeps/ieee754/ldbl-128/e_lgammal_r.c
@@ -70,17 +70,14 @@
 
 #include <math.h>
 #include <math_private.h>
-#include <libc-internal.h>
 #include <float.h>
 
-/* BZ#16347: ldbl-128ibm uses this file as is, however the MAXLGM
-   definition overflows for IBM long double.  This directive prevents the
-   overflow warnings until IBM long double version is fixed.  */
 static const long double PIL = 3.1415926535897932384626433832795028841972E0L;
-DIAG_PUSH_NEEDS_COMMENT;
-DIAG_IGNORE_NEEDS_COMMENT (4.6, "-Woverflow");
+#if LDBL_MANT_DIG == 106
+static const long double MAXLGM = 0x5.d53649e2d469dbc1f01e99fd66p+1012L;
+#else
 static const long double MAXLGM = 1.0485738685148938358098967157129705071571E4928L;
-DIAG_POP_NEEDS_COMMENT;
+#endif
 static const long double one = 1.0L;
 static const long double huge = LDBL_MAX;
 
@@ -1035,6 +1032,8 @@ __ieee754_lgammal_r (long double x, int *signgamp)
   if (x > MAXLGM)
     return (*signgamp * huge * huge);
 
+  if (x > 0x1p120L)
+    return x * (__logl (x) - 1.0L);
   q = ls2pi - x;
   q = (x - 0.5L) * __logl (x) + q;
   if (x > 1.0e18L)

-- 
Joseph S. Myers
joseph@codesourcery.com


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]