summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoseph Myers <joseph@codesourcery.com>2014-06-30 17:38:16 +0000
committerJoseph Myers <joseph@codesourcery.com>2014-06-30 17:38:16 +0000
commitce9c5b3e955746a9187ffde9b16feea4a357c86a (patch)
treee60ee24b2da9fb3291a4667607040ca7d9337fa1
parent3a6e988706d1ce2c88c933619d1f312098698ecd (diff)
downloadglibc-ce9c5b3e955746a9187ffde9b16feea4a357c86a.tar.gz
Fix ldbl-128 expm1l spurious underflow (bug 16539).
This patch fixes spurious underflows from ldbl-128 expm1l, as reported in <https://sourceware.org/ml/libc-alpha/2014-06/msg00835.html> and exposed by the tests added for such a bug in the x86 / x86-64 version. The bug and fix are essentially the same, so no separate bug is filed in Bugzilla. Tested for mips64. [BZ #16539] * sysdeps/ieee754/ldbl-128/s_expm1l.c: Include <float.h>. (__expm1l): Return argument unchanged when small but not subnormal.
-rw-r--r--ChangeLog5
-rw-r--r--sysdeps/ieee754/ldbl-128/s_expm1l.c5
2 files changed, 10 insertions, 0 deletions
diff --git a/ChangeLog b/ChangeLog
index 2ef0a7489d..8897d9ce14 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,10 @@
2014-06-30 Joseph Myers <joseph@codesourcery.com>
+ [BZ #16539]
+ * sysdeps/ieee754/ldbl-128/s_expm1l.c: Include <float.h>.
+ (__expm1l): Return argument unchanged when small but not
+ subnormal.
+
* soft-fp/op-1.h (_FP_UNPACK_RAW_1): Rename local variables to
include macro name.
(_FP_UNPACK_RAW_1_P): Likewise.
diff --git a/sysdeps/ieee754/ldbl-128/s_expm1l.c b/sysdeps/ieee754/ldbl-128/s_expm1l.c
index 1c12109511..f708af504c 100644
--- a/sysdeps/ieee754/ldbl-128/s_expm1l.c
+++ b/sysdeps/ieee754/ldbl-128/s_expm1l.c
@@ -54,6 +54,7 @@
#include <errno.h>
+#include <float.h>
#include <math.h>
#include <math_private.h>
@@ -136,6 +137,10 @@ __expm1l (long double x)
if (x < minarg)
return (4.0/big - 1.0L);
+ /* Avoid internal underflow when result does not underflow. */
+ if (fabsl (x) < 0x1p-113L && fabsl (x) >= LDBL_MIN)
+ return x;
+
/* Express x = ln 2 (k + remainder), remainder not exceeding 1/2. */
xx = C1 + C2; /* ln 2. */
px = __floorl (0.5 + x / xx);