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);