about summary refs log tree commit diff
path: root/sysdeps/ieee754
diff options
context:
space:
mode:
authorJoseph Myers <joseph@codesourcery.com>2012-11-07 13:03:31 +0000
committerJoseph Myers <joseph@codesourcery.com>2012-11-07 13:03:31 +0000
commit60e235ee2ae834bb9f7a884f1b192304b9fdcf33 (patch)
tree4053809680e9b6def9eab8272fc70ac6c6edb16c /sysdeps/ieee754
parent0ab234b7db4991121eb572bf5c4971bfeb2d49a2 (diff)
downloadglibc-60e235ee2ae834bb9f7a884f1b192304b9fdcf33.tar.gz
glibc-60e235ee2ae834bb9f7a884f1b192304b9fdcf33.tar.xz
glibc-60e235ee2ae834bb9f7a884f1b192304b9fdcf33.zip
Fix spurious underflows from pow with results close to 1 (bug 14811).
Diffstat (limited to 'sysdeps/ieee754')
-rw-r--r--sysdeps/ieee754/dbl-64/e_pow.c4
-rw-r--r--sysdeps/ieee754/flt-32/e_powf.c4
2 files changed, 8 insertions, 0 deletions
diff --git a/sysdeps/ieee754/dbl-64/e_pow.c b/sysdeps/ieee754/dbl-64/e_pow.c
index 3fd5e6507f..513171891c 100644
--- a/sysdeps/ieee754/dbl-64/e_pow.c
+++ b/sysdeps/ieee754/dbl-64/e_pow.c
@@ -90,6 +90,10 @@ __ieee754_pow(double x, double y) {
 
     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*134217729.0;
     y1 = t - (t-y);
diff --git a/sysdeps/ieee754/flt-32/e_powf.c b/sysdeps/ieee754/flt-32/e_powf.c
index 43069479a5..12c408f93c 100644
--- a/sysdeps/ieee754/flt-32/e_powf.c
+++ b/sysdeps/ieee754/flt-32/e_powf.c
@@ -141,6 +141,10 @@ __ieee754_powf(float x, float y)
 	    t2 = v-(t1-u);
 	} else {
 	    float s2,s_h,s_l,t_h,t_l;
+	    /* Avoid internal underflow for tiny y.  The exact value
+	       of y does not matter if |y| <= 2**-32.  */
+	    if (iy < 0x2f800000)
+	      SET_FLOAT_WORD (y, (hy & 0x80000000) | 0x2f800000);
 	    n = 0;
 	/* take care subnormal number */
 	    if(ix<0x00800000)