Received: from malur.postgresql.org ([2a02:16a8:dc51::56]) by arkaria.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA384:256) (Exim 4.89) (envelope-from ) id 1fIhvL-0005Lw-By for pgsql-hackers@arkaria.postgresql.org; Tue, 15 May 2018 21:55:59 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.89) (envelope-from ) id 1fIhvJ-0005bX-UV for pgsql-hackers@arkaria.postgresql.org; Tue, 15 May 2018 21:55:57 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA384:256) (Exim 4.89) (envelope-from ) id 1fIhvJ-0005bN-NJ for pgsql-hackers@lists.postgresql.org; Tue, 15 May 2018 21:55:57 +0000 Received: from sss.pgh.pa.us ([66.207.139.130]) by magus.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA384:256) (Exim 4.89) (envelope-from ) id 1fIhvB-0006KN-Cm for pgsql-hackers@postgresql.org; Tue, 15 May 2018 21:55:57 +0000 Received: from sss1.sss.pgh.pa.us (localhost [127.0.0.1]) by sss.pgh.pa.us (8.14.4/8.14.4) with ESMTP id w4FLtcVq010899; Tue, 15 May 2018 17:55:38 -0400 From: Tom Lane To: David Rowley cc: Bruce Momjian , =?UTF-8?B?xJDhurduZyBNaW5oIEjGsOG7m25n?= , PostgreSQL-development Subject: NaNs in numeric_power (was Re: Postgres 11 release notes) In-reply-to: References: <20180511150852.GA18510@momjian.us> <20180514202850.GE5217@momjian.us> <18049.1526392887@sss.pgh.pa.us> Comments: In-reply-to David Rowley message dated "Wed, 16 May 2018 07:04:56 +1200" MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="----- =_aaaaaaaaaa0" Content-ID: <10826.1526421252.0@sss.pgh.pa.us> Date: Tue, 15 May 2018 17:55:38 -0400 Message-ID: <10898.1526421338@sss.pgh.pa.us> List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Precedence: bulk ------- =_aaaaaaaaaa0 Content-Type: text/plain; charset="us-ascii" Content-ID: <10826.1526421252.1@sss.pgh.pa.us> David Rowley writes: > On 16 May 2018 at 02:01, Tom Lane wrote: >> I'm not particularly fussed about getting credit for that. However, >> looking again at how that patch series turned out --- ie, that >> we ensured POSIX behavior for NaNs only in HEAD --- I wonder >> whether we shouldn't do what was mentioned in the commit log for >> 6bdf1303, and teach numeric_pow() about these same special cases. >> It seems like it would be more consistent to change both functions >> for v11, rather than letting that other shoe drop in some future >> major release. > I'm inclined to agree. It's hard to imagine these two functions > behaving differently in regards to NaN input is useful to anyone. Here's a proposed patch for that. regards, tom lane ------- =_aaaaaaaaaa0 Content-Type: text/x-diff; name="make-numeric_power-handle-NaNs-per-POSIX.patch"; charset="us-ascii" Content-ID: <10826.1526421252.2@sss.pgh.pa.us> Content-Description: make-numeric_power-handle-NaNs-per-POSIX.patch Content-Transfer-Encoding: quoted-printable diff --git a/src/backend/utils/adt/numeric.c b/src/backend/utils/adt/numer= ic.c index dcf31e3..8dfdffc 100644 *** a/src/backend/utils/adt/numeric.c --- b/src/backend/utils/adt/numeric.c *************** numeric_power(PG_FUNCTION_ARGS) *** 2972,2981 **** NumericVar result; = /* ! * Handle NaN */ ! if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2)) PG_RETURN_NUMERIC(make_result(&const_nan)); = /* * Initialize things --- 2972,2998 ---- NumericVar result; = /* ! * Handle NaN cases. We follow the POSIX spec for pow(3), which says t= hat ! * NaN ^ 0 =3D 1, and 1 ^ NaN =3D 1, while all other cases with NaN inp= uts ! * yield NaN (with no error). */ ! if (NUMERIC_IS_NAN(num1)) ! { ! if (!NUMERIC_IS_NAN(num2)) ! { ! init_var_from_num(num2, &arg2); ! if (cmp_var(&arg2, &const_zero) =3D=3D 0) ! PG_RETURN_NUMERIC(make_result(&const_one)); ! } ! PG_RETURN_NUMERIC(make_result(&const_nan)); ! } ! if (NUMERIC_IS_NAN(num2)) ! { ! init_var_from_num(num1, &arg1); ! if (cmp_var(&arg1, &const_one) =3D=3D 0) ! PG_RETURN_NUMERIC(make_result(&const_one)); PG_RETURN_NUMERIC(make_result(&const_nan)); + } = /* * Initialize things diff --git a/src/test/regress/expected/numeric.out b/src/test/regress/expe= cted/numeric.out index 17985e8..1cb3c3b 100644 *** a/src/test/regress/expected/numeric.out --- b/src/test/regress/expected/numeric.out *************** select 0.0 ^ 12.34; *** 1664,1669 **** --- 1664,1700 ---- 0.0000000000000000 (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 select 0.0 ^ (-12.34); ERROR: zero raised to a negative power is undefined diff --git a/src/test/regress/sql/numeric.sql b/src/test/regress/sql/numer= ic.sql index d77504e..a939412 100644 *** a/src/test/regress/sql/numeric.sql --- b/src/test/regress/sql/numeric.sql *************** select (-12.34) ^ 0.0; *** 911,916 **** --- 911,923 ---- select 12.34 ^ 0.0; 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 select 0.0 ^ (-12.34); select (-12.34) ^ 1.2; ------- =_aaaaaaaaaa0--