From 6b4e9d16547760ad7132c138b6c76bca96d135cc Mon Sep 17 00:00:00 2001 From: Bruce Momjian Date: Thu, 8 May 2008 19:25:38 +0000 Subject: [PATCH] Have numeric 0 ^ 4.3 return 1, rather than an error, and have 0 ^ 0.0 return 1, rather than error. This was already the float8 behavior. --- src/backend/utils/adt/numeric.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/src/backend/utils/adt/numeric.c b/src/backend/utils/adt/numeric.c index c5801ade2a..defdc623cd 100644 --- a/src/backend/utils/adt/numeric.c +++ b/src/backend/utils/adt/numeric.c @@ -14,7 +14,7 @@ * Copyright (c) 1998-2008, PostgreSQL Global Development Group * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/adt/numeric.c,v 1.110 2008/04/21 00:26:45 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/numeric.c,v 1.111 2008/05/08 19:25:38 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -5170,6 +5170,21 @@ power_var(NumericVar *base, NumericVar *exp, NumericVar *result) 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) { @@ -5266,15 +5281,9 @@ power_var_int(NumericVar *base, int exp, NumericVar *result, int rscale) NumericVar base_prod; int local_rscale; - /* Detect some special cases, particularly 0^0. */ - switch (exp) { case 0: - if (base->ndigits == 0) - ereport(ERROR, - (errcode(ERRCODE_FLOATING_POINT_EXCEPTION), - errmsg("zero raised to zero is undefined"))); set_var_from_var(&const_one, result); result->dscale = rscale; /* no need to round */ return;