From: drh Date: Tue, 23 Jun 2020 14:44:57 +0000 (+0000) Subject: Avoid unnecessary normalization in decimal_sum(). Trim excess trailing X-Git-Tag: version-3.33.0~102^2~1 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=6b647186186cc01237d600ace86602d72d4f58d0;p=thirdparty%2Fsqlite.git Avoid unnecessary normalization in decimal_sum(). Trim excess trailing zeros off the result of decimal_mul(). FossilOrigin-Name: 0294ce071c863eb517e97beff31c3d95a4370e979a969415162302a90d3fda0e --- diff --git a/ext/misc/decimal.c b/ext/misc/decimal.c index 341b3c046d..43c5c2ef0d 100644 --- a/ext/misc/decimal.c +++ b/ext/misc/decimal.c @@ -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; ia[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( nSignDigit-pB->nFrac ) nSig = pB->nDigit - pB->nFrac; + if( nSig && pA->a[0]==0 ) nSig--; + if( nSignDigit-pB->nFrac ){ + nSig = pB->nDigit - pB->nFrac; + } nFrac = pA->nFrac; if( nFracnFrac ) 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->nFracnFrac; 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: diff --git a/manifest b/manifest index 4c38728caa..5cbe47f9cc 100644 --- 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 diff --git a/manifest.uuid b/manifest.uuid index 997afdbdeb..f937a3c5a4 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -72eee04b67268ad38fd51ff32849f08c0a54cf1b481d5ecb11d77cc9c729ee03 \ No newline at end of file +0294ce071c863eb517e97beff31c3d95a4370e979a969415162302a90d3fda0e \ No newline at end of file diff --git a/test/decimal.test b/test/decimal.test index 726f470bcc..6fb15340f8 100644 --- a/test/decimal.test +++ b/test/decimal.test @@ -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