1
0
mirror of https://sourceware.org/git/glibc.git synced 2025-05-31 15:01:17 +03:00

Fix powf (close to -1, large) (bug 18647).

The flt-32 implementation of powf wrongly uses x-1 instead of |x|-1
when computing log (x) for the case where |x| is close to 1 and y is
large.  This patch fixes the logic accordingly.  Relevant tests
existed for x close to 1, and corresponding tests are added for x
close to -1, as well as for some new variant cases.

Tested for x86_64 and x86.

	[BZ #18647]
	* sysdeps/ieee754/flt-32/e_powf.c (__ieee754_powf): For large y
	and |x| close to 1, use absolute value of x when computing log.
	* math/auto-libm-test-in: Add more tests of pow.
	* math/auto-libm-test-out: Regenerated.
This commit is contained in:
Joseph Myers 2015-08-05 15:01:58 +00:00
parent 2aa6c8af26
commit cf36e5034f
5 changed files with 5661 additions and 2 deletions

View File

@ -1,3 +1,11 @@
2015-08-05 Joseph Myers <joseph@codesourcery.com>
[BZ #18647]
* sysdeps/ieee754/flt-32/e_powf.c (__ieee754_powf): For large y
and |x| close to 1, use absolute value of x when computing log.
* math/auto-libm-test-in: Add more tests of pow.
* math/auto-libm-test-out: Regenerated.
2015-08-05 Adhemerval Zanella <adhemerval.zanella@linaro.org> 2015-08-05 Adhemerval Zanella <adhemerval.zanella@linaro.org>
* sysdeps/unix/sysv/linux/arm/mmap.c: Add file. * sysdeps/unix/sysv/linux/arm/mmap.c: Add file.

2
NEWS
View File

@ -8,7 +8,7 @@ using `glibc' in the "product" field.
Version 2.23 Version 2.23
* The following bugs are resolved with this release: * The following bugs are resolved with this release:
18265, 18525. 18265, 18525, 18647.
Version 2.22 Version 2.22

View File

@ -2361,6 +2361,46 @@ pow 0x0.ffffffffffffffffffffffffffff8p0 -0x1.23456789abcdef0123456789abcdp126
pow 0x1.0000000000000000000000000001p0 0x1.23456789abcdef0123456789abcdp125 pow 0x1.0000000000000000000000000001p0 0x1.23456789abcdef0123456789abcdp125
pow 0x1.0000000000000000000000000001p0 -0x1.23456789abcdef0123456789abcdp125 pow 0x1.0000000000000000000000000001p0 -0x1.23456789abcdef0123456789abcdp125
pow -0x0.ffffffp0 10
pow -0x0.ffffffp0 100
pow -0x0.ffffffp0 1000
pow -0x0.ffffffp0 0x1p24
pow -0x0.ffffffp0 0x1p30
pow -0x0.ffffffp0 0x1.234566p30
pow -0x0.ffffffp0 -10
pow -0x0.ffffffp0 -100
pow -0x0.ffffffp0 -1000
pow -0x0.ffffffp0 -0x1p24
pow -0x0.ffffffp0 -0x1p30
pow -0x0.ffffffp0 -0x1.234566p30
pow -0x1.000002p0 0x1p24
pow -0x1.000002p0 0x1.234566p29
pow -0x1.000002p0 -0x1.234566p29
pow -0x0.fffffffffffff8p0 0x1.23456789abcdfp62
pow -0x0.fffffffffffff8p0 -0x1.23456789abcdfp62
pow -0x1.0000000000001p0 0x1.23456789abcdfp61
pow -0x1.0000000000001p0 -0x1.23456789abcdfp61
pow -0x0.ffffffffffffffffp0 0x1.23456789abcdef0ep77
pow -0x0.ffffffffffffffffp0 -0x1.23456789abcdef0ep77
pow -0x1.0000000000000002p0 0x1.23456789abcdef0ep76
pow -0x1.0000000000000002p0 -0x1.23456789abcdef0ep76
pow -0x0.ffffffffffffffffffffffffffff8p0 0x1.23456789abcdef0123456789abcdp126
pow -0x0.ffffffffffffffffffffffffffff8p0 -0x1.23456789abcdef0123456789abcdp126
pow -0x1.0000000000000000000000000001p0 0x1.23456789abcdef0123456789abcdp125
pow -0x1.0000000000000000000000000001p0 -0x1.23456789abcdef0123456789abcdp125
pow 0x1.000002p0 0x1p30
pow -0x1.000002p0 0x1p30
pow 0x1.000002p0 max
pow -0x1.000002p0 max
pow 0x1.00000ep0 0x1p30
pow -0x1.00000ep0 0x1p30
pow 0x1.00000ep0 max
pow -0x1.00000ep0 max
pow 1e4932 0.75 pow 1e4932 0.75
pow 1e4928 0.75 pow 1e4928 0.75
pow 1e4924 0.75 pow 1e4924 0.75

File diff suppressed because it is too large Load Diff

View File

@ -131,7 +131,7 @@ __ieee754_powf(float x, float y)
if(ix>0x3f800007) return (hy>0)? huge*huge:tiny*tiny; if(ix>0x3f800007) return (hy>0)? huge*huge:tiny*tiny;
/* now |1-x| is tiny <= 2**-20, suffice to compute /* now |1-x| is tiny <= 2**-20, suffice to compute
log(x) by x-x^2/2+x^3/3-x^4/4 */ log(x) by x-x^2/2+x^3/3-x^4/4 */
t = x-1; /* t has 20 trailing zeros */ t = ax-1; /* t has 20 trailing zeros */
w = (t*t)*((float)0.5-t*((float)0.333333333333-t*(float)0.25)); w = (t*t)*((float)0.5-t*((float)0.333333333333-t*(float)0.25));
u = ivln2_h*t; /* ivln2_h has 16 sig. bits */ u = ivln2_h*t; /* ivln2_h has 16 sig. bits */
v = t*ivln2_l-w*ivln2; v = t*ivln2_l-w*ivln2;