about summary refs log tree commit diff
path: root/sysdeps/ieee754/dbl-64/e_pow.c
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/ieee754/dbl-64/e_pow.c')
-rw-r--r--sysdeps/ieee754/dbl-64/e_pow.c61
1 files changed, 41 insertions, 20 deletions
diff --git a/sysdeps/ieee754/dbl-64/e_pow.c b/sysdeps/ieee754/dbl-64/e_pow.c
index 1c5f4b311e..2dd66d87b7 100644
--- a/sysdeps/ieee754/dbl-64/e_pow.c
+++ b/sysdeps/ieee754/dbl-64/e_pow.c
@@ -34,6 +34,7 @@
 /* round to nearest mode of IEEE 754 standard.                             */
 /*                                                                         */
 /***************************************************************************/
+#include <math.h>
 #include "endian.h"
 #include "upow.h"
 #include <dla.h>
@@ -91,27 +92,33 @@ __ieee754_pow (double x, double y)
     {				/* if y<-1 or y>1   */
       double retval;
 
-      SET_RESTORE_ROUND (FE_TONEAREST);
+      {
+	SET_RESTORE_ROUND (FE_TONEAREST);
 
-      /* Avoid internal underflow for tiny y.  The exact value of y does
-         not matter if |y| <= 2**-64.  */
-      if (ABS (y) < 0x1p-64)
-	y = y < 0 ? -0x1p-64 : 0x1p-64;
-      z = log1 (x, &aa, &error);	/* x^y  =e^(y log (X)) */
-      t = y * CN;
-      y1 = t - (t - y);
-      y2 = y - y1;
-      t = z * CN;
-      a1 = t - (t - z);
-      a2 = (z - a1) + aa;
-      a = y1 * a1;
-      aa = y2 * a1 + y * a2;
-      a1 = a + aa;
-      a2 = (a - a1) + aa;
-      error = error * ABS (y);
-      t = __exp1 (a1, a2, 1.9e16 * error);	/* return -10 or 0 if wasn't computed exactly */
-      retval = (t > 0) ? t : power1 (x, y);
+	/* Avoid internal underflow for tiny y.  The exact value of y does
+	   not matter if |y| <= 2**-64.  */
+	if (ABS (y) < 0x1p-64)
+	  y = y < 0 ? -0x1p-64 : 0x1p-64;
+	z = log1 (x, &aa, &error);	/* x^y  =e^(y log (X)) */
+	t = y * CN;
+	y1 = t - (t - y);
+	y2 = y - y1;
+	t = z * CN;
+	a1 = t - (t - z);
+	a2 = (z - a1) + aa;
+	a = y1 * a1;
+	aa = y2 * a1 + y * a2;
+	a1 = a + aa;
+	a2 = (a - a1) + aa;
+	error = error * ABS (y);
+	t = __exp1 (a1, a2, 1.9e16 * error);	/* return -10 or 0 if wasn't computed exactly */
+	retval = (t > 0) ? t : power1 (x, y);
+      }
 
+      if (__isinf (retval))
+	retval = huge * huge;
+      else if (retval == 0)
+	retval = tiny * tiny;
       return retval;
     }
 
@@ -164,7 +171,21 @@ __ieee754_pow (double x, double y)
 	    return y < 0 ? 0.0 : INF.x;
 	}
       /* if y even or odd */
-      return (k == 1) ? __ieee754_pow (-x, y) : -__ieee754_pow (-x, y);
+      if (k == 1)
+	return __ieee754_pow (-x, y);
+      else
+	{
+	  double retval;
+	  {
+	    SET_RESTORE_ROUND (FE_TONEAREST);
+	    retval = -__ieee754_pow (-x, y);
+	  }
+	  if (__isinf (retval))
+	    retval = -huge * huge;
+	  else if (retval == 0)
+	    retval = -tiny * tiny;
+	  return retval;
+	}
     }
   /* x>0 */