diff options
author | Joseph Myers <joseph@codesourcery.com> | 2017-02-07 17:15:47 +0000 |
---|---|---|
committer | Joseph Myers <joseph@codesourcery.com> | 2017-02-07 17:15:47 +0000 |
commit | edbbdb185518008439221ed9db296ab31039d076 (patch) | |
tree | 4332e967234b3fca070f1f94d9d735fc3cfffb11 /sysdeps/ieee754 | |
parent | 43ce02c6ec27d4e2d8f0ae327bbbeaba84060964 (diff) | |
download | glibc-edbbdb185518008439221ed9db296ab31039d076.tar.gz glibc-edbbdb185518008439221ed9db296ab31039d076.tar.xz glibc-edbbdb185518008439221ed9db296ab31039d076.zip |
Fix powf inaccuracy (bug 21112).
Bug 21112 reports a case where powf is substantially inaccurate. This results from a multiplication where cp_h*p_h is required to be exact, and p_h is masked to have only 12 leading nonzero bits in its mantissa, but the value of cp_h has the 13th bit nonzero, leading to inexact multiplication results in some cases that can result in large errors in the final result of powf. This patch fixes this by using a value of cp_h correctly rounded to nearest to 12 bits, with a corresponding updated value of cp_l. Tested for x86_64 and x86. [BZ #21112] * sysdeps/ieee754/flt-32/e_powf.c (cp_h): Use value with trailing 12 bits zero. (cp_l): Update for new value of cp_h. * math/auto-libm-test-in: Add another test of pow. * math/auto-libm-test-out-pow: Regenerated.
Diffstat (limited to 'sysdeps/ieee754')
-rw-r--r-- | sysdeps/ieee754/flt-32/e_powf.c | 4 |
1 files changed, 2 insertions, 2 deletions
diff --git a/sysdeps/ieee754/flt-32/e_powf.c b/sysdeps/ieee754/flt-32/e_powf.c index d9470f190d..13b49def8e 100644 --- a/sysdeps/ieee754/flt-32/e_powf.c +++ b/sysdeps/ieee754/flt-32/e_powf.c @@ -43,8 +43,8 @@ lg2_h = 6.93145752e-01, /* 0x3f317200 */ lg2_l = 1.42860654e-06, /* 0x35bfbe8c */ ovt = 4.2995665694e-08, /* -(128-log2(ovfl+.5ulp)) */ cp = 9.6179670095e-01, /* 0x3f76384f =2/(3ln2) */ -cp_h = 9.6179199219e-01, /* 0x3f763800 =head of cp */ -cp_l = 4.7017383622e-06, /* 0x369dc3a0 =tail of cp_h */ +cp_h = 0xf.64p-4, /* cp high 12 bits. */ +cp_l = -0x7.b11e3p-16, /* 2/(3ln2) - cp_h. */ ivln2 = 1.4426950216e+00, /* 0x3fb8aa3b =1/ln2 */ ivln2_h = 1.4426879883e+00, /* 0x3fb8aa00 =16b 1/ln2*/ ivln2_l = 7.0526075433e-06; /* 0x36eca570 =1/ln2 tail*/ |