]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Avoid unnecessary normalization in decimal_sum(). Trim excess trailing
authordrh <drh@noemail.net>
Tue, 23 Jun 2020 14:44:57 +0000 (14:44 +0000)
committerdrh <drh@noemail.net>
Tue, 23 Jun 2020 14:44:57 +0000 (14:44 +0000)
zeros off the result of decimal_mul().

FossilOrigin-Name: 0294ce071c863eb517e97beff31c3d95a4370e979a969415162302a90d3fda0e

ext/misc/decimal.c
manifest
manifest.uuid
test/decimal.test

index 341b3c046d6d68131de9bb35d57731a0b5b1790a..43c5c2ef0d4a66b72e1e93a56954722ecbf8de57 100644 (file)
@@ -204,6 +204,10 @@ static void decimal_result(sqlite3_context *pCtx, Decimal *p){
     z[i++] = '0';
   }
   j = 0;
+  while( n>1 && p->a[j]==0 ){
+    j++;
+    n--;
+  }
   while( n>0  ){
     z[i++] = p->a[j] + '0';
     j++;
@@ -297,26 +301,6 @@ cmp_done:
   decimal_free(pB);
 }
 
-/*
-** Remove leading zeros from before the decimal and
-** trailing zeros after the decimal.
-*/
-static void decimal_normalize(Decimal *p){
-  int i;
-  int nSig;
-  if( p==0 ) return;
-  nSig = p->nDigit - p->nFrac;
-  for(i=0; i<nSig && p->a[i]==0; i++){}
-  if( i ){
-    memmove(p->a, p->a+i, p->nDigit - i);
-    p->nDigit -= i;
-  }
-  while( p->nFrac && p->a[p->nDigit-1]==0 ){
-    p->nFrac--;
-    p->nDigit--;
-  }
-}
-
 /*
 ** Expand the Decimal so that it has a least nDigit digits and nFrac
 ** digits to the right of the decimal point.
@@ -348,7 +332,7 @@ static void decimal_expand(Decimal *p, int nDigit, int nFrac){
 /*
 ** Add the value pB into pA.
 **
-** pB might become denormalized by this routine.
+** Both pA and pB might become denormalized by this routine.
 */
 static void decimal_add(Decimal *pA, Decimal *pB){
   int nSig, nFrac, nDigit;
@@ -365,7 +349,10 @@ static void decimal_add(Decimal *pA, Decimal *pB){
     return;
   }
   nSig = pA->nDigit - pA->nFrac;
-  if( nSig<pB->nDigit-pB->nFrac ) nSig = pB->nDigit - pB->nFrac;
+  if( nSig && pA->a[0]==0 ) nSig--;
+  if( nSig<pB->nDigit-pB->nFrac ){
+    nSig = pB->nDigit - pB->nFrac;
+  }
   nFrac = pA->nFrac;
   if( nFrac<pB->nFrac ) nFrac = pB->nFrac;
   nDigit = nSig + nFrac + 1;
@@ -410,7 +397,6 @@ static void decimal_add(Decimal *pA, Decimal *pB){
       }
     }
   }
-  decimal_normalize(pA);
 }
 
 /*
@@ -518,13 +504,11 @@ static void decimalSumInverse(
 static void decimalSumValue(sqlite3_context *context){
   Decimal *p = sqlite3_aggregate_context(context, 0);
   if( p==0 ) return;
-  decimal_normalize(p);
   decimal_result(context, p);
 }
 static void decimalSumFinalize(sqlite3_context *context){
   Decimal *p = sqlite3_aggregate_context(context, 0);
   if( p==0 ) return;
-  decimal_normalize(p);
   decimal_result(context, p);
   decimal_clear(p);
 }
@@ -533,6 +517,11 @@ static void decimalSumFinalize(sqlite3_context *context){
 ** SQL Function:   decimal_mul(X, Y)
 **
 ** Return the product of X and Y.
+**
+** All significant digits after the decimal point are retained.
+** Trailing zeros after the decimal point are omitted as long as
+** the number of digits after the decimal point is no less than
+** either the number of digits in either input.
 */
 static void decimalMulFunc(
   sqlite3_context *context,
@@ -543,6 +532,7 @@ static void decimalMulFunc(
   Decimal *pB = decimal_new(context, argv[1], 0, 0);
   signed char *acc = 0;
   int i, j, k;
+  int minFrac;
   if( pA==0 || pA->oom || pA->isNull
    || pB==0 || pB->oom || pB->isNull 
   ){
@@ -554,6 +544,8 @@ static void decimalMulFunc(
     goto mul_end;
   }
   memset(acc, 0, pA->nDigit + pB->nDigit + 2);
+  minFrac = pA->nFrac;
+  if( pB->nFrac<minFrac ) minFrac = pB->nFrac;
   for(i=pA->nDigit-1; i>=0; i--){
     signed char f = pA->a[i];
     int carry = 0, x;
@@ -572,7 +564,10 @@ static void decimalMulFunc(
   pA->nDigit += pB->nDigit + 2;
   pA->nFrac += pB->nFrac;
   pA->sign ^= pB->sign;
-  decimal_normalize(pA);
+  while( pA->nFrac>minFrac && pA->a[pA->nDigit-1]==0 ){
+    pA->nFrac--;
+    pA->nDigit--;
+  }
   decimal_result(context, pA);
 
 mul_end:
index 4c38728caa20119525f655b470cb37d3ee181e36..5cbe47f9ccb3c3aaf5b77bfb702bc27cce6740b1 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,17 +1,17 @@
 B 7a876209a678a34c198b54ceef9e3c041f128a14dc73357f6a57cadadaa6cf7b
-C Add\sthe\sdecimal_mul()\sfunction.
-D 2020-06-22T21:25:37.690
+C Avoid\sunnecessary\snormalization\sin\sdecimal_sum().\s\sTrim\sexcess\strailing\nzeros\soff\sthe\sresult\sof\sdecimal_mul().
+D 2020-06-23T14:44:57.292
 F Makefile.in 014ad669b4a5809752939c2dea83722992711b464aa56adebca80c5cc98cfdc2
 F Makefile.msc 08c8bbedfa51e21b57153370edbfee86d35bbefb53e3773a3e086fe654facccb
 F autoconf/Makefile.am a8d1d24affe52ebf8d7ddcf91aa973fa0316618ab95bb68c87cabf8faf527dc8
-F ext/misc/decimal.c 334d8d34c124a8820d814dadbe1ac3daec63f504d5b322eb63671c317d3c6a3e
+F ext/misc/decimal.c 7ddba759b25b433231d1d9ca7cfba947992856059e2eefc5664160d4163c71d2
 F main.mk c99e452dd4edd0bea28547259421bd6cf24d41d928d24720737efc548958ca39
 F src/build.c ba1bbe563a3dc02d5fed20537603181e5289c13ea30ae5e775f552e7557adbfa
 F src/shell.c.in 7fe12fb6452de32f92bb26ee50524ec31c9d08a1c46376ca00a4ecd27472a14d
 F src/test1.c fe56c4bcaa2685ca9aa25d817a0ee9345e189aff4a5a71a3d8ba946c7776feb8
-F test/decimal.test c4af0264a0f30e896f617b489d69039932fe5127b02ac221d96f8af31db13826
+F test/decimal.test 12739a01bdba4c4d79f95b323e6b67b9fad1ab6ffb56116bd2b9c81a5b19e1d9
 F tool/mkautoconfamal.sh f62353eb6c06ab264da027fd4507d09914433dbdcab9cb011cdc18016f1ab3b8
-P 4c3b85607feb53462ccc8b89bea699fdb132c402eae597afa33cc40a85c32329
-R d79a1d72394e5a5f6c93e9466f2c9aa1
+P 72eee04b67268ad38fd51ff32849f08c0a54cf1b481d5ecb11d77cc9c729ee03
+R 91beb964e18be89b7d24fd58df29ec37
 U drh
-Z 3092a9d89a34e083e375231f8e857b54
+Z 2211c9af276c1b9a10695b6c4b82f27a
index 997afdbdeb17dfc1e11109de0cb149d31a213a31..f937a3c5a42e1a603f37adfc335ac35da030239c 100644 (file)
@@ -1 +1 @@
-72eee04b67268ad38fd51ff32849f08c0a54cf1b481d5ecb11d77cc9c729ee03
\ No newline at end of file
+0294ce071c863eb517e97beff31c3d95a4370e979a969415162302a90d3fda0e
\ No newline at end of file
index 726f470bcc16cf261c0b6aa9797f6af861247313..6fb15340f8ca14edbad8081c754c1304006e950f 100644 (file)
@@ -125,4 +125,18 @@ do_execsql_test 5000 {
   SELECT count(*) FROM c WHERE decimal_mul(y,z)='1';
 } {33}
 
+do_execsql_test 5100 {
+  SELECT decimal_mul('1234.00','2.00');
+} {2468.00}
+do_execsql_test 5101 {
+  SELECT decimal_mul('1234.00','2.0000');
+} {2468.00}
+do_execsql_test 5102 {
+  SELECT decimal_mul('1234.0000','2.000');
+} {2468.000}
+do_execsql_test 5103 {
+  SELECT decimal_mul('1234.0000','2');
+} {2468}
+
+
 finish_test