about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAdhemerval Zanella <azanella@linux.vnet.ibm.com>2013-05-06 14:40:17 -0500
committerAdhemerval Zanella <azanella@linux.vnet.ibm.com>2013-05-06 14:40:17 -0500
commit16e616a72f9ac247520c0c7da99b99e229facdf9 (patch)
treeebecfcd57f8fec0766600b1bcc1d037fdd83ed8a
parentd5e8275481e57cc7f3bd6ba435a7bbced9b97202 (diff)
downloadglibc-16e616a72f9ac247520c0c7da99b99e229facdf9.tar.gz
glibc-16e616a72f9ac247520c0c7da99b99e229facdf9.tar.xz
glibc-16e616a72f9ac247520c0c7da99b99e229facdf9.zip
PowerPC: fix hypot/hypof FP exceptions
This patch fixes hypot/hypotf spurious floating-point exceptions
generate by internal operations.
-rw-r--r--ChangeLog8
-rw-r--r--NEWS2
-rw-r--r--math/libm-test.inc2
-rw-r--r--sysdeps/powerpc/fpu/e_hypot.c16
-rw-r--r--sysdeps/powerpc/fpu/e_hypotf.c14
5 files changed, 25 insertions, 17 deletions
diff --git a/ChangeLog b/ChangeLog
index 1c43908d62..4bf30b6c57 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2013-05-06  Adhemerval Zanella  <azanella@linux.vnet.ibm.com>
+
+	[BZ #15418]
+	[BZ #15419]
+	* sysdeps/powerpc/fpu/e_hypot.c: Fix spurious FP exception generated by
+	internal tests.
+	* sysdeps/powerpc/fpu/e_hypotf.c: Likewise.
+
 2013-05-06  Roland McGrath  <roland@hack.frob.com>
 
 	* elf/dl-writev.h: New file.
diff --git a/NEWS b/NEWS
index ce654c1e5c..95a4e4f4c3 100644
--- a/NEWS
+++ b/NEWS
@@ -16,7 +16,7 @@ Version 2.18
   15084, 15085, 15086, 15160, 15214, 15221, 15232, 15234, 15283, 15285,
   15287, 15304, 15305, 15307, 15309, 15327, 15330, 15335, 15336, 15337,
   15342, 15346, 15361, 15366, 15380, 15394, 15405, 15406, 15409, 15416,
-  15423.
+  15418, 15419, 15423.
 
 * CVE-2013-0242 Buffer overrun in regexp matcher has been fixed (Bugzilla
   #15078).
diff --git a/math/libm-test.inc b/math/libm-test.inc
index 4e1eb72919..7afa46dba8 100644
--- a/math/libm-test.inc
+++ b/math/libm-test.inc
@@ -9159,6 +9159,7 @@ hypot_test (void)
   TEST_ff_f (hypot, 0.75L, 1.25L, 1.45773797371132511771853821938639577L);
 
   TEST_ff_f (hypot, 1.0L, 0x1p-61L, 1.0L);
+  TEST_ff_f (hypot, 0x1p+0L, 0x1.fp-129L, 0x1p+0L);
 #if defined TEST_LDOUBLE && LDBL_MANT_DIG >= 106
   TEST_ff_f (hypot, 0x1.23456789abcdef0123456789ab8p-500L, 0x1.23456789abcdef0123456789ab8p-500L, 4.9155782399407039128612180934736799735113e-151L);
 #endif
@@ -9170,6 +9171,7 @@ hypot_test (void)
 
 #if !defined TEST_FLOAT && !(defined TEST_DOUBLE && defined TEST_INLINE)
   TEST_ff_f (hypot, 0x3p1021L, 0x4p1021L, 0x5p1021L);
+  TEST_ff_f (hypot, 0x1p+0L, 0x0.3ep-1022L, 0x1p+0L);
 #endif
 
 #if defined TEST_LDOUBLE && LDBL_MAX_EXP >= 16384 && !defined TEST_INLINE
diff --git a/sysdeps/powerpc/fpu/e_hypot.c b/sysdeps/powerpc/fpu/e_hypot.c
index f23633946f..d8568d6e3f 100644
--- a/sysdeps/powerpc/fpu/e_hypot.c
+++ b/sysdeps/powerpc/fpu/e_hypot.c
@@ -26,6 +26,7 @@ static const double two600  = 4.149515568880993e+180;
 static const double two1022 = 4.49423283715579e+307;
 static const double twoM500 = 3.054936363499605e-151;
 static const double twoM600 = 2.4099198651028841e-181;
+static const double two60factor = 1.5592502418239997e+290;
 static const double pdnum   = 2.225073858507201e-308;
 
 /* __ieee754_hypot(x,y)
@@ -87,9 +88,20 @@ __ieee754_hypot (double x, double y)
       x = y;
       y = t;
     }
-  if (y == 0.0 || (x / y) > two60)
+  if (y == 0.0)
+    return x;
+  /* if y is higher enough, y * 2^60 might overflow. The tests if
+     y >= 1.7976931348623157e+308/2^60 (two60factor) and uses the
+     appropriate check to avoid the overflow exception generation.  */
+  if (y > two60factor)
     {
-      return x + y;
+      if ((x / y) > two60)
+	return x + y;
+    }
+  else
+    {
+      if (x > (y * two60))
+	return x + y;
     }
   if (x > two500)
     {
diff --git a/sysdeps/powerpc/fpu/e_hypotf.c b/sysdeps/powerpc/fpu/e_hypotf.c
index e97f0c35e3..93055afce5 100644
--- a/sysdeps/powerpc/fpu/e_hypotf.c
+++ b/sysdeps/powerpc/fpu/e_hypotf.c
@@ -69,22 +69,8 @@ static const float two30  = 1.0737418e09;
 float
 __ieee754_hypotf (float x, float y)
 {
-  x = fabsf (x);
-  y = fabsf (y);
-
   TEST_INF_NAN (x, y);
 
-  if (y > x)
-    {
-      float t = y;
-      y = x;
-      x = t;
-    }
-  if (y == 0.0 || (x / y) > two30)
-    {
-      return x + y;
-    }
-
   return __ieee754_sqrt ((double) x * x + (double) y * y);
 }
 strong_alias (__ieee754_hypotf, __hypotf_finite)