Re: power() function in Windows: "value out of range: underflow"

From: David Rowley <david(dot)rowley(at)2ndquadrant(dot)com>
To: Huong Dangminh <huo-dangminh(at)ys(dot)jp(dot)nec(dot)com>
Cc: "pgsql-bugs(at)lists(dot)postgresql(dot)org" <pgsql-bugs(at)lists(dot)postgresql(dot)org>, Pg Hackers <pgsql-hackers(at)postgresql(dot)org>, Akio Iwaasa <aki-iwaasa(at)vt(dot)jp(dot)nec(dot)com>
Subject: Re: power() function in Windows: "value out of range: underflow"
Date: 2018-04-11 03:13:35
Message-ID: CAKJS1f9y5RqPps4i+13k9ry9pHZ2p_pCtZrOke0-4Nkz3POqbg@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-bugs pgsql-hackers

On 10 April 2018 at 20:30, Huong Dangminh <huo-dangminh(at)ys(dot)jp(dot)nec(dot)com> wrote:
> Hi,
>
> There are some cases that power() function does not work
> correctly with 'NaN' arguments in Windows environment.
> Something like,
>
> postgres=# select power('NaN',11);
> ERROR: value out of range: underflow
> postgres=# select power('NaN','NaN');
> ERROR: value out of range: underflow
> postgres=# select power(11,'NaN');
> ERROR: value out of range: underflow
>
> In Linux environment, instead of ERROR it returns 'NaN'.
>
> The reason here is,
> When pow() in float.c:dpow() is called with 'NaN' arguments,
> pow() returns 'NaN' but in Windows environment errno is set to
> EDOM(invalid floating-point exception).
> So, PostgreSQL update "result" and cause an ERROR in CHECKFLOATVAL macro.

I can recreate this when building with MSVC 2012. I confirm that I see
the same as you. Microsoft are setting errno to EDOM in the above 3
cases, where in Linux the result is still NaN, just the errno is not
set.

Looking at [1], it says:

* If x or y is a NaN, a NaN shall be returned (unless specified
elsewhere in this description).

* For any value of y (including NaN), if x is +1, 1.0 shall be returned.

* For any value of x (including NaN), if y is ±0, 1.0 shall be returned.

Which Microsoft seem to not have broken, they're just also setting the
errno to EDOM in the first case, which seems a little strange, but the
standard there does not seem to mention that it shouldn't do that.

You patch fixes the problem for me, and importantly the two following
cases still work:

postgres=# select power(1,'NaN');
power
-------
1
(1 row)

postgres=# select power('NaN', 0);
power
-------
1
(1 row)

There's no mention in the SQL standard about NaN handling in the above
two cases, but I wonder if it's worth also adding a couple of tests
for the above two cases to ensure all platforms are doing the same
thing... ?

I'd also rather see this line:

if (errno == EDOM && isnan(result) && !(isnan(arg1) || isnan(arg2)))

written as:

if (errno == EDOM && isnan(result) && !isnan(arg1) && !isnan(arg2))

[1] http://pubs.opengroup.org/onlinepubs/9699919799/functions/pow.html

--
David Rowley http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

In response to

Responses

Browse pgsql-bugs by date

  From Date Subject
Next Message Michael Paquier 2018-04-11 03:30:24 Re: BUG #15105: OpenTransientFile() should be paired with CloseTransientFile() rather than close()
Previous Message Soni M 2018-04-11 00:32:22 Re: pg_dump with disable trigger

Browse pgsql-hackers by date

  From Date Subject
Next Message Euler Taveira 2018-04-11 04:10:29 Re: power() function in Windows: "value out of range: underflow"
Previous Message Amit Langote 2018-04-11 02:33:54 Re: Boolean partitions syntax