pow(-DBL_MIN, 3) should be -0; similarly, pow(-DBL_MAX, -3) should be -0. glibc gets the sign of the 0 wrong here and in some such cases with large integer exponent wrongly returns NaN. Tested with current CVS glibc on i686-pc-linux-gnu, originally seen on PowerPC in testing an earlier glibc version with the ucbtest testsuite. I'll attach a testsuite patch that adds some tests for these cases to illustrate the problem. (There are already such tests where the first argument of pow is actually -0 or -infinity rather than -DBL_MIN or -DBL_MAX.) This shows failures such as in test-float.out (test-double.out, test-ldouble.out similar): Failure: Test: pow (-min_value, 3) == -0 Result: is: 0.00000000000000000000e+00 0x0.00000000000000000000p+0 should be: -0.00000000000000000000e+00 -0x0.00000000000000000000p+0 difference: 0.00000000000000000000e+00 0x0.00000000000000000000p+0 ulp : 0.0000 max.ulp : 0.0000 Failure: Test: pow (-min_value, 16777215) == -0 Result: is: 0.00000000000000000000e+00 0x0.00000000000000000000p+0 should be: -0.00000000000000000000e+00 -0x0.00000000000000000000p+0 difference: 0.00000000000000000000e+00 0x0.00000000000000000000p+0 ulp : 0.0000 max.ulp : 0.0000 Failure: pow (-min_value, 1e10) == 0.0: Exception "Invalid operation" set Failure: Test: pow (-min_value, 1e10) == 0.0 Result: is: nan nan should be: 0.00000000000000000000e+00 0x0.00000000000000000000p+0 Failure: pow (-min_value, 1e20) == 0.0: Exception "Invalid operation" set Failure: Test: pow (-min_value, 1e20) == 0.0 Result: is: nan nan should be: 0.00000000000000000000e+00 0x0.00000000000000000000p+0 Failure: Test: pow (-max_value, -3) == -0 Result: is: 0.00000000000000000000e+00 0x0.00000000000000000000p+0 should be: -0.00000000000000000000e+00 -0x0.00000000000000000000p+0 difference: 0.00000000000000000000e+00 0x0.00000000000000000000p+0 ulp : 0.0000 max.ulp : 0.0000 Failure: Test: pow (-max_value, -16777215) == -0 Result: is: 0.00000000000000000000e+00 0x0.00000000000000000000p+0 should be: -0.00000000000000000000e+00 -0x0.00000000000000000000p+0 difference: 0.00000000000000000000e+00 0x0.00000000000000000000p+0 ulp : 0.0000 max.ulp : 0.0000 Failure: pow (-max_value, -1e10) == 0.0: Exception "Invalid operation" set Failure: Test: pow (-max_value, -1e10) == 0.0 Result: is: nan nan should be: 0.00000000000000000000e+00 0x0.00000000000000000000p+0 Failure: pow (-max_value, -1e20) == 0.0: Exception "Invalid operation" set Failure: Test: pow (-max_value, -1e20) == 0.0 Result: is: nan nan should be: 0.00000000000000000000e+00 0x0.00000000000000000000p+0

Created attachment 1035 [details] Testsuite patch

Created attachment 4227 [details] test case

This is still wrong with glibc 2.9, and with 2.10.1 (development version): pow(-2.225074e-308,3.000000e+00) = 0.000000 (-0 expected) [mpfr -0.000000] pow(-2.225074e-308,1.677722e+07) = 0.000000 (-0 expected) [mpfr -0.000000] pow(-2.225074e-308,1.000000e+10) = 0.000000 (0 expected) [mpfr 0.000000] pow(-2.225074e-308,1.000000e+20) = 0.000000 (0 expected) [mpfr 0.000000] pow(-1.797693e+308,-3.000000e+00) = 0.000000 (-0 expected) [mpfr -0.000000] pow(-1.797693e+308,-1.677722e+07) = 0.000000 (-0 expected) [mpfr -0.000000] pow(-1.797693e+308,-1.000000e+10) = 0.000000 (0 expected) [mpfr 0.000000] pow(-1.797693e+308,-1.000000e+20) = 0.000000 (0 expected) [mpfr 0.000000] Moreover when compiling with -O1 with GCC 4.3.2 (i.e., when constant folding is activated) all tests except the first one are wrong too (but the values computed by MPFR are correct): libc version: 2.10.1 pow(-2.225074e-308,3.000000e+00) = -0.000000 (-0 expected) [mpfr -0.000000] pow(-2.225074e-308,1.677722e+07) = 0.000000 (-0 expected) [mpfr -0.000000] pow(-2.225074e-308,1.000000e+10) = 0.000000 (0 expected) [mpfr 0.000000] pow(-2.225074e-308,1.000000e+20) = 0.000000 (0 expected) [mpfr 0.000000] pow(-1.797693e+308,-3.000000e+00) = 0.000000 (-0 expected) [mpfr -0.000000] pow(-1.797693e+308,-1.677722e+07) = 0.000000 (-0 expected) [mpfr -0.000000] pow(-1.797693e+308,-1.000000e+10) = 0.000000 (0 expected) [mpfr 0.000000] pow(-1.797693e+308,-1.000000e+20) = 0.000000 (0 expected) [mpfr 0.000000]

(In reply to comment #3) > Moreover when compiling with -O1 with GCC 4.3.2 (i.e., when constant folding > is activated) It seems that constant folding on pow() isn't done by GCC yet. I interpret the change due to -O1 by an optimization like pow(x,3) -> x * x * x (and glibc isn't concerned since this is a GCC optimization).

(In reply to comment #4) > It seems that constant folding on pow() isn't done by GCC yet. according to http://gcc.gnu.org/gcc-4.3/changes.html#mpfropts, pow is also handled by the constant folding mechanism.

Confirmed still present.

Fixed by: commit d6270972f79fe89a96fa7a3909991dad2e317033 Author: Joseph Myers <joseph@codesourcery.com> Date: Wed Mar 28 14:57:58 2012 +0000 Fix pow of negative numbers to integer exponents (bugs 369, 2678, 3866).