Commit d1fc750b authored by Tom Lane's avatar Tom Lane

Make numeric power() handle NaNs according to the modern POSIX spec.

In commit 6bdf1303, we ensured that power()/^ for float8 would honor
the NaN behaviors specified by POSIX standards released in this century,
ie NaN ^ 0 = 1 and 1 ^ NaN = 1.  However, numeric_power() was not
touched and continued to follow the once-common behavior that every
case involving NaN input produces NaN.  For consistency, let's switch
the numeric behavior to the modern spec in the same release that ensures
that behavior for float8.

(Note that while 6bdf1303 was initially back-patched, we later undid
that, concluding that any behavioral change should appear only in v11.)

Discussion: https://postgr.es/m/10898.1526421338@sss.pgh.pa.us
parent b2b82228
...@@ -2972,10 +2972,27 @@ numeric_power(PG_FUNCTION_ARGS) ...@@ -2972,10 +2972,27 @@ numeric_power(PG_FUNCTION_ARGS)
NumericVar result; NumericVar result;
/* /*
* Handle NaN * Handle NaN cases. We follow the POSIX spec for pow(3), which says that
* NaN ^ 0 = 1, and 1 ^ NaN = 1, while all other cases with NaN inputs
* yield NaN (with no error).
*/ */
if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2)) if (NUMERIC_IS_NAN(num1))
{
if (!NUMERIC_IS_NAN(num2))
{
init_var_from_num(num2, &arg2);
if (cmp_var(&arg2, &const_zero) == 0)
PG_RETURN_NUMERIC(make_result(&const_one));
}
PG_RETURN_NUMERIC(make_result(&const_nan)); PG_RETURN_NUMERIC(make_result(&const_nan));
}
if (NUMERIC_IS_NAN(num2))
{
init_var_from_num(num1, &arg1);
if (cmp_var(&arg1, &const_one) == 0)
PG_RETURN_NUMERIC(make_result(&const_one));
PG_RETURN_NUMERIC(make_result(&const_nan));
}
/* /*
* Initialize things * Initialize things
......
...@@ -1664,6 +1664,37 @@ select 0.0 ^ 12.34; ...@@ -1664,6 +1664,37 @@ select 0.0 ^ 12.34;
0.0000000000000000 0.0000000000000000
(1 row) (1 row)
-- NaNs
select 'NaN'::numeric ^ 'NaN'::numeric;
?column?
----------
NaN
(1 row)
select 'NaN'::numeric ^ 0;
?column?
----------
1
(1 row)
select 'NaN'::numeric ^ 1;
?column?
----------
NaN
(1 row)
select 0 ^ 'NaN'::numeric;
?column?
----------
NaN
(1 row)
select 1 ^ 'NaN'::numeric;
?column?
----------
1
(1 row)
-- invalid inputs -- invalid inputs
select 0.0 ^ (-12.34); select 0.0 ^ (-12.34);
ERROR: zero raised to a negative power is undefined ERROR: zero raised to a negative power is undefined
......
...@@ -911,6 +911,13 @@ select (-12.34) ^ 0.0; ...@@ -911,6 +911,13 @@ select (-12.34) ^ 0.0;
select 12.34 ^ 0.0; select 12.34 ^ 0.0;
select 0.0 ^ 12.34; select 0.0 ^ 12.34;
-- NaNs
select 'NaN'::numeric ^ 'NaN'::numeric;
select 'NaN'::numeric ^ 0;
select 'NaN'::numeric ^ 1;
select 0 ^ 'NaN'::numeric;
select 1 ^ 'NaN'::numeric;
-- invalid inputs -- invalid inputs
select 0.0 ^ (-12.34); select 0.0 ^ (-12.34);
select (-12.34) ^ 1.2; select (-12.34) ^ 1.2;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment