Re: power() function in Windows: "value out of range: underflow" - Mailing list pgsql-bugs

From David Rowley
Subject Re: power() function in Windows: "value out of range: underflow"
Date
Msg-id CAKJS1f9y5RqPps4i+13k9ry9pHZ2p_pCtZrOke0-4Nkz3POqbg@mail.gmail.com
Whole thread Raw
In response to power() function in Windows: "value out of range: underflow"  (Huong Dangminh <huo-dangminh@ys.jp.nec.com>)
Responses Re: power() function in Windows: "value out of range: underflow"  (Euler Taveira <euler@timbira.com.br>)
Re: power() function in Windows: "value out of range: underflow"  (Euler Taveira <euler@timbira.com.br>)
List pgsql-bugs
On 10 April 2018 at 20:30, Huong Dangminh <huo-dangminh@ys.jp.nec.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


pgsql-bugs by date:

Previous
From: Soni M
Date:
Subject: Re: pg_dump with disable trigger
Next
From: Michael Paquier
Date:
Subject: Re: BUG #15105: OpenTransientFile() should be paired withCloseTransientFile() rather than close()