Avoid unnecessary normalization in decimal_sum(). Trim excess trailing

zeros off the result of decimal_mul().

FossilOrigin-Name: 0294ce071c863eb517e97beff31c3d95a4370e979a969415162302a90d3fda0e
This commit is contained in:
drh 2020-06-23 14:44:57 +00:00
parent 427af8dc3d
commit 6b64718618
4 changed files with 43 additions and 34 deletions

View 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:

View File

@ -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

View File

@ -1 +1 @@
72eee04b67268ad38fd51ff32849f08c0a54cf1b481d5ecb11d77cc9c729ee03
0294ce071c863eb517e97beff31c3d95a4370e979a969415162302a90d3fda0e

View 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