On Mon, 13 Sept 2021 at 17:51, Alvaro Herrera <alvhe...@alvh.no-ip.org> wrote:
>
> I came here just to opine that there should be a comment about there not
> being a clamp to the maximum scale.  For example, log_var says "Set the
> scales .. so that they each have more digits ..." which seems clear
> enough; I think the new comment is a bit on the short side.
>

OK, that's a fair point. Updated version attached.

> I couldn't get bc (version 1.07.1) to output the result; it says
>
> Runtime warning (func=(main), adr=47): non-zero scale in exponent
> Runtime error (func=(main), adr=47): exponent too large in raise
>

Ah yes, bc's "^" operator is a bit limited. It doesn't support
fractional powers for example, and evidently doesn't like powers that
large. I'm so used to not using it that I didn't notice - I always
just use exp() and ln() in bc to compute powers:

scale=2000
e(l(1 - 1.500012345678*10^-1000) * 1.45*10^1003) * 10^1000

Regards,
Dean
diff --git a/src/backend/utils/adt/numeric.c b/src/backend/utils/adt/numeric.c
new file mode 100644
index 796f517..1de7448
--- a/src/backend/utils/adt/numeric.c
+++ b/src/backend/utils/adt/numeric.c
@@ -10266,9 +10266,13 @@ power_var(const NumericVar *base, const
 	 */
 	ln_dweight = estimate_ln_dweight(base);
 
+	/*
+	 * Set the scale for the low-precision calculation, computing ln(base) to
+	 * around 8 significant digits.  Note that ln_dweight may be as small as
+	 * -SHRT_MAX, so the scale may exceed NUMERIC_MAX_DISPLAY_SCALE here.
+	 */
 	local_rscale = 8 - ln_dweight;
 	local_rscale = Max(local_rscale, NUMERIC_MIN_DISPLAY_SCALE);
-	local_rscale = Min(local_rscale, NUMERIC_MAX_DISPLAY_SCALE);
 
 	ln_var(base, &ln_base, local_rscale);
 
diff --git a/src/test/regress/expected/numeric.out b/src/test/regress/expected/numeric.out
new file mode 100644
index efbb22a..e224eff
--- a/src/test/regress/expected/numeric.out
+++ b/src/test/regress/expected/numeric.out
@@ -2483,6 +2483,12 @@ select coalesce(nullif(0.9999999999 ^ 23
               0
 (1 row)
 
+select round(((1 - 1.500012345678e-1000) ^ 1.45e1003) * 1e1000);
+                          round                           
+----------------------------------------------------------
+ 25218976308958387188077465658068501556514992509509282366
+(1 row)
+
 -- cases that used to error out
 select 0.12 ^ (-25);
                  ?column?                  
diff --git a/src/test/regress/sql/numeric.sql b/src/test/regress/sql/numeric.sql
new file mode 100644
index 0418ff0..eeca63d
--- a/src/test/regress/sql/numeric.sql
+++ b/src/test/regress/sql/numeric.sql
@@ -1148,6 +1148,7 @@ select 1.2 ^ 345;
 select 0.12 ^ (-20);
 select 1.000000000123 ^ (-2147483648);
 select coalesce(nullif(0.9999999999 ^ 23300000000000, 0), 0) as rounds_to_zero;
+select round(((1 - 1.500012345678e-1000) ^ 1.45e1003) * 1e1000);
 
 -- cases that used to error out
 select 0.12 ^ (-25);

Reply via email to