Opened 9 years ago

Closed 9 years ago

#8809 closed Bugs (fixed)

pow(cpp_dec_float_type(-1), cpp_dec_float_type(n)) != (+-)1 for n >= 0x8000000000000000u

Reported by: Jan Bouwer <JBouwer@…> Owned by: John Maddock
Milestone: To Be Determined Component: multiprecision
Version: Boost Development Trunk Severity: Problem
Keywords: Cc: pbristow@…, e_float@…

Description

Function pow(const number-or-expression-template-type&, const number-or-expression-template-type&) for cpp_dec_float backend gives wrong answer when used with base -1 and a positive exponent equivalent to a type (unsigned 64bit on my platform) with the high bit set; i.e. an exponent >= 0x8000000000000000u.

The answers suggest that the exponent may be interpreted as its 2's complement-negative value (not confirmed) - see sample output below. This may be related to #8711 & #8798.

Output from attached code:

pow(-1, 9.22337e+18) = -0.00127263
pow(-1, 9.22337e+18) = -0.00127263
pow(-1, 1.84467e+19) = 0
pow(-1, 1.84467e+19) = 0
pow(-1, 9.22337e+18) = -0.00127263
pow(-1, 9.22337e+18) = -0.00127263
pow(-1, 1.84467e+19) = 0
pow(-1, 1.84467e+19) = 0

Tested against trunk rev 8490 with clang (Apple LLVM version 4.2 (clang-425.0.28) (based on LLVM 3.2svn)) target: x86_64-apple-darwin12.4.0 with: -std=c++11 -stdlib=libc++.

Attachments (1)

boost_multiprecision_power_demo2.cpp (938 bytes ) - added by Jan Bouwer <JBouwer@…> 9 years ago.
Demonstration of the error

Download all attachments as: .zip

Change History (4)

by Jan Bouwer <JBouwer@…>, 9 years ago

Demonstration of the error

comment:1 by Jan Bouwer <JBouwer@…>, 9 years ago

Curiously (or not ;-)) - my std library function pow(double, double) gives the same answers ... ... perhaps shifting the scope of this elsewhere?

comment:2 by John Maddock, 9 years ago

Cc: pbristow@… e_float@… added
Status: newassigned

This is actually quite tricky - and hard to deal with in a consistent (across different backends) way.

The issue is that these routines need to check for integer exponent when the base is < 1, but this is hard to do when the exponent becomes overly large. A related point is that once the exponent becomes sufficiently large it's no longer possible to determine whether it is even or odd (needed for the sign of the result) as the final digit has dropped off the end of the floating point type.

That said we should be able to fix this up to numeric_limits<uintmax_t>::max(), and this has uncovered some broken error handling too. I'm CC'ing Chris and Paul into this issue in case they have some ideas.

comment:3 by John Maddock, 9 years ago

Resolution: fixed
Status: assignedclosed

(In [85008]) Fix mpfi pow function to correctly handle negative base with integer power. Fixed error handling to not return numeric_limits<>::quiet_NaN if there is no NaN supported. Fixed default pow implementation to handle integer args up to numeric_limits<uintmax_t>::max(). Fixed error handling in default pow implementation to return NaN for too large exponents (can't tell if they're integers or even or odd) and negative bases. Fixed array subscript bug in cpp_dec_float. Greatly increased pow testing. Fixes #8809.

Note: See TracTickets for help on using tickets.