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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy