Bug 2678 - pow returns incorrect results on underflow
Summary: pow returns incorrect results on underflow
Status: RESOLVED FIXED
Alias: None
Product: glibc
Classification: Unclassified
Component: math (show other bugs)
Version: 2.4
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2006-05-21 00:30 UTC by Joseph Myers
Modified: 2019-04-10 08:16 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:
fweimer: security-


Attachments
Testsuite patch (416 bytes, patch)
2006-05-21 00:31 UTC, Joseph Myers
Details | Diff
test case (463 bytes, text/x-csrc)
2009-09-24 09:42 UTC, Paul Zimmermann
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Joseph Myers 2006-05-21 00:30:11 UTC
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
Comment 1 Joseph Myers 2006-05-21 00:31:33 UTC
Created attachment 1035 [details]
Testsuite patch
Comment 2 Paul Zimmermann 2009-09-24 09:42:05 UTC
Created attachment 4227 [details]
test case
Comment 3 Paul Zimmermann 2009-09-24 09:43:38 UTC
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]
Comment 4 Vincent Lefèvre 2009-09-24 10:43:37 UTC
(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).
Comment 5 Paul Zimmermann 2009-09-24 14:06:29 UTC
(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.

Comment 6 Joseph Myers 2012-02-28 16:40:27 UTC
Confirmed still present.
Comment 7 Joseph Myers 2012-03-28 15:03:05 UTC
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).