Improve the accuracy of numeric power() for integer exponents.
authorDean Rasheed <dean.a.rasheed@gmail.com>
Thu, 20 Oct 2022 09:10:17 +0000 (10:10 +0100)
committerDean Rasheed <dean.a.rasheed@gmail.com>
Thu, 20 Oct 2022 09:10:17 +0000 (10:10 +0100)
This makes the choice of result scale of numeric power() for integer
exponents consistent with the choice for non-integer exponents, and
with the result scale of other numeric functions. Specifically, the
result scale will be at least as large as the scale of either input,
and sufficient to ensure that the result has at least 16 significant
digits.

Formerly, the result scale was based only on the scale of the first
input, without taking into account the weight of the result. For
results with negative weight, that could lead to results with very few
or even no non-zero significant digits (e.g., 10.0 ^ (-18) produced
0.0000000000000000).

Fix this by moving responsibility for the choice of result scale into
power_var_int(), which already has code to estimate the result weight.

Per report by Adrian Klaver and suggested fix by Tom Lane.

No back-patch -- arguably this is a bug fix, but one which is easy to
work around, so it doesn't seem worth the risk of changing query
results in stable branches.

Discussion: https://postgr.es/m/12a40226-70ac-3a3b-3d3a-fdaf9e32d312%40aklaver.com

src/backend/utils/adt/numeric.c
src/test/regress/expected/numeric.out
src/test/regress/expected/numeric_big.out
src/test/regress/sql/numeric.sql
src/test/regress/sql/numeric_big.sql

index cafe1ac47b04f5d27ce69f9b26708a3de112ed6b..7f0e93aa803dda8a298391b81d3d226f49bdc9b0 100644 (file)
@@ -571,8 +571,8 @@ static void log_var(const NumericVar *base, const NumericVar *num,
                    NumericVar *result);
 static void power_var(const NumericVar *base, const NumericVar *exp,
                      NumericVar *result);
-static void power_var_int(const NumericVar *base, int exp, NumericVar *result,
-                         int rscale);
+static void power_var_int(const NumericVar *base, int exp, int exp_dscale,
+                         NumericVar *result);
 static void power_ten_int(int exp, NumericVar *result);
 
 static int cmp_abs(const NumericVar *var1, const NumericVar *var2);
@@ -10335,13 +10335,8 @@ power_var(const NumericVar *base, const NumericVar *exp, NumericVar *result)
        {
            if (expval64 >= PG_INT32_MIN && expval64 <= PG_INT32_MAX)
            {
-               /* Okay, select rscale */
-               rscale = NUMERIC_MIN_SIG_DIGITS;
-               rscale = Max(rscale, base->dscale);
-               rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
-               rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
-
-               power_var_int(base, (int) expval64, result, rscale);
+               /* Okay, use power_var_int */
+               power_var_int(base, (int) expval64, exp->dscale, result);
                return;
            }
        }
@@ -10475,19 +10470,76 @@ power_var(const NumericVar *base, const NumericVar *exp, NumericVar *result)
  * power_var_int() -
  *
  * Raise base to the power of exp, where exp is an integer.
+ *
+ * Note: this routine chooses dscale of the result.
  */
 static void
-power_var_int(const NumericVar *base, int exp, NumericVar *result, int rscale)
+power_var_int(const NumericVar *base, int exp, int exp_dscale,
+             NumericVar *result)
 {
    double      f;
    int         p;
    int         i;
+   int         rscale;
    int         sig_digits;
    unsigned int mask;
    bool        neg;
    NumericVar  base_prod;
    int         local_rscale;
 
+   /*
+    * Choose the result scale.  For this we need an estimate of the decimal
+    * weight of the result, which we obtain by approximating using double
+    * precision arithmetic.
+    *
+    * We also perform crude overflow/underflow tests here so that we can exit
+    * early if the result is sure to overflow/underflow, and to guard against
+    * integer overflow when choosing the result scale.
+    */
+   if (base->ndigits != 0)
+   {
+       /*----------
+        * Choose f (double) and p (int) such that base ~= f * 10^p.
+        * Then log10(result) = log10(base^exp) ~= exp * (log10(f) + p).
+        *----------
+        */
+       f = base->digits[0];
+       p = base->weight * DEC_DIGITS;
+
+       for (i = 1; i < base->ndigits && i * DEC_DIGITS < 16; i++)
+       {
+           f = f * NBASE + base->digits[i];
+           p -= DEC_DIGITS;
+       }
+
+       f = exp * (log10(f) + p);   /* approximate decimal result weight */
+   }
+   else
+       f = 0;                  /* result is 0 or 1 (weight 0), or error */
+
+   /* overflow/underflow tests with fuzz factors */
+   if (f > (SHRT_MAX + 1) * DEC_DIGITS)
+       ereport(ERROR,
+               (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
+                errmsg("value overflows numeric format")));
+   if (f + 1 < -NUMERIC_MAX_DISPLAY_SCALE)
+   {
+       zero_var(result);
+       result->dscale = NUMERIC_MAX_DISPLAY_SCALE;
+       return;
+   }
+
+   /*
+    * Choose the result scale in the same way as power_var(), so it has at
+    * least NUMERIC_MIN_SIG_DIGITS significant digits and is not less than
+    * either input's display scale.
+    */
+   rscale = NUMERIC_MIN_SIG_DIGITS - (int) f;
+   rscale = Max(rscale, base->dscale);
+   rscale = Max(rscale, exp_dscale);
+   rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
+   rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
+
    /* Handle some common special cases, as well as corner cases */
    switch (exp)
    {
@@ -10532,43 +10584,15 @@ power_var_int(const NumericVar *base, int exp, NumericVar *result, int rscale)
     * The general case repeatedly multiplies base according to the bit
     * pattern of exp.
     *
-    * First we need to estimate the weight of the result so that we know how
-    * many significant digits are needed.
+    * The local rscale used for each multiplication is varied to keep a fixed
+    * number of significant digits, sufficient to give the required result
+    * scale.
     */
-   f = base->digits[0];
-   p = base->weight * DEC_DIGITS;
-
-   for (i = 1; i < base->ndigits && i * DEC_DIGITS < 16; i++)
-   {
-       f = f * NBASE + base->digits[i];
-       p -= DEC_DIGITS;
-   }
-
-   /*----------
-    * We have base ~= f * 10^p
-    * so log10(result) = log10(base^exp) ~= exp * (log10(f) + p)
-    *----------
-    */
-   f = exp * (log10(f) + p);
-
-   /*
-    * Apply crude overflow/underflow tests so we can exit early if the result
-    * certainly will overflow/underflow.
-    */
-   if (f > 3 * SHRT_MAX * DEC_DIGITS)
-       ereport(ERROR,
-               (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
-                errmsg("value overflows numeric format")));
-   if (f + 1 < -rscale || f + 1 < -NUMERIC_MAX_DISPLAY_SCALE)
-   {
-       zero_var(result);
-       result->dscale = rscale;
-       return;
-   }
 
    /*
     * Approximate number of significant digits in the result.  Note that the
-    * underflow test above means that this is necessarily >= 0.
+    * underflow test above, together with the choice of rscale, ensures that
+    * this approximation is necessarily > 0.
     */
    sig_digits = 1 + rscale + (int) f;
 
index e224eff9f06f5c77a2d5abf1c53bafca930d3c70..3c610646dc5a258e071abd55e42937fcf3afd589 100644 (file)
@@ -952,44 +952,44 @@ WITH v(x) AS
 SELECT x1, x2,
   power(x1, x2)
 FROM v AS v1(x1), v AS v2(x2) WHERE x1 != 0 OR x2 >= 0;
-    x1    |    x2    |        power        
-----------+----------+---------------------
-        0 |        0 |  1.0000000000000000
-        0 |        1 |  0.0000000000000000
-        0 |        2 |  0.0000000000000000
-        0 |      4.2 |  0.0000000000000000
-        0 | Infinity |                   0
-        0 |      NaN |                 NaN
-        1 |        0 |  1.0000000000000000
-        1 |        1 |  1.0000000000000000
-        1 |        2 |  1.0000000000000000
-        1 |      4.2 |  1.0000000000000000
-        1 | Infinity |                   1
-        1 |      NaN |                   1
-        2 |        0 |  1.0000000000000000
-        2 |        1 |  2.0000000000000000
-        2 |        2 |  4.0000000000000000
-        2 |      4.2 |  18.379173679952560
-        2 | Infinity |            Infinity
-        2 |      NaN |                 NaN
-      4.2 |        0 |  1.0000000000000000
-      4.2 |        1 |  4.2000000000000000
-      4.2 |        2 | 17.6400000000000000
-      4.2 |      4.2 |  414.61691860129675
-      4.2 | Infinity |            Infinity
-      4.2 |      NaN |                 NaN
- Infinity |        0 |                   1
- Infinity |        1 |            Infinity
- Infinity |        2 |            Infinity
- Infinity |      4.2 |            Infinity
- Infinity | Infinity |            Infinity
- Infinity |      NaN |                 NaN
-      NaN |        0 |                   1
-      NaN |        1 |                 NaN
-      NaN |        2 |                 NaN
-      NaN |      4.2 |                 NaN
-      NaN | Infinity |                 NaN
-      NaN |      NaN |                 NaN
+    x1    |    x2    |       power        
+----------+----------+--------------------
+        0 |        0 | 1.0000000000000000
+        0 |        1 | 0.0000000000000000
+        0 |        2 | 0.0000000000000000
+        0 |      4.2 | 0.0000000000000000
+        0 | Infinity |                  0
+        0 |      NaN |                NaN
+        1 |        0 | 1.0000000000000000
+        1 |        1 | 1.0000000000000000
+        1 |        2 | 1.0000000000000000
+        1 |      4.2 | 1.0000000000000000
+        1 | Infinity |                  1
+        1 |      NaN |                  1
+        2 |        0 | 1.0000000000000000
+        2 |        1 | 2.0000000000000000
+        2 |        2 | 4.0000000000000000
+        2 |      4.2 | 18.379173679952560
+        2 | Infinity |           Infinity
+        2 |      NaN |                NaN
+      4.2 |        0 | 1.0000000000000000
+      4.2 |        1 | 4.2000000000000000
+      4.2 |        2 | 17.640000000000000
+      4.2 |      4.2 | 414.61691860129675
+      4.2 | Infinity |           Infinity
+      4.2 |      NaN |                NaN
+ Infinity |        0 |                  1
+ Infinity |        1 |           Infinity
+ Infinity |        2 |           Infinity
+ Infinity |      4.2 |           Infinity
+ Infinity | Infinity |           Infinity
+ Infinity |      NaN |                NaN
+      NaN |        0 |                  1
+      NaN |        1 |                NaN
+      NaN |        2 |                NaN
+      NaN |      4.2 |                NaN
+      NaN | Infinity |                NaN
+      NaN |      NaN |                NaN
 (36 rows)
 
 SELECT power('0'::numeric, '-1');
@@ -2431,15 +2431,15 @@ select sqrt(8015491789940783531003294973900307::numeric);
 -- Test code path for raising to integer powers
 --
 select 10.0 ^ -2147483648 as rounds_to_zero;
-   rounds_to_zero   
---------------------
- 0.0000000000000000
+                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               rounds_to_zero                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               
+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ 0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
 (1 row)
 
 select 10.0 ^ -2147483647 as rounds_to_zero;
-   rounds_to_zero   
---------------------
- 0.0000000000000000
+                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               rounds_to_zero                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               
+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ 0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
 (1 row)
 
 select 10.0 ^ 2147483647 as overflows;
@@ -2447,28 +2447,28 @@ ERROR:  value overflows numeric format
 select 117743296169.0 ^ 1000000000 as overflows;
 ERROR:  value overflows numeric format
 -- cases that used to return inaccurate results
-select 3.789 ^ 21;
+select 3.789 ^ 21.0000000000000000;
             ?column?            
 --------------------------------
  1409343026052.8716016316022141
 (1 row)
 
-select 3.789 ^ 35;
+select 3.789 ^ 35.0000000000000000;
                 ?column?                
 ----------------------------------------
  177158169650516670809.3820586142670135
 (1 row)
 
 select 1.2 ^ 345;
-                   ?column?                    
------------------------------------------------
- 2077446682327378559843444695.5827049735727869
+            ?column?            
+--------------------------------
+ 2077446682327378559843444695.6
 (1 row)
 
 select 0.12 ^ (-20);
-               ?column?               
---------------------------------------
- 2608405330458882702.5529619561355838
+        ?column?        
+------------------------
+ 2608405330458882702.55
 (1 row)
 
 select 1.000000000123 ^ (-2147483648);
@@ -2491,15 +2491,15 @@ select round(((1 - 1.500012345678e-1000) ^ 1.45e1003) * 1e1000);
 
 -- cases that used to error out
 select 0.12 ^ (-25);
-                 ?column?                  
--------------------------------------------
- 104825960103961013959336.4983657883169110
+          ?column?           
+-----------------------------
+ 104825960103961013959336.50
 (1 row)
 
 select 0.5678 ^ (-85);
-                ?column?                
-----------------------------------------
- 782333637740774446257.7719390061997396
+          ?column?          
+----------------------------
+ 782333637740774446257.7719
 (1 row)
 
 select coalesce(nullif(0.9999999999 ^ 70000000000000, 0), 0) as underflows;
@@ -2539,6 +2539,54 @@ select (-1.0) ^ 1000000000000001;
  -1.0000000000000000
 (1 row)
 
+-- integer powers of 10
+select n, 10.0 ^ n as "10^n", (10.0 ^ n) * (10.0 ^ (-n)) = 1 as ok
+from generate_series(-20, 20) n;
+  n  |                  10^n                  | ok 
+-----+----------------------------------------+----
+ -20 | 0.000000000000000000010000000000000000 | t
+ -19 |  0.00000000000000000010000000000000000 | t
+ -18 |   0.0000000000000000010000000000000000 | t
+ -17 |    0.000000000000000010000000000000000 | t
+ -16 |     0.00000000000000010000000000000000 | t
+ -15 |      0.0000000000000010000000000000000 | t
+ -14 |       0.000000000000010000000000000000 | t
+ -13 |        0.00000000000010000000000000000 | t
+ -12 |         0.0000000000010000000000000000 | t
+ -11 |          0.000000000010000000000000000 | t
+ -10 |           0.00000000010000000000000000 | t
+  -9 |            0.0000000010000000000000000 | t
+  -8 |             0.000000010000000000000000 | t
+  -7 |              0.00000010000000000000000 | t
+  -6 |               0.0000010000000000000000 | t
+  -5 |                0.000010000000000000000 | t
+  -4 |                 0.00010000000000000000 | t
+  -3 |                  0.0010000000000000000 | t
+  -2 |                   0.010000000000000000 | t
+  -1 |                    0.10000000000000000 | t
+   0 |                     1.0000000000000000 | t
+   1 |                     10.000000000000000 | t
+   2 |                     100.00000000000000 | t
+   3 |                     1000.0000000000000 | t
+   4 |                     10000.000000000000 | t
+   5 |                     100000.00000000000 | t
+   6 |                     1000000.0000000000 | t
+   7 |                     10000000.000000000 | t
+   8 |                     100000000.00000000 | t
+   9 |                     1000000000.0000000 | t
+  10 |                     10000000000.000000 | t
+  11 |                     100000000000.00000 | t
+  12 |                     1000000000000.0000 | t
+  13 |                     10000000000000.000 | t
+  14 |                     100000000000000.00 | t
+  15 |                     1000000000000000.0 | t
+  16 |                    10000000000000000.0 | t
+  17 |                   100000000000000000.0 | t
+  18 |                  1000000000000000000.0 | t
+  19 |                 10000000000000000000.0 | t
+  20 |                100000000000000000000.0 | t
+(41 rows)
+
 --
 -- Tests for raising to non-integer powers
 --
@@ -2630,9 +2678,9 @@ select 12.3 ^ (-45.6);
 
 -- big test
 select 1.234 ^ 5678;
-                                                                                                                                                                                                                                                                         ?column?                                                                                                                                                                                                                                                                         
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
- 307239295662090741644584872593956173493568238595074141254349565406661439636598896798876823220904084953233015553994854875890890858118656468658643918169805277399402542281777901029346337707622181574346585989613344285010764501017625366742865066948856161360224801370482171458030533346309750557140549621313515752078638620714732831815297168231790779296290266207315344008883935010274044001522606235576584215999260117523114297033944018699691024106823438431754073086813382242140602291215149759520833200152654884259619588924545324.5973362312547382
+                                                                                                                                                                                                                                                                  ?column?                                                                                                                                                                                                                                                                   
+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ 307239295662090741644584872593956173493568238595074141254349565406661439636598896798876823220904084953233015553994854875890890858118656468658643918169805277399402542281777901029346337707622181574346585989613344285010764501017625366742865066948856161360224801370482171458030533346309750557140549621313515752078638620714732831815297168231790779296290266207315344008883935010274044001522606235576584215999260117523114297033944018699691024106823438431754073086813382242140602291215149759520833200152654884259619588924545324.597
 (1 row)
 
 --
index 468c6026bcde85a70db6683a94467ed94e6e83bf..12ff35b583cc6d90b8f72836751908dd49449248 100644 (file)
@@ -686,91 +686,91 @@ SELECT t1.id1, t1.result, t2.expected
 --   echo "($b, $p, $r),"
 -- done
 WITH t(b, p, bc_result) AS (VALUES
-(0.084738, -20, 2744326694304960114888.7859130502035257),
-(0.084738, -19, 232548755422013710215.4459407000481464),
-(0.084738, -18, 19705716436950597776.2364581230406798),
-(0.084738, -17, 1669822999434319754.3627249884302211),
-(0.084738, -16, 141497461326065387.3451885900696001),
-(0.084738, -15, 11990211877848128.7928565907453178),
-(0.084738, -14, 1016026574105094.7376490817865767),
-(0.084738, -13, 86096059836517.5178789078924309),
-(0.084738, -12, 7295607918426.8214300228969888),
-(0.084738, -11, 618215223791.6519943372802450),
-(0.084738, -10, 52386321633.6570066961524534),
-(0.084738, -9, 4439112122.5928274334185666),
-(0.084738, -8, 376161483.0442710110530225),
-(0.084738, -7, 31875171.7502054369346110),
-(0.084738, -6, 2701038.3037689083149651),
-(0.084738, -5, 228880.5837847697527935),
-(0.084738, -4, 19394.8829087538193122),
-(0.084738, -3, 1643.4835879219811409),
-(0.084738, -2, 139.2655122733328379),
-(0.084738, -1, 11.8010809790176780),
+(0.084738, -20, 2744326694304960114888.785913),
+(0.084738, -19, 232548755422013710215.445941),
+(0.084738, -18, 19705716436950597776.236458),
+(0.084738, -17, 1669822999434319754.362725),
+(0.084738, -16, 141497461326065387.345189),
+(0.084738, -15, 11990211877848128.792857),
+(0.084738, -14, 1016026574105094.737649),
+(0.084738, -13, 86096059836517.517879),
+(0.084738, -12, 7295607918426.821430),
+(0.084738, -11, 618215223791.651994),
+(0.084738, -10, 52386321633.657007),
+(0.084738, -9, 4439112122.5928274),
+(0.084738, -8, 376161483.04427101),
+(0.084738, -7, 31875171.750205437),
+(0.084738, -6, 2701038.3037689083),
+(0.084738, -5, 228880.58378476975),
+(0.084738, -4, 19394.882908753819),
+(0.084738, -3, 1643.4835879219811),
+(0.084738, -2, 139.26551227333284),
+(0.084738, -1, 11.801080979017678),
 (0.084738, 0, 1),
 (0.084738, 1, .084738),
 (0.084738, 2, .007180528644),
-(0.084738, 3, .0006084636362353),
-(0.084738, 4, .0000515599916073),
-(0.084738, 5, .0000043690905688),
-(0.084738, 6, .0000003702279966),
-(0.084738, 7, .0000000313723800),
-(0.084738, 8, .0000000026584327),
-(0.084738, 9, .0000000002252703),
-(0.084738, 10, .0000000000190890),
-(0.084738, 11, .0000000000016176),
-(0.084738, 12, .0000000000001371),
-(0.084738, 13, .0000000000000116),
-(0.084738, 14, .0000000000000010),
-(0.084738, 15, .0000000000000001),
-(0.084738, 16, .0000000000000000),
-(0.084738, 17, .0000000000000000),
-(0.084738, 18, .0000000000000000),
-(0.084738, 19, .0000000000000000),
-(0.084738, 20, .0000000000000000))
+(0.084738, 3, .000608463636235272),
+(0.084738, 4, .00005155999160730448),
+(0.084738, 5, .000004369090568819767),
+(0.084738, 6, .0000003702279966206494),
+(0.084738, 7, .00000003137237997764059),
+(0.084738, 8, .000000002658432734545308),
+(0.084738, 9, .0000000002252702730599003),
+(0.084738, 10, .00000000001908895239854983),
+(0.084738, 11, .000000000001617559648348316),
+(0.084738, 12, .0000000000001370687694817396),
+(0.084738, 13, .00000000000001161493338834365),
+(0.084738, 14, .0000000000000009842262254614642),
+(0.084738, 15, .00000000000000008340136189315355),
+(0.084738, 16, .000000000000000007067264604102046),
+(0.084738, 17, .0000000000000000005988658680223991),
+(0.084738, 18, .00000000000000000005074669592448206),
+(0.084738, 19, .000000000000000000004300173519248761),
+(0.084738, 20, .0000000000000000000003643881036741015))
 SELECT b, p, bc_result, b^p AS power, b^p - bc_result AS diff FROM t;
-    b     |  p  |                bc_result                |                  power                  |        diff        
-----------+-----+-----------------------------------------+-----------------------------------------+--------------------
- 0.084738 | -20 | 2744326694304960114888.7859130502035257 | 2744326694304960114888.7859130502035257 | 0.0000000000000000
- 0.084738 | -19 |  232548755422013710215.4459407000481464 |  232548755422013710215.4459407000481464 | 0.0000000000000000
- 0.084738 | -18 |   19705716436950597776.2364581230406798 |   19705716436950597776.2364581230406798 | 0.0000000000000000
- 0.084738 | -17 |    1669822999434319754.3627249884302211 |    1669822999434319754.3627249884302211 | 0.0000000000000000
- 0.084738 | -16 |     141497461326065387.3451885900696001 |     141497461326065387.3451885900696001 | 0.0000000000000000
- 0.084738 | -15 |      11990211877848128.7928565907453178 |      11990211877848128.7928565907453178 | 0.0000000000000000
- 0.084738 | -14 |       1016026574105094.7376490817865767 |       1016026574105094.7376490817865767 | 0.0000000000000000
- 0.084738 | -13 |         86096059836517.5178789078924309 |         86096059836517.5178789078924309 | 0.0000000000000000
- 0.084738 | -12 |          7295607918426.8214300228969888 |          7295607918426.8214300228969888 | 0.0000000000000000
- 0.084738 | -11 |           618215223791.6519943372802450 |           618215223791.6519943372802450 | 0.0000000000000000
- 0.084738 | -10 |            52386321633.6570066961524534 |            52386321633.6570066961524534 | 0.0000000000000000
- 0.084738 |  -9 |             4439112122.5928274334185666 |             4439112122.5928274334185666 | 0.0000000000000000
- 0.084738 |  -8 |              376161483.0442710110530225 |              376161483.0442710110530225 | 0.0000000000000000
- 0.084738 |  -7 |               31875171.7502054369346110 |               31875171.7502054369346110 | 0.0000000000000000
- 0.084738 |  -6 |                2701038.3037689083149651 |                2701038.3037689083149651 | 0.0000000000000000
- 0.084738 |  -5 |                 228880.5837847697527935 |                 228880.5837847697527935 | 0.0000000000000000
- 0.084738 |  -4 |                  19394.8829087538193122 |                  19394.8829087538193122 | 0.0000000000000000
- 0.084738 |  -3 |                   1643.4835879219811409 |                   1643.4835879219811409 | 0.0000000000000000
- 0.084738 |  -2 |                    139.2655122733328379 |                    139.2655122733328379 | 0.0000000000000000
- 0.084738 |  -1 |                     11.8010809790176780 |                     11.8010809790176780 | 0.0000000000000000
- 0.084738 |   0 |                                       1 |                      1.0000000000000000 | 0.0000000000000000
- 0.084738 |   1 |                                0.084738 |                      0.0847380000000000 | 0.0000000000000000
- 0.084738 |   2 |                          0.007180528644 |                      0.0071805286440000 | 0.0000000000000000
- 0.084738 |   3 |                      0.0006084636362353 |                      0.0006084636362353 | 0.0000000000000000
- 0.084738 |   4 |                      0.0000515599916073 |                      0.0000515599916073 | 0.0000000000000000
- 0.084738 |   5 |                      0.0000043690905688 |                      0.0000043690905688 | 0.0000000000000000
- 0.084738 |   6 |                      0.0000003702279966 |                      0.0000003702279966 | 0.0000000000000000
- 0.084738 |   7 |                      0.0000000313723800 |                      0.0000000313723800 | 0.0000000000000000
- 0.084738 |   8 |                      0.0000000026584327 |                      0.0000000026584327 | 0.0000000000000000
- 0.084738 |   9 |                      0.0000000002252703 |                      0.0000000002252703 | 0.0000000000000000
- 0.084738 |  10 |                      0.0000000000190890 |                      0.0000000000190890 | 0.0000000000000000
- 0.084738 |  11 |                      0.0000000000016176 |                      0.0000000000016176 | 0.0000000000000000
- 0.084738 |  12 |                      0.0000000000001371 |                      0.0000000000001371 | 0.0000000000000000
- 0.084738 |  13 |                      0.0000000000000116 |                      0.0000000000000116 | 0.0000000000000000
- 0.084738 |  14 |                      0.0000000000000010 |                      0.0000000000000010 | 0.0000000000000000
- 0.084738 |  15 |                      0.0000000000000001 |                      0.0000000000000001 | 0.0000000000000000
- 0.084738 |  16 |                      0.0000000000000000 |                      0.0000000000000000 | 0.0000000000000000
- 0.084738 |  17 |                      0.0000000000000000 |                      0.0000000000000000 | 0.0000000000000000
- 0.084738 |  18 |                      0.0000000000000000 |                      0.0000000000000000 | 0.0000000000000000
- 0.084738 |  19 |                      0.0000000000000000 |                      0.0000000000000000 | 0.0000000000000000
- 0.084738 |  20 |                      0.0000000000000000 |                      0.0000000000000000 | 0.0000000000000000
+    b     |  p  |                bc_result                |                  power                  |                  diff                   
+----------+-----+-----------------------------------------+-----------------------------------------+-----------------------------------------
+ 0.084738 | -20 |           2744326694304960114888.785913 |           2744326694304960114888.785913 |                                0.000000
+ 0.084738 | -19 |            232548755422013710215.445941 |            232548755422013710215.445941 |                                0.000000
+ 0.084738 | -18 |             19705716436950597776.236458 |             19705716436950597776.236458 |                                0.000000
+ 0.084738 | -17 |              1669822999434319754.362725 |              1669822999434319754.362725 |                                0.000000
+ 0.084738 | -16 |               141497461326065387.345189 |               141497461326065387.345189 |                                0.000000
+ 0.084738 | -15 |                11990211877848128.792857 |                11990211877848128.792857 |                                0.000000
+ 0.084738 | -14 |                 1016026574105094.737649 |                 1016026574105094.737649 |                                0.000000
+ 0.084738 | -13 |                   86096059836517.517879 |                   86096059836517.517879 |                                0.000000
+ 0.084738 | -12 |                    7295607918426.821430 |                    7295607918426.821430 |                                0.000000
+ 0.084738 | -11 |                     618215223791.651994 |                     618215223791.651994 |                                0.000000
+ 0.084738 | -10 |                      52386321633.657007 |                      52386321633.657007 |                                0.000000
+ 0.084738 |  -9 |                      4439112122.5928274 |                      4439112122.5928274 |                               0.0000000
+ 0.084738 |  -8 |                      376161483.04427101 |                      376161483.04427101 |                              0.00000000
+ 0.084738 |  -7 |                      31875171.750205437 |                      31875171.750205437 |                             0.000000000
+ 0.084738 |  -6 |                      2701038.3037689083 |                      2701038.3037689083 |                            0.0000000000
+ 0.084738 |  -5 |                      228880.58378476975 |                      228880.58378476975 |                           0.00000000000
+ 0.084738 |  -4 |                      19394.882908753819 |                      19394.882908753819 |                          0.000000000000
+ 0.084738 |  -3 |                      1643.4835879219811 |                      1643.4835879219811 |                         0.0000000000000
+ 0.084738 |  -2 |                      139.26551227333284 |                      139.26551227333284 |                        0.00000000000000
+ 0.084738 |  -1 |                      11.801080979017678 |                      11.801080979017678 |                       0.000000000000000
+ 0.084738 |   0 |                                       1 |                      1.0000000000000000 |                      0.0000000000000000
+ 0.084738 |   1 |                                0.084738 |                     0.08473800000000000 |                     0.00000000000000000
+ 0.084738 |   2 |                          0.007180528644 |                    0.007180528644000000 |                    0.000000000000000000
+ 0.084738 |   3 |                    0.000608463636235272 |                   0.0006084636362352720 |                   0.0000000000000000000
+ 0.084738 |   4 |                  0.00005155999160730448 |                  0.00005155999160730448 |                  0.00000000000000000000
+ 0.084738 |   5 |                 0.000004369090568819767 |                 0.000004369090568819767 |                 0.000000000000000000000
+ 0.084738 |   6 |                0.0000003702279966206494 |                0.0000003702279966206494 |                0.0000000000000000000000
+ 0.084738 |   7 |               0.00000003137237997764059 |               0.00000003137237997764059 |               0.00000000000000000000000
+ 0.084738 |   8 |              0.000000002658432734545308 |              0.000000002658432734545308 |              0.000000000000000000000000
+ 0.084738 |   9 |             0.0000000002252702730599003 |             0.0000000002252702730599003 |             0.0000000000000000000000000
+ 0.084738 |  10 |            0.00000000001908895239854983 |            0.00000000001908895239854983 |            0.00000000000000000000000000
+ 0.084738 |  11 |           0.000000000001617559648348316 |           0.000000000001617559648348316 |           0.000000000000000000000000000
+ 0.084738 |  12 |          0.0000000000001370687694817396 |          0.0000000000001370687694817396 |          0.0000000000000000000000000000
+ 0.084738 |  13 |         0.00000000000001161493338834365 |         0.00000000000001161493338834365 |         0.00000000000000000000000000000
+ 0.084738 |  14 |       0.0000000000000009842262254614642 |       0.0000000000000009842262254614642 |       0.0000000000000000000000000000000
+ 0.084738 |  15 |      0.00000000000000008340136189315355 |      0.00000000000000008340136189315355 |      0.00000000000000000000000000000000
+ 0.084738 |  16 |     0.000000000000000007067264604102046 |     0.000000000000000007067264604102046 |     0.000000000000000000000000000000000
+ 0.084738 |  17 |    0.0000000000000000005988658680223991 |    0.0000000000000000005988658680223991 |    0.0000000000000000000000000000000000
+ 0.084738 |  18 |   0.00000000000000000005074669592448206 |   0.00000000000000000005074669592448206 |   0.00000000000000000000000000000000000
+ 0.084738 |  19 |  0.000000000000000000004300173519248761 |  0.000000000000000000004300173519248761 |  0.000000000000000000000000000000000000
+ 0.084738 |  20 | 0.0000000000000000000003643881036741015 | 0.0000000000000000000003643881036741015 | 0.0000000000000000000000000000000000000
 (41 rows)
 
 -- base greater than 1
@@ -785,91 +785,91 @@ SELECT b, p, bc_result, b^p AS power, b^p - bc_result AS diff FROM t;
 --   echo "($b, $p, $r),"
 -- done
 WITH t(b, p, bc_result) AS (VALUES
-(37.821637, -20, .0000000000000000),
-(37.821637, -19, .0000000000000000),
-(37.821637, -18, .0000000000000000),
-(37.821637, -17, .0000000000000000),
-(37.821637, -16, .0000000000000000),
-(37.821637, -15, .0000000000000000),
-(37.821637, -14, .0000000000000000),
-(37.821637, -13, .0000000000000000),
-(37.821637, -12, .0000000000000000),
-(37.821637, -11, .0000000000000000),
-(37.821637, -10, .0000000000000002),
-(37.821637, -9, .0000000000000063),
-(37.821637, -8, .0000000000002388),
-(37.821637, -7, .0000000000090327),
-(37.821637, -6, .0000000003416316),
-(37.821637, -5, .0000000129210673),
-(37.821637, -4, .0000004886959182),
-(37.821637, -3, .0000184832796213),
-(37.821637, -2, .0006990678924066),
-(37.821637, -1, .0264398920649574),
+(37.821637, -20, .00000000000000000000000000000002787363175065101),
+(37.821637, -19, .000000000000000000000000000001054226381944797),
+(37.821637, -18, .00000000000000000000000000003987256753373947),
+(37.821637, -17, .000000000000000000000000001508045775519079),
+(37.821637, -16, .00000000000000000000000005703675990106610),
+(37.821637, -15, .000000000000000000000002157223628634278),
+(37.821637, -14, .00000000000000000000008158972901002847),
+(37.821637, -13, .000000000000000000003085857113545666),
+(37.821637, -12, .0000000000000000001167121675823920),
+(37.821637, -11, .000000000000000004414245235784397),
+(37.821637, -10, .0000000000000001669539809368169),
+(37.821637, -9, .000000000000006314472862697207),
+(37.821637, -8, .0000000000002388237004592846),
+(37.821637, -7, .000000000009032703305767796),
+(37.821637, -6, .0000000003416316255594496),
+(37.821637, -5, .00000001292106732962942),
+(37.821637, -4, .0000004886959181938034),
+(37.821637, -3, .00001848327962130773),
+(37.821637, -2, .0006990678924065984),
+(37.821637, -1, .02643989206495742),
 (37.821637, 0, 1),
 (37.821637, 1, 37.821637),
 (37.821637, 2, 1430.476225359769),
-(37.821637, 3, 54102.9525326873775219),
-(37.821637, 4, 2046262.2313195326271135),
-(37.821637, 5, 77392987.3197773940323425),
-(37.821637, 6, 2927129472.7542235178972258),
-(37.821637, 7, 110708828370.5116321107718772),
-(37.821637, 8, 4187189119324.7924539711577286),
-(37.821637, 9, 158366346921451.9852944363360812),
-(37.821637, 10, 5989674486279224.5007355092228730),
-(37.821637, 11, 226539294168214309.7083246628376531),
-(37.821637, 12, 8568086950266418559.9938312759931069),
-(37.821637, 13, 324059074417413536066.1494087598581043),
-(37.821637, 14, 12256444679171401239980.3109258799733927),
-(37.821637, 15, 463558801566202198479885.2069857662592280),
-(37.821637, 16, 17532552720991931019508170.1002855156233684),
-(37.821637, 17, 663109844696719094948877928.0672523682648687),
-(37.821637, 18, 25079899837245684700124994552.6717306599041850),
-(37.821637, 19, 948562867640665366544581398598.1275771806665398),
-(37.821637, 20, 35876200451584291931921101974730.6901038166532866))
+(37.821637, 3, 54102.952532687378),
+(37.821637, 4, 2046262.2313195326),
+(37.821637, 5, 77392987.319777394),
+(37.821637, 6, 2927129472.7542235),
+(37.821637, 7, 110708828370.511632),
+(37.821637, 8, 4187189119324.792454),
+(37.821637, 9, 158366346921451.985294),
+(37.821637, 10, 5989674486279224.500736),
+(37.821637, 11, 226539294168214309.708325),
+(37.821637, 12, 8568086950266418559.993831),
+(37.821637, 13, 324059074417413536066.149409),
+(37.821637, 14, 12256444679171401239980.310926),
+(37.821637, 15, 463558801566202198479885.206986),
+(37.821637, 16, 17532552720991931019508170.100286),
+(37.821637, 17, 663109844696719094948877928.067252),
+(37.821637, 18, 25079899837245684700124994552.671731),
+(37.821637, 19, 948562867640665366544581398598.127577),
+(37.821637, 20, 35876200451584291931921101974730.690104))
 SELECT b, p, bc_result, b^p AS power, b^p - bc_result AS diff FROM t;
-     b     |  p  |                     bc_result                     |                       power                       |        diff        
------------+-----+---------------------------------------------------+---------------------------------------------------+--------------------
- 37.821637 | -20 |                                0.0000000000000000 |                                0.0000000000000000 | 0.0000000000000000
- 37.821637 | -19 |                                0.0000000000000000 |                                0.0000000000000000 | 0.0000000000000000
- 37.821637 | -18 |                                0.0000000000000000 |                                0.0000000000000000 | 0.0000000000000000
- 37.821637 | -17 |                                0.0000000000000000 |                                0.0000000000000000 | 0.0000000000000000
- 37.821637 | -16 |                                0.0000000000000000 |                                0.0000000000000000 | 0.0000000000000000
- 37.821637 | -15 |                                0.0000000000000000 |                                0.0000000000000000 | 0.0000000000000000
- 37.821637 | -14 |                                0.0000000000000000 |                                0.0000000000000000 | 0.0000000000000000
- 37.821637 | -13 |                                0.0000000000000000 |                                0.0000000000000000 | 0.0000000000000000
- 37.821637 | -12 |                                0.0000000000000000 |                                0.0000000000000000 | 0.0000000000000000
- 37.821637 | -11 |                                0.0000000000000000 |                                0.0000000000000000 | 0.0000000000000000
- 37.821637 | -10 |                                0.0000000000000002 |                                0.0000000000000002 | 0.0000000000000000
- 37.821637 |  -9 |                                0.0000000000000063 |                                0.0000000000000063 | 0.0000000000000000
- 37.821637 |  -8 |                                0.0000000000002388 |                                0.0000000000002388 | 0.0000000000000000
- 37.821637 |  -7 |                                0.0000000000090327 |                                0.0000000000090327 | 0.0000000000000000
- 37.821637 |  -6 |                                0.0000000003416316 |                                0.0000000003416316 | 0.0000000000000000
- 37.821637 |  -5 |                                0.0000000129210673 |                                0.0000000129210673 | 0.0000000000000000
- 37.821637 |  -4 |                                0.0000004886959182 |                                0.0000004886959182 | 0.0000000000000000
- 37.821637 |  -3 |                                0.0000184832796213 |                                0.0000184832796213 | 0.0000000000000000
- 37.821637 |  -2 |                                0.0006990678924066 |                                0.0006990678924066 | 0.0000000000000000
- 37.821637 |  -1 |                                0.0264398920649574 |                                0.0264398920649574 | 0.0000000000000000
- 37.821637 |   0 |                                                 1 |                                1.0000000000000000 | 0.0000000000000000
- 37.821637 |   1 |                                         37.821637 |                               37.8216370000000000 | 0.0000000000000000
- 37.821637 |   2 |                                 1430.476225359769 |                             1430.4762253597690000 | 0.0000000000000000
- 37.821637 |   3 |                            54102.9525326873775219 |                            54102.9525326873775219 | 0.0000000000000000
- 37.821637 |   4 |                          2046262.2313195326271135 |                          2046262.2313195326271135 | 0.0000000000000000
- 37.821637 |   5 |                         77392987.3197773940323425 |                         77392987.3197773940323425 | 0.0000000000000000
- 37.821637 |   6 |                       2927129472.7542235178972258 |                       2927129472.7542235178972258 | 0.0000000000000000
- 37.821637 |   7 |                     110708828370.5116321107718772 |                     110708828370.5116321107718772 | 0.0000000000000000
- 37.821637 |   8 |                    4187189119324.7924539711577286 |                    4187189119324.7924539711577286 | 0.0000000000000000
- 37.821637 |   9 |                  158366346921451.9852944363360812 |                  158366346921451.9852944363360812 | 0.0000000000000000
- 37.821637 |  10 |                 5989674486279224.5007355092228730 |                 5989674486279224.5007355092228730 | 0.0000000000000000
- 37.821637 |  11 |               226539294168214309.7083246628376531 |               226539294168214309.7083246628376531 | 0.0000000000000000
- 37.821637 |  12 |              8568086950266418559.9938312759931069 |              8568086950266418559.9938312759931069 | 0.0000000000000000
- 37.821637 |  13 |            324059074417413536066.1494087598581043 |            324059074417413536066.1494087598581043 | 0.0000000000000000
- 37.821637 |  14 |          12256444679171401239980.3109258799733927 |          12256444679171401239980.3109258799733927 | 0.0000000000000000
- 37.821637 |  15 |         463558801566202198479885.2069857662592280 |         463558801566202198479885.2069857662592280 | 0.0000000000000000
- 37.821637 |  16 |       17532552720991931019508170.1002855156233684 |       17532552720991931019508170.1002855156233684 | 0.0000000000000000
- 37.821637 |  17 |      663109844696719094948877928.0672523682648687 |      663109844696719094948877928.0672523682648687 | 0.0000000000000000
- 37.821637 |  18 |    25079899837245684700124994552.6717306599041850 |    25079899837245684700124994552.6717306599041850 | 0.0000000000000000
- 37.821637 |  19 |   948562867640665366544581398598.1275771806665398 |   948562867640665366544581398598.1275771806665398 | 0.0000000000000000
- 37.821637 |  20 | 35876200451584291931921101974730.6901038166532866 | 35876200451584291931921101974730.6901038166532866 | 0.0000000000000000
+     b     |  p  |                     bc_result                     |                       power                       |                       diff                        
+-----------+-----+---------------------------------------------------+---------------------------------------------------+---------------------------------------------------
+ 37.821637 | -20 | 0.00000000000000000000000000000002787363175065101 | 0.00000000000000000000000000000002787363175065101 | 0.00000000000000000000000000000000000000000000000
+ 37.821637 | -19 |   0.000000000000000000000000000001054226381944797 |   0.000000000000000000000000000001054226381944797 |   0.000000000000000000000000000000000000000000000
+ 37.821637 | -18 |    0.00000000000000000000000000003987256753373947 |    0.00000000000000000000000000003987256753373947 |    0.00000000000000000000000000000000000000000000
+ 37.821637 | -17 |      0.000000000000000000000000001508045775519079 |      0.000000000000000000000000001508045775519079 |      0.000000000000000000000000000000000000000000
+ 37.821637 | -16 |       0.00000000000000000000000005703675990106610 |       0.00000000000000000000000005703675990106610 |       0.00000000000000000000000000000000000000000
+ 37.821637 | -15 |         0.000000000000000000000002157223628634278 |         0.000000000000000000000002157223628634278 |         0.000000000000000000000000000000000000000
+ 37.821637 | -14 |          0.00000000000000000000008158972901002847 |          0.00000000000000000000008158972901002847 |          0.00000000000000000000000000000000000000
+ 37.821637 | -13 |            0.000000000000000000003085857113545666 |            0.000000000000000000003085857113545666 |            0.000000000000000000000000000000000000
+ 37.821637 | -12 |              0.0000000000000000001167121675823920 |              0.0000000000000000001167121675823920 |              0.0000000000000000000000000000000000
+ 37.821637 | -11 |               0.000000000000000004414245235784397 |               0.000000000000000004414245235784397 |               0.000000000000000000000000000000000
+ 37.821637 | -10 |                 0.0000000000000001669539809368169 |                 0.0000000000000001669539809368169 |                 0.0000000000000000000000000000000
+ 37.821637 |  -9 |                  0.000000000000006314472862697207 |                  0.000000000000006314472862697207 |                  0.000000000000000000000000000000
+ 37.821637 |  -8 |                    0.0000000000002388237004592846 |                    0.0000000000002388237004592846 |                    0.0000000000000000000000000000
+ 37.821637 |  -7 |                     0.000000000009032703305767796 |                     0.000000000009032703305767796 |                     0.000000000000000000000000000
+ 37.821637 |  -6 |                       0.0000000003416316255594496 |                       0.0000000003416316255594496 |                       0.0000000000000000000000000
+ 37.821637 |  -5 |                         0.00000001292106732962942 |                         0.00000001292106732962942 |                         0.00000000000000000000000
+ 37.821637 |  -4 |                          0.0000004886959181938034 |                          0.0000004886959181938034 |                          0.0000000000000000000000
+ 37.821637 |  -3 |                            0.00001848327962130773 |                            0.00001848327962130773 |                            0.00000000000000000000
+ 37.821637 |  -2 |                             0.0006990678924065984 |                             0.0006990678924065984 |                             0.0000000000000000000
+ 37.821637 |  -1 |                               0.02643989206495742 |                               0.02643989206495742 |                               0.00000000000000000
+ 37.821637 |   0 |                                                 1 |                                1.0000000000000000 |                                0.0000000000000000
+ 37.821637 |   1 |                                         37.821637 |                                37.821637000000000 |                                 0.000000000000000
+ 37.821637 |   2 |                                 1430.476225359769 |                                1430.4762253597690 |                                   0.0000000000000
+ 37.821637 |   3 |                                54102.952532687378 |                                54102.952532687378 |                                    0.000000000000
+ 37.821637 |   4 |                                2046262.2313195326 |                                2046262.2313195326 |                                      0.0000000000
+ 37.821637 |   5 |                                77392987.319777394 |                                77392987.319777394 |                                       0.000000000
+ 37.821637 |   6 |                                2927129472.7542235 |                                2927129472.7542235 |                                         0.0000000
+ 37.821637 |   7 |                               110708828370.511632 |                               110708828370.511632 |                                          0.000000
+ 37.821637 |   8 |                              4187189119324.792454 |                              4187189119324.792454 |                                          0.000000
+ 37.821637 |   9 |                            158366346921451.985294 |                            158366346921451.985294 |                                          0.000000
+ 37.821637 |  10 |                           5989674486279224.500736 |                           5989674486279224.500736 |                                          0.000000
+ 37.821637 |  11 |                         226539294168214309.708325 |                         226539294168214309.708325 |                                          0.000000
+ 37.821637 |  12 |                        8568086950266418559.993831 |                        8568086950266418559.993831 |                                          0.000000
+ 37.821637 |  13 |                      324059074417413536066.149409 |                      324059074417413536066.149409 |                                          0.000000
+ 37.821637 |  14 |                    12256444679171401239980.310926 |                    12256444679171401239980.310926 |                                          0.000000
+ 37.821637 |  15 |                   463558801566202198479885.206986 |                   463558801566202198479885.206986 |                                          0.000000
+ 37.821637 |  16 |                 17532552720991931019508170.100286 |                 17532552720991931019508170.100286 |                                          0.000000
+ 37.821637 |  17 |                663109844696719094948877928.067252 |                663109844696719094948877928.067252 |                                          0.000000
+ 37.821637 |  18 |              25079899837245684700124994552.671731 |              25079899837245684700124994552.671731 |                                          0.000000
+ 37.821637 |  19 |             948562867640665366544581398598.127577 |             948562867640665366544581398598.127577 |                                          0.000000
+ 37.821637 |  20 |           35876200451584291931921101974730.690104 |           35876200451584291931921101974730.690104 |                                          0.000000
 (41 rows)
 
 --
index eeca63d86e71c86448ce8e8a7444d82f535cda5c..93bb0996be57418f5b779f32a38094977ce5af24 100644 (file)
@@ -1142,8 +1142,8 @@ select 10.0 ^ 2147483647 as overflows;
 select 117743296169.0 ^ 1000000000 as overflows;
 
 -- cases that used to return inaccurate results
-select 3.789 ^ 21;
-select 3.789 ^ 35;
+select 3.789 ^ 21.0000000000000000;
+select 3.789 ^ 35.0000000000000000;
 select 1.2 ^ 345;
 select 0.12 ^ (-20);
 select 1.000000000123 ^ (-2147483648);
@@ -1162,6 +1162,10 @@ select (-1.0) ^ 2147483648;
 select (-1.0) ^ 1000000000000000;
 select (-1.0) ^ 1000000000000001;
 
+-- integer powers of 10
+select n, 10.0 ^ n as "10^n", (10.0 ^ n) * (10.0 ^ (-n)) = 1 as ok
+from generate_series(-20, 20) n;
+
 --
 -- Tests for raising to non-integer powers
 --
index c9d52d08b4455f699a6b75d060d5ad2d6cdf0805..d67d9e88f9ad267fecfdb7c42ea0eb946ea18c2c 100644 (file)
@@ -664,47 +664,47 @@ SELECT t1.id1, t1.result, t2.expected
 -- done
 
 WITH t(b, p, bc_result) AS (VALUES
-(0.084738, -20, 2744326694304960114888.7859130502035257),
-(0.084738, -19, 232548755422013710215.4459407000481464),
-(0.084738, -18, 19705716436950597776.2364581230406798),
-(0.084738, -17, 1669822999434319754.3627249884302211),
-(0.084738, -16, 141497461326065387.3451885900696001),
-(0.084738, -15, 11990211877848128.7928565907453178),
-(0.084738, -14, 1016026574105094.7376490817865767),
-(0.084738, -13, 86096059836517.5178789078924309),
-(0.084738, -12, 7295607918426.8214300228969888),
-(0.084738, -11, 618215223791.6519943372802450),
-(0.084738, -10, 52386321633.6570066961524534),
-(0.084738, -9, 4439112122.5928274334185666),
-(0.084738, -8, 376161483.0442710110530225),
-(0.084738, -7, 31875171.7502054369346110),
-(0.084738, -6, 2701038.3037689083149651),
-(0.084738, -5, 228880.5837847697527935),
-(0.084738, -4, 19394.8829087538193122),
-(0.084738, -3, 1643.4835879219811409),
-(0.084738, -2, 139.2655122733328379),
-(0.084738, -1, 11.8010809790176780),
+(0.084738, -20, 2744326694304960114888.785913),
+(0.084738, -19, 232548755422013710215.445941),
+(0.084738, -18, 19705716436950597776.236458),
+(0.084738, -17, 1669822999434319754.362725),
+(0.084738, -16, 141497461326065387.345189),
+(0.084738, -15, 11990211877848128.792857),
+(0.084738, -14, 1016026574105094.737649),
+(0.084738, -13, 86096059836517.517879),
+(0.084738, -12, 7295607918426.821430),
+(0.084738, -11, 618215223791.651994),
+(0.084738, -10, 52386321633.657007),
+(0.084738, -9, 4439112122.5928274),
+(0.084738, -8, 376161483.04427101),
+(0.084738, -7, 31875171.750205437),
+(0.084738, -6, 2701038.3037689083),
+(0.084738, -5, 228880.58378476975),
+(0.084738, -4, 19394.882908753819),
+(0.084738, -3, 1643.4835879219811),
+(0.084738, -2, 139.26551227333284),
+(0.084738, -1, 11.801080979017678),
 (0.084738, 0, 1),
 (0.084738, 1, .084738),
 (0.084738, 2, .007180528644),
-(0.084738, 3, .0006084636362353),
-(0.084738, 4, .0000515599916073),
-(0.084738, 5, .0000043690905688),
-(0.084738, 6, .0000003702279966),
-(0.084738, 7, .0000000313723800),
-(0.084738, 8, .0000000026584327),
-(0.084738, 9, .0000000002252703),
-(0.084738, 10, .0000000000190890),
-(0.084738, 11, .0000000000016176),
-(0.084738, 12, .0000000000001371),
-(0.084738, 13, .0000000000000116),
-(0.084738, 14, .0000000000000010),
-(0.084738, 15, .0000000000000001),
-(0.084738, 16, .0000000000000000),
-(0.084738, 17, .0000000000000000),
-(0.084738, 18, .0000000000000000),
-(0.084738, 19, .0000000000000000),
-(0.084738, 20, .0000000000000000))
+(0.084738, 3, .000608463636235272),
+(0.084738, 4, .00005155999160730448),
+(0.084738, 5, .000004369090568819767),
+(0.084738, 6, .0000003702279966206494),
+(0.084738, 7, .00000003137237997764059),
+(0.084738, 8, .000000002658432734545308),
+(0.084738, 9, .0000000002252702730599003),
+(0.084738, 10, .00000000001908895239854983),
+(0.084738, 11, .000000000001617559648348316),
+(0.084738, 12, .0000000000001370687694817396),
+(0.084738, 13, .00000000000001161493338834365),
+(0.084738, 14, .0000000000000009842262254614642),
+(0.084738, 15, .00000000000000008340136189315355),
+(0.084738, 16, .000000000000000007067264604102046),
+(0.084738, 17, .0000000000000000005988658680223991),
+(0.084738, 18, .00000000000000000005074669592448206),
+(0.084738, 19, .000000000000000000004300173519248761),
+(0.084738, 20, .0000000000000000000003643881036741015))
 SELECT b, p, bc_result, b^p AS power, b^p - bc_result AS diff FROM t;
 
 -- base greater than 1
@@ -720,47 +720,47 @@ SELECT b, p, bc_result, b^p AS power, b^p - bc_result AS diff FROM t;
 -- done
 
 WITH t(b, p, bc_result) AS (VALUES
-(37.821637, -20, .0000000000000000),
-(37.821637, -19, .0000000000000000),
-(37.821637, -18, .0000000000000000),
-(37.821637, -17, .0000000000000000),
-(37.821637, -16, .0000000000000000),
-(37.821637, -15, .0000000000000000),
-(37.821637, -14, .0000000000000000),
-(37.821637, -13, .0000000000000000),
-(37.821637, -12, .0000000000000000),
-(37.821637, -11, .0000000000000000),
-(37.821637, -10, .0000000000000002),
-(37.821637, -9, .0000000000000063),
-(37.821637, -8, .0000000000002388),
-(37.821637, -7, .0000000000090327),
-(37.821637, -6, .0000000003416316),
-(37.821637, -5, .0000000129210673),
-(37.821637, -4, .0000004886959182),
-(37.821637, -3, .0000184832796213),
-(37.821637, -2, .0006990678924066),
-(37.821637, -1, .0264398920649574),
+(37.821637, -20, .00000000000000000000000000000002787363175065101),
+(37.821637, -19, .000000000000000000000000000001054226381944797),
+(37.821637, -18, .00000000000000000000000000003987256753373947),
+(37.821637, -17, .000000000000000000000000001508045775519079),
+(37.821637, -16, .00000000000000000000000005703675990106610),
+(37.821637, -15, .000000000000000000000002157223628634278),
+(37.821637, -14, .00000000000000000000008158972901002847),
+(37.821637, -13, .000000000000000000003085857113545666),
+(37.821637, -12, .0000000000000000001167121675823920),
+(37.821637, -11, .000000000000000004414245235784397),
+(37.821637, -10, .0000000000000001669539809368169),
+(37.821637, -9, .000000000000006314472862697207),
+(37.821637, -8, .0000000000002388237004592846),
+(37.821637, -7, .000000000009032703305767796),
+(37.821637, -6, .0000000003416316255594496),
+(37.821637, -5, .00000001292106732962942),
+(37.821637, -4, .0000004886959181938034),
+(37.821637, -3, .00001848327962130773),
+(37.821637, -2, .0006990678924065984),
+(37.821637, -1, .02643989206495742),
 (37.821637, 0, 1),
 (37.821637, 1, 37.821637),
 (37.821637, 2, 1430.476225359769),
-(37.821637, 3, 54102.9525326873775219),
-(37.821637, 4, 2046262.2313195326271135),
-(37.821637, 5, 77392987.3197773940323425),
-(37.821637, 6, 2927129472.7542235178972258),
-(37.821637, 7, 110708828370.5116321107718772),
-(37.821637, 8, 4187189119324.7924539711577286),
-(37.821637, 9, 158366346921451.9852944363360812),
-(37.821637, 10, 5989674486279224.5007355092228730),
-(37.821637, 11, 226539294168214309.7083246628376531),
-(37.821637, 12, 8568086950266418559.9938312759931069),
-(37.821637, 13, 324059074417413536066.1494087598581043),
-(37.821637, 14, 12256444679171401239980.3109258799733927),
-(37.821637, 15, 463558801566202198479885.2069857662592280),
-(37.821637, 16, 17532552720991931019508170.1002855156233684),
-(37.821637, 17, 663109844696719094948877928.0672523682648687),
-(37.821637, 18, 25079899837245684700124994552.6717306599041850),
-(37.821637, 19, 948562867640665366544581398598.1275771806665398),
-(37.821637, 20, 35876200451584291931921101974730.6901038166532866))
+(37.821637, 3, 54102.952532687378),
+(37.821637, 4, 2046262.2313195326),
+(37.821637, 5, 77392987.319777394),
+(37.821637, 6, 2927129472.7542235),
+(37.821637, 7, 110708828370.511632),
+(37.821637, 8, 4187189119324.792454),
+(37.821637, 9, 158366346921451.985294),
+(37.821637, 10, 5989674486279224.500736),
+(37.821637, 11, 226539294168214309.708325),
+(37.821637, 12, 8568086950266418559.993831),
+(37.821637, 13, 324059074417413536066.149409),
+(37.821637, 14, 12256444679171401239980.310926),
+(37.821637, 15, 463558801566202198479885.206986),
+(37.821637, 16, 17532552720991931019508170.100286),
+(37.821637, 17, 663109844696719094948877928.067252),
+(37.821637, 18, 25079899837245684700124994552.671731),
+(37.821637, 19, 948562867640665366544581398598.127577),
+(37.821637, 20, 35876200451584291931921101974730.690104))
 SELECT b, p, bc_result, b^p AS power, b^p - bc_result AS diff FROM t;
 
 --