Re: pgsql: Have numeric 0 ^ 4.3 return 1, rather than an error, and have 0 ^ - Mailing list pgsql-committers

From Bruce Momjian
Subject Re: pgsql: Have numeric 0 ^ 4.3 return 1, rather than an error, and have 0 ^
Date
Msg-id 200805082218.m48MI0E19032@momjian.us
Whole thread Raw
In response to Re: pgsql: Have numeric 0 ^ 4.3 return 1, rather than an error, and have 0 ^  (Neil Conway <neilc@samurai.com>)
List pgsql-committers
Neil Conway wrote:
> On Thu, 2008-05-08 at 19:25 +0000, Bruce Momjian wrote:
> > Have numeric 0 ^ 4.3 return 1, rather than an error, and have 0 ^ 0.0
> > return 1, rather than error.
>
> A regression test for this behavior would be useful, I think.

Done, plus I wasn't happy with the original patch so I redid it to be
more modular, also attached.

--
  Bruce Momjian  <bruce@momjian.us>        http://momjian.us
  EnterpriseDB                             http://enterprisedb.com

  + If your life is a hard drive, Christ can be your backup. +
Index: src/backend/utils/adt/numeric.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/utils/adt/numeric.c,v
retrieving revision 1.111
diff -c -c -r1.111 numeric.c
*** src/backend/utils/adt/numeric.c    8 May 2008 19:25:38 -0000    1.111
--- src/backend/utils/adt/numeric.c    8 May 2008 22:16:55 -0000
***************
*** 5170,5190 ****
      int            local_rscale;
      double        val;

-     /*
-      *    This avoids log(0) for cases of 0 raised to a non-integer.
-      *    Also, while 0 ^ 0 can be either 1 or indeterminate (error), we
-      *    treat it as one because most programming languages do this.
-      *    http://en.wikipedia.org/wiki/Exponentiation#Zero_to_the_zero_power
-      */
-     if (cmp_var(base, &const_zero) == 0)
-     {
-         if (cmp_var(exp, &const_zero) == 0)
-             set_var_from_var(&const_one, result);
-         else
-             set_var_from_var(&const_zero, result);
-         return;
-     }
-
      /* If exp can be represented as an integer, use power_var_int */
      if (exp->ndigits == 0 || exp->ndigits <= exp->weight + 1)
      {
--- 5170,5175 ----
***************
*** 5217,5222 ****
--- 5202,5218 ----
          free_var(&x);
      }

+     /*
+      *    This avoids log(0) for cases of 0 raised to a non-integer.
+      *    0 ^ 0 handled by power_var_int().
+      */
+     if (cmp_var(base, &const_zero) == 0)
+     {
+         set_var_from_var(&const_zero, result);
+         result->dscale = NUMERIC_MIN_SIG_DIGITS;    /* no need to round */
+         return;
+     }
+
      init_var(&ln_base);
      init_var(&ln_num);

***************
*** 5284,5289 ****
--- 5280,5290 ----
      switch (exp)
      {
          case 0:
+             /*
+              *    While 0 ^ 0 can be either 1 or indeterminate (error), we
+              *    treat it as 1 because most programming languages do this.
+              *    http://en.wikipedia.org/wiki/Exponentiation#Zero_to_the_zero_power
+              */
              set_var_from_var(&const_one, result);
              result->dscale = rscale;    /* no need to round */
              return;
Index: src/test/regress/expected/float8.out
===================================================================
RCS file: /cvsroot/pgsql/src/test/regress/expected/float8.out,v
retrieving revision 1.25
diff -c -c -r1.25 float8.out
*** src/test/regress/expected/float8.out    2 Jan 2007 20:00:50 -0000    1.25
--- src/test/regress/expected/float8.out    8 May 2008 22:16:56 -0000
***************
*** 349,354 ****
--- 349,360 ----
  ERROR:  value out of range: overflow
  SELECT '' AS bad, f.f1 ^ '1e200' from FLOAT8_TBL f;
  ERROR:  value out of range: overflow
+ SELECT 0 ^ 0 + 0 ^ 1 + 0 ^ 0.0 + 0 ^ 0.5;
+  ?column?
+ ----------
+         2
+ (1 row)
+
  SELECT '' AS bad, ln(f.f1) from FLOAT8_TBL f where f.f1 = '0.0' ;
  ERROR:  cannot take logarithm of zero
  SELECT '' AS bad, ln(f.f1) from FLOAT8_TBL f where f.f1 < '0.0' ;
Index: src/test/regress/sql/float8.sql
===================================================================
RCS file: /cvsroot/pgsql/src/test/regress/sql/float8.sql,v
retrieving revision 1.15
diff -c -c -r1.15 float8.sql
*** src/test/regress/sql/float8.sql    8 Jun 2005 21:15:29 -0000    1.15
--- src/test/regress/sql/float8.sql    8 May 2008 22:16:56 -0000
***************
*** 129,134 ****
--- 129,136 ----

  SELECT '' AS bad, f.f1 ^ '1e200' from FLOAT8_TBL f;

+ SELECT 0 ^ 0 + 0 ^ 1 + 0 ^ 0.0 + 0 ^ 0.5;
+
  SELECT '' AS bad, ln(f.f1) from FLOAT8_TBL f where f.f1 = '0.0' ;

  SELECT '' AS bad, ln(f.f1) from FLOAT8_TBL f where f.f1 < '0.0' ;

pgsql-committers by date:

Previous
From: momjian@postgresql.org (Bruce Momjian)
Date:
Subject: pgsql: Add regression test for various power expressions with a zero
Next
From: Tom Lane
Date:
Subject: Re: pgsql: Have numeric 0 ^ 4.3 return 1, rather than an error, and have 0 ^