about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJoseph Myers <joseph@codesourcery.com>2015-07-01 22:27:49 +0000
committerJoseph Myers <joseph@codesourcery.com>2015-07-01 22:27:49 +0000
commita04bb3306a9f9f17e5c588c903a438f1182ecd1a (patch)
tree41ea8bb67309f76a21a4269fd384518fee2cf000
parented225df3ad9cbac3c22ec3f0fbbed1f9c61d1c54 (diff)
downloadglibc-a04bb3306a9f9f17e5c588c903a438f1182ecd1a.tar.gz
glibc-a04bb3306a9f9f17e5c588c903a438f1182ecd1a.tar.xz
glibc-a04bb3306a9f9f17e5c588c903a438f1182ecd1a.zip
Fix ldbl-128 expm1l (-min_subnorm) result sign (bug 18619).
In the ldbl-128 implementation of expm1l, when expm1l's result should
underflow to 0 (argument minus the least subnormal, in some rounding
modes), it can be a zero of the wrong sign.  This patch fixes this in
the same way previously used for the x86 / x86_64 versions.

Tested for mips64.

	[BZ #18619]
	* sysdeps/ieee754/ldbl-128/s_expm1l.c (__expm1l): Force underflow
	and return argument in case of subnormal argument.
-rw-r--r--ChangeLog6
-rw-r--r--NEWS2
-rw-r--r--sysdeps/ieee754/ldbl-128/s_expm1l.c15
3 files changed, 19 insertions, 4 deletions
diff --git a/ChangeLog b/ChangeLog
index a2fd213951..7d501d5491 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2015-07-01  Joseph Myers  <joseph@codesourcery.com>
+
+	[BZ #18619]
+	* sysdeps/ieee754/ldbl-128/s_expm1l.c (__expm1l): Force underflow
+	and return argument in case of subnormal argument.
+
 2015-07-01  Martin Sebor  <msebor@redhat.com>
 
 	[BZ #18435]
diff --git a/NEWS b/NEWS
index 91320dd429..eecc9a1cc6 100644
--- a/NEWS
+++ b/NEWS
@@ -25,7 +25,7 @@ Version 2.22
   18496, 18497, 18498, 18502, 18507, 18512, 18513, 18519, 18520, 18522,
   18527, 18528, 18529, 18530, 18532, 18533, 18534, 18536, 18539, 18540,
   18542, 18544, 18545, 18546, 18547, 18549, 18553, 18558, 18569, 18583,
-  18585, 18586, 18593, 18594, 18602, 18612, 18613.
+  18585, 18586, 18593, 18594, 18602, 18612, 18613, 18619.
 
 * Cache information can be queried via sysconf() function on s390 e.g. with
   _SC_LEVEL1_ICACHE_SIZE as argument.
diff --git a/sysdeps/ieee754/ldbl-128/s_expm1l.c b/sysdeps/ieee754/ldbl-128/s_expm1l.c
index f708af504c..573d00be57 100644
--- a/sysdeps/ieee754/ldbl-128/s_expm1l.c
+++ b/sysdeps/ieee754/ldbl-128/s_expm1l.c
@@ -137,9 +137,18 @@ __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;
+  /* Avoid internal underflow when result does not underflow, while
+     ensuring underflow (without returning a zero of the wrong sign)
+     when the result does underflow.  */
+  if (fabsl (x) < 0x1p-113L)
+    {
+      if (fabsl (x) < LDBL_MIN)
+	{
+	  long double force_underflow = x * x;
+	  math_force_eval (force_underflow);
+	}
+      return x;
+    }
 
   /* Express x = ln 2 (k + remainder), remainder not exceeding 1/2. */
   xx = C1 + C2;			/* ln 2. */