Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 5674eb9

Browse files
committed
Fix power() for large inputs yet more.
Buildfarm results for commit e532b1d reveal the error in my thinking about the unexpected-EDOM case. I'd supposed this was no longer really a live issue, but it seems the fix for glibc's bug #3866 is not all that old, and we still have at least one buildfarm animal (lapwing) with the bug. Hence, resurrect essentially the previous logic (but, I hope, less opaquely presented), and explain what it is we're really doing here. Also, blindly try to fix fossa's failure by tweaking the logic that figures out whether y is an odd integer when x is -inf. This smells a whole lot like a compiler bug, but I lack access to icc to try to pin it down. Maybe doing division instead of multiplication will dodge the issue. Discussion: https://postgr.es/m/E1jkU7H-00024V-NZ@gemulon.postgresql.org
1 parent 2961c97 commit 5674eb9

File tree

1 file changed

+23
-11
lines changed

1 file changed

+23
-11
lines changed

src/backend/utils/adt/float.c

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1583,7 +1583,7 @@ dpow(PG_FUNCTION_ARGS)
15831583
if (arg2 == floor(arg2))
15841584
{
15851585
/* y is integral; it's odd if y/2 is not integral */
1586-
double halfy = arg2 * 0.5; /* should be computed exactly */
1586+
double halfy = arg2 / 2; /* should be computed exactly */
15871587

15881588
if (halfy != floor(halfy))
15891589
yisoddinteger = true;
@@ -1608,17 +1608,29 @@ dpow(PG_FUNCTION_ARGS)
16081608
if (errno == EDOM || isnan(result))
16091609
{
16101610
/*
1611-
* We eliminated all the possible domain errors above, or should
1612-
* have; but if pow() has a more restrictive test for "is y an
1613-
* integer?" than we do, we could get here anyway. Historical
1614-
* evidence suggests that some platforms once implemented the test
1615-
* as "y == (long) y", which of course misbehaves beyond LONG_MAX.
1616-
* There's not a lot of choice except to accept the platform's
1617-
* conclusion that we have a domain error.
1611+
* We handled all possible domain errors above, so this should be
1612+
* impossible. However, old glibc versions on x86 have a bug that
1613+
* causes them to fail this way for abs(y) greater than 2^63:
1614+
*
1615+
* https://sourceware.org/bugzilla/show_bug.cgi?id=3866
1616+
*
1617+
* Hence, if we get here, assume y is finite but large (large
1618+
* enough to be certainly even). The result should be 0 if x == 0,
1619+
* 1.0 if abs(x) == 1.0, otherwise an overflow or underflow error.
16181620
*/
1619-
ereport(ERROR,
1620-
(errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
1621-
errmsg("a negative number raised to a non-integer power yields a complex result")));
1621+
if (arg1 == 0.0)
1622+
result = 0.0; /* we already verified y is positive */
1623+
else
1624+
{
1625+
double absx = fabs(arg1);
1626+
1627+
if (absx == 1.0)
1628+
result = 1.0;
1629+
else if (arg2 >= 0.0 ? (absx > 1.0) : (absx < 1.0))
1630+
float_overflow_error();
1631+
else
1632+
float_underflow_error();
1633+
}
16221634
}
16231635
else if (errno == ERANGE)
16241636
{

0 commit comments

Comments
 (0)