2007-03-01  Jakub Jelinek  <jakub@redhat.com>
	[BZ #4096]
	* sysdeps/ieee754/dbl-64/e_pow.c (__ieee754_pow): Check for NaN
	earlier.
	* math/libm-test.inc (pow_test): Add more tests involving NaNs.

	* sysdeps/i386/fpu/e_powf.S (__ieee754_powf): Avoid invalid exception
	for x qNaN and y either +-inf or non-integer value.
	* sysdeps/i386/fpu/e_pow.S (__ieee754_pow): Likewise.
	* sysdeps/i386/fpu/e_powl.S (__ieee754_powl): Likewise.
	* sysdeps/x86_64/fpu/e_powl.S (__ieee754_powl): Likewise.
This commit is contained in:
Ulrich Drepper 2007-03-05 19:38:56 +00:00
parent 245a1481d7
commit 8f3edfee15
7 changed files with 76 additions and 43 deletions

View File

@ -1,3 +1,16 @@
2007-03-01 Jakub Jelinek <jakub@redhat.com>
[BZ #4096]
* sysdeps/ieee754/dbl-64/e_pow.c (__ieee754_pow): Check for NaN
earlier.
* math/libm-test.inc (pow_test): Add more tests involving NaNs.
* sysdeps/i386/fpu/e_powf.S (__ieee754_powf): Avoid invalid exception
for x qNaN and y either +-inf or non-integer value.
* sysdeps/i386/fpu/e_pow.S (__ieee754_pow): Likewise.
* sysdeps/i386/fpu/e_powl.S (__ieee754_powl): Likewise.
* sysdeps/x86_64/fpu/e_powl.S (__ieee754_powl): Likewise.
2007-02-10 Mike Frysinger <vapier@gentoo.org> 2007-02-10 Mike Frysinger <vapier@gentoo.org>
* sysdeps/unix/sysv/linux/sh/Makefile: Remove sys/io.h * sysdeps/unix/sysv/linux/sh/Makefile: Remove sys/io.h

View File

@ -4614,6 +4614,17 @@ pow_test (void)
/* pow (x, NaN) == NaN. */ /* pow (x, NaN) == NaN. */
TEST_ff_f (pow, 3.0, nan_value, nan_value); TEST_ff_f (pow, 3.0, nan_value, nan_value);
TEST_ff_f (pow, minus_zero, nan_value, nan_value);
TEST_ff_f (pow, plus_infty, nan_value, nan_value);
TEST_ff_f (pow, -3.0, nan_value, nan_value);
TEST_ff_f (pow, minus_infty, nan_value, nan_value);
TEST_ff_f (pow, nan_value, 3.0, nan_value);
TEST_ff_f (pow, nan_value, -3.0, nan_value);
TEST_ff_f (pow, nan_value, plus_infty, nan_value);
TEST_ff_f (pow, nan_value, minus_infty, nan_value);
TEST_ff_f (pow, nan_value, 2.5, nan_value);
TEST_ff_f (pow, nan_value, -2.5, nan_value);
TEST_ff_f (pow, 1, plus_infty, 1); TEST_ff_f (pow, 1, plus_infty, 1);
TEST_ff_f (pow, -1, plus_infty, 1); TEST_ff_f (pow, -1, plus_infty, 1);

View File

@ -1,5 +1,5 @@
/* ix87 specific implementation of pow function. /* ix87 specific implementation of pow function.
Copyright (C) 1996, 1997, 1998, 1999, 2001, 2004, 2005 Copyright (C) 1996, 1997, 1998, 1999, 2001, 2004, 2005, 2007
Free Software Foundation, Inc. Free Software Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
@ -161,10 +161,11 @@ ENTRY(__ieee754_pow)
2: /* y is a real number. */ 2: /* y is a real number. */
fxch // x : y fxch // x : y
fldl MO(one) // 1.0 : x : y fldl MO(one) // 1.0 : x : y
fld %st(1) // x : 1.0 : x : y fldl MO(limit) // 0.29 : 1.0 : x : y
fsub %st(1) // x-1 : 1.0 : x : y fld %st(2) // x : 0.29 : 1.0 : x : y
fabs // |x-1| : 1.0 : x : y fsub %st(2) // x-1 : 0.29 : 1.0 : x : y
fcompl MO(limit) // 1.0 : x : y fabs // |x-1| : 0.29 : 1.0 : x : y
fucompp // 1.0 : x : y
fnstsw fnstsw
fxch // x : 1.0 : y fxch // x : 1.0 : y
sahf sahf
@ -197,9 +198,10 @@ ENTRY(__ieee754_pow)
// y == ±inf // y == ±inf
.align ALIGNARG(4) .align ALIGNARG(4)
12: fstp %st(0) // pop y 12: fstp %st(0) // pop y
fldl 4(%esp) // x fldl MO(one) // 1
fabs fldl 4(%esp) // x : 1
fcompl MO(one) // < 1, == 1, or > 1 fabs // abs(x) : 1
fucompp // < 1, == 1, or > 1
fnstsw fnstsw
andb $0x45, %ah andb $0x45, %ah
cmpb $0x45, %ah cmpb $0x45, %ah

View File

@ -1,5 +1,5 @@
/* ix87 specific implementation of pow function. /* ix87 specific implementation of pow function.
Copyright (C) 1996, 1997, 1999, 2001, 2004, 2005 Copyright (C) 1996, 1997, 1999, 2001, 2004, 2005, 2007
Free Software Foundation, Inc. Free Software Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
@ -155,10 +155,11 @@ ENTRY(__ieee754_powf)
2: /* y is a real number. */ 2: /* y is a real number. */
fxch // x : y fxch // x : y
fldl MO(one) // 1.0 : x : y fldl MO(one) // 1.0 : x : y
fld %st(1) // x : 1.0 : x : y fldl MO(limit) // 0.29 : 1.0 : x : y
fsub %st(1) // x-1 : 1.0 : x : y fld %st(2) // x : 0.29 : 1.0 : x : y
fabs // |x-1| : 1.0 : x : y fsub %st(2) // x-1 : 0.29 : 1.0 : x : y
fcompl MO(limit) // 1.0 : x : y fabs // |x-1| : 0.29 : 1.0 : x : y
fucompp // 1.0 : x : y
fnstsw fnstsw
fxch // x : 1.0 : y fxch // x : 1.0 : y
sahf sahf
@ -191,9 +192,10 @@ ENTRY(__ieee754_powf)
// y == ±inf // y == ±inf
.align ALIGNARG(4) .align ALIGNARG(4)
12: fstp %st(0) // pop y 12: fstp %st(0) // pop y
flds 4(%esp) // x fldl MO(one) // 1
fabs flds 4(%esp) // x : 1
fcompl MO(one) // < 1, == 1, or > 1 fabs // abs(x) : 1
fucompp // < 1, == 1, or > 1
fnstsw fnstsw
andb $0x45, %ah andb $0x45, %ah
cmpb $0x45, %ah cmpb $0x45, %ah

View File

@ -1,5 +1,5 @@
/* ix87 specific implementation of pow function. /* ix87 specific implementation of pow function.
Copyright (C) 1996, 1997, 1998, 1999, 2001, 2004, 2005 Copyright (C) 1996, 1997, 1998, 1999, 2001, 2004, 2005, 2007
Free Software Foundation, Inc. Free Software Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
@ -161,10 +161,11 @@ ENTRY(__ieee754_powl)
2: /* y is a real number. */ 2: /* y is a real number. */
fxch // x : y fxch // x : y
fldl MO(one) // 1.0 : x : y fldl MO(one) // 1.0 : x : y
fld %st(1) // x : 1.0 : x : y fldl MO(limit) // 0.29 : 1.0 : x : y
fsub %st(1) // x-1 : 1.0 : x : y fld %st(2) // x : 0.29 : 1.0 : x : y
fabs // |x-1| : 1.0 : x : y fsub %st(2) // x-1 : 0.29 : 1.0 : x : y
fcompl MO(limit) // 1.0 : x : y fabs // |x-1| : 0.29 : 1.0 : x : y
fucompp // 1.0 : x : y
fnstsw fnstsw
fxch // x : 1.0 : y fxch // x : 1.0 : y
sahf sahf
@ -210,9 +211,10 @@ ENTRY(__ieee754_powl)
// y == ±inf // y == ±inf
.align ALIGNARG(4) .align ALIGNARG(4)
12: fstp %st(0) // pop y 12: fstp %st(0) // pop y
fldt 4(%esp) // x fldl MO(one) // 1
fabs fldt 4(%esp) // x : 1
fcompl MO(one) // < 1, == 1, or > 1 fabs // abs(x) : 1
fucompp // < 1, == 1, or > 1
fnstsw fnstsw
andb $0x45, %ah andb $0x45, %ah
cmpb $0x45, %ah cmpb $0x45, %ah

View File

@ -106,20 +106,28 @@ double __ieee754_pow(double x, double y) {
else else
return y < 0 ? 1.0/ABS(x) : 0.0; /* return 0 */ return y < 0 ? 1.0/ABS(x) : 0.0; /* return 0 */
} }
qx = u.i[HIGH_HALF]&0x7fffffff; /* no sign */
qy = v.i[HIGH_HALF]&0x7fffffff; /* no sign */
if (qx >= 0x7ff00000 && (qx > 0x7ff00000 || u.i[LOW_HALF] != 0)) return NaNQ.x;
if (qy >= 0x7ff00000 && (qy > 0x7ff00000 || v.i[LOW_HALF] != 0))
return x == 1.0 ? 1.0 : NaNQ.x;
/* if x<0 */ /* if x<0 */
if (u.i[HIGH_HALF] < 0) { if (u.i[HIGH_HALF] < 0) {
k = checkint(y); k = checkint(y);
if (k==0) { if (k==0) {
if ((v.i[HIGH_HALF] & 0x7fffffff) == 0x7ff00000 && v.i[LOW_HALF] == 0) { if (qy == 0x7ff00000) {
if (x == -1.0) return 1.0; if (x == -1.0) return 1.0;
else if (x > -1.0) return v.i[HIGH_HALF] < 0 ? INF.x : 0.0; else if (x > -1.0) return v.i[HIGH_HALF] < 0 ? INF.x : 0.0;
else return v.i[HIGH_HALF] < 0 ? 0.0 : INF.x; else return v.i[HIGH_HALF] < 0 ? 0.0 : INF.x;
} }
else if (u.i[HIGH_HALF] == 0xfff00000 && u.i[LOW_HALF] == 0) else if (qx == 0x7ff00000)
return y < 0 ? 0.0 : INF.x; return y < 0 ? 0.0 : INF.x;
return NaNQ.x; /* y not integer and x<0 */ return NaNQ.x; /* y not integer and x<0 */
} }
else if (u.i[HIGH_HALF] == 0xfff00000 && u.i[LOW_HALF] == 0) else if (qx == 0x7ff00000)
{ {
if (k < 0) if (k < 0)
return y < 0 ? nZERO.x : nINF.x; return y < 0 ? nZERO.x : nINF.x;
@ -129,14 +137,6 @@ double __ieee754_pow(double x, double y) {
return (k==1)?__ieee754_pow(-x,y):-__ieee754_pow(-x,y); /* if y even or odd */ return (k==1)?__ieee754_pow(-x,y):-__ieee754_pow(-x,y); /* if y even or odd */
} }
/* x>0 */ /* x>0 */
qx = u.i[HIGH_HALF]&0x7fffffff; /* no sign */
qy = v.i[HIGH_HALF]&0x7fffffff; /* no sign */
if (qx > 0x7ff00000 || (qx == 0x7ff00000 && u.i[LOW_HALF] != 0)) return NaNQ.x;
/* if 0<x<2^-0x7fe */
if (qy > 0x7ff00000 || (qy == 0x7ff00000 && v.i[LOW_HALF] != 0))
return x == 1.0 ? 1.0 : NaNQ.x;
/* if y<2^-0x7fe */
if (qx == 0x7ff00000) /* x= 2^-0x3ff */ if (qx == 0x7ff00000) /* x= 2^-0x3ff */
{if (y == 0) return NaNQ.x; {if (y == 0) return NaNQ.x;

View File

@ -1,5 +1,6 @@
/* ix87 specific implementation of pow function. /* ix87 specific implementation of pow function.
Copyright (C) 1996, 1997, 1998, 1999, 2001, 2004 Free Software Foundation, Inc. Copyright (C) 1996, 1997, 1998, 1999, 2001, 2004, 2007
Free Software Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
@ -146,10 +147,11 @@ ENTRY(__ieee754_powl)
2: /* y is a real number. */ 2: /* y is a real number. */
fxch // x : y fxch // x : y
fldl MO(one) // 1.0 : x : y fldl MO(one) // 1.0 : x : y
fld %st(1) // x : 1.0 : x : y fldl MO(limit) // 0.29 : 1.0 : x : y
fsub %st(1) // x-1 : 1.0 : x : y fld %st(2) // x : 0.29 : 1.0 : x : y
fabs // |x-1| : 1.0 : x : y fsub %st(2) // x-1 : 0.29 : 1.0 : x : y
fcompl MO(limit) // 1.0 : x : y fabs // |x-1| : 0.29 : 1.0 : x : y
fucompp // 1.0 : x : y
fnstsw fnstsw
fxch // x : 1.0 : y fxch // x : 1.0 : y
test $4500,%eax test $4500,%eax
@ -190,9 +192,10 @@ ENTRY(__ieee754_powl)
// y == ±inf // y == ±inf
.align ALIGNARG(4) .align ALIGNARG(4)
12: fstp %st(0) // pop y 12: fstp %st(0) // pop y
fldt 8(%rsp) // x fldl MO(one) // 1
fabs fldt 8(%rsp) // x : 1
fcompl MO(one) // < 1, == 1, or > 1 fabs // abs(x) : 1
fucompp // < 1, == 1, or > 1
fnstsw fnstsw
andb $0x45, %ah andb $0x45, %ah
cmpb $0x45, %ah cmpb $0x45, %ah