xref: /sqlite-3.40.0/ext/misc/decimal.c (revision e103a8de)
1beb9def0Sdrh /*
2beb9def0Sdrh ** 2020-06-22
3beb9def0Sdrh **
4beb9def0Sdrh ** The author disclaims copyright to this source code.  In place of
5beb9def0Sdrh ** a legal notice, here is a blessing:
6beb9def0Sdrh **
7beb9def0Sdrh **    May you do good and not evil.
8beb9def0Sdrh **    May you find forgiveness for yourself and forgive others.
9beb9def0Sdrh **    May you share freely, never taking more than you give.
10beb9def0Sdrh **
11beb9def0Sdrh ******************************************************************************
12beb9def0Sdrh **
13beb9def0Sdrh ** Routines to implement arbitrary-precision decimal math.
14beb9def0Sdrh **
15beb9def0Sdrh ** The focus here is on simplicity and correctness, not performance.
16beb9def0Sdrh */
17beb9def0Sdrh #include "sqlite3ext.h"
18beb9def0Sdrh SQLITE_EXTENSION_INIT1
19beb9def0Sdrh #include <assert.h>
20beb9def0Sdrh #include <string.h>
21beb9def0Sdrh #include <ctype.h>
22beb9def0Sdrh #include <stdlib.h>
23beb9def0Sdrh 
24a7c74006Sdrh /* Mark a function parameter as unused, to suppress nuisance compiler
25a7c74006Sdrh ** warnings. */
26a7c74006Sdrh #ifndef UNUSED_PARAMETER
27a7c74006Sdrh # define UNUSED_PARAMETER(X)  (void)(X)
28a7c74006Sdrh #endif
29a7c74006Sdrh 
30beb9def0Sdrh 
31beb9def0Sdrh /* A decimal object */
32beb9def0Sdrh typedef struct Decimal Decimal;
33beb9def0Sdrh struct Decimal {
34beb9def0Sdrh   char sign;        /* 0 for positive, 1 for negative */
35beb9def0Sdrh   char oom;         /* True if an OOM is encountered */
36beb9def0Sdrh   char isNull;      /* True if holds a NULL rather than a number */
37beb9def0Sdrh   char isInit;      /* True upon initialization */
38beb9def0Sdrh   int nDigit;       /* Total number of digits */
39beb9def0Sdrh   int nFrac;        /* Number of digits to the right of the decimal point */
40beb9def0Sdrh   signed char *a;   /* Array of digits.  Most significant first. */
41beb9def0Sdrh };
42beb9def0Sdrh 
43beb9def0Sdrh /*
44beb9def0Sdrh ** Release memory held by a Decimal, but do not free the object itself.
45beb9def0Sdrh */
decimal_clear(Decimal * p)46beb9def0Sdrh static void decimal_clear(Decimal *p){
47beb9def0Sdrh   sqlite3_free(p->a);
48beb9def0Sdrh }
49beb9def0Sdrh 
50beb9def0Sdrh /*
51beb9def0Sdrh ** Destroy a Decimal object
52beb9def0Sdrh */
decimal_free(Decimal * p)53beb9def0Sdrh static void decimal_free(Decimal *p){
54beb9def0Sdrh   if( p ){
55beb9def0Sdrh     decimal_clear(p);
56beb9def0Sdrh     sqlite3_free(p);
57beb9def0Sdrh   }
58beb9def0Sdrh }
59beb9def0Sdrh 
60beb9def0Sdrh /*
61beb9def0Sdrh ** Allocate a new Decimal object.  Initialize it to the number given
62beb9def0Sdrh ** by the input string.
63beb9def0Sdrh */
decimal_new(sqlite3_context * pCtx,sqlite3_value * pIn,int nAlt,const unsigned char * zAlt)64beb9def0Sdrh static Decimal *decimal_new(
65beb9def0Sdrh   sqlite3_context *pCtx,
66beb9def0Sdrh   sqlite3_value *pIn,
67beb9def0Sdrh   int nAlt,
68beb9def0Sdrh   const unsigned char *zAlt
69beb9def0Sdrh ){
70beb9def0Sdrh   Decimal *p;
71beb9def0Sdrh   int n, i;
72beb9def0Sdrh   const unsigned char *zIn;
73beb9def0Sdrh   int iExp = 0;
74beb9def0Sdrh   p = sqlite3_malloc( sizeof(*p) );
75beb9def0Sdrh   if( p==0 ) goto new_no_mem;
76beb9def0Sdrh   p->sign = 0;
77beb9def0Sdrh   p->oom = 0;
78beb9def0Sdrh   p->isInit = 1;
79beb9def0Sdrh   p->isNull = 0;
80beb9def0Sdrh   p->nDigit = 0;
81beb9def0Sdrh   p->nFrac = 0;
82beb9def0Sdrh   if( zAlt ){
83beb9def0Sdrh     n = nAlt,
84beb9def0Sdrh     zIn = zAlt;
85beb9def0Sdrh   }else{
86beb9def0Sdrh     if( sqlite3_value_type(pIn)==SQLITE_NULL ){
87beb9def0Sdrh       p->a = 0;
88beb9def0Sdrh       p->isNull = 1;
89beb9def0Sdrh       return p;
90beb9def0Sdrh     }
91beb9def0Sdrh     n = sqlite3_value_bytes(pIn);
92beb9def0Sdrh     zIn = sqlite3_value_text(pIn);
93beb9def0Sdrh   }
94beb9def0Sdrh   p->a = sqlite3_malloc64( n+1 );
95beb9def0Sdrh   if( p->a==0 ) goto new_no_mem;
96beb9def0Sdrh   for(i=0; isspace(zIn[i]); i++){}
97beb9def0Sdrh   if( zIn[i]=='-' ){
98beb9def0Sdrh     p->sign = 1;
99beb9def0Sdrh     i++;
100beb9def0Sdrh   }else if( zIn[i]=='+' ){
101beb9def0Sdrh     i++;
102beb9def0Sdrh   }
103beb9def0Sdrh   while( i<n && zIn[i]=='0' ) i++;
104beb9def0Sdrh   while( i<n ){
105beb9def0Sdrh     char c = zIn[i];
106beb9def0Sdrh     if( c>='0' && c<='9' ){
107beb9def0Sdrh       p->a[p->nDigit++] = c - '0';
108beb9def0Sdrh     }else if( c=='.' ){
109beb9def0Sdrh       p->nFrac = p->nDigit + 1;
110beb9def0Sdrh     }else if( c=='e' || c=='E' ){
111beb9def0Sdrh       int j = i+1;
112beb9def0Sdrh       int neg = 0;
113beb9def0Sdrh       if( j>=n ) break;
114beb9def0Sdrh       if( zIn[j]=='-' ){
115beb9def0Sdrh         neg = 1;
116beb9def0Sdrh         j++;
117beb9def0Sdrh       }else if( zIn[j]=='+' ){
118beb9def0Sdrh         j++;
119beb9def0Sdrh       }
120beb9def0Sdrh       while( j<n && iExp<1000000 ){
121beb9def0Sdrh         if( zIn[j]>='0' && zIn[j]<='9' ){
122beb9def0Sdrh           iExp = iExp*10 + zIn[j] - '0';
123beb9def0Sdrh         }
124beb9def0Sdrh         j++;
125beb9def0Sdrh       }
126beb9def0Sdrh       if( neg ) iExp = -iExp;
127beb9def0Sdrh       break;
128beb9def0Sdrh     }
129beb9def0Sdrh     i++;
130beb9def0Sdrh   }
131beb9def0Sdrh   if( p->nFrac ){
132beb9def0Sdrh     p->nFrac = p->nDigit - (p->nFrac - 1);
133beb9def0Sdrh   }
134beb9def0Sdrh   if( iExp>0 ){
135beb9def0Sdrh     if( p->nFrac>0 ){
136beb9def0Sdrh       if( iExp<=p->nFrac ){
137beb9def0Sdrh         p->nFrac -= iExp;
138beb9def0Sdrh         iExp = 0;
139beb9def0Sdrh       }else{
140beb9def0Sdrh         iExp -= p->nFrac;
141beb9def0Sdrh         p->nFrac = 0;
142beb9def0Sdrh       }
143beb9def0Sdrh     }
144beb9def0Sdrh     if( iExp>0 ){
145beb9def0Sdrh       p->a = sqlite3_realloc64(p->a, p->nDigit + iExp + 1 );
146beb9def0Sdrh       if( p->a==0 ) goto new_no_mem;
147beb9def0Sdrh       memset(p->a+p->nDigit, 0, iExp);
148beb9def0Sdrh       p->nDigit += iExp;
149beb9def0Sdrh     }
150beb9def0Sdrh   }else if( iExp<0 ){
151beb9def0Sdrh     int nExtra;
152beb9def0Sdrh     iExp = -iExp;
153beb9def0Sdrh     nExtra = p->nDigit - p->nFrac - 1;
154beb9def0Sdrh     if( nExtra ){
155beb9def0Sdrh       if( nExtra>=iExp ){
156beb9def0Sdrh         p->nFrac += iExp;
157beb9def0Sdrh         iExp  = 0;
158beb9def0Sdrh       }else{
159beb9def0Sdrh         iExp -= nExtra;
160beb9def0Sdrh         p->nFrac = p->nDigit - 1;
161beb9def0Sdrh       }
162beb9def0Sdrh     }
163beb9def0Sdrh     if( iExp>0 ){
164beb9def0Sdrh       p->a = sqlite3_realloc64(p->a, p->nDigit + iExp + 1 );
165beb9def0Sdrh       if( p->a==0 ) goto new_no_mem;
166beb9def0Sdrh       memmove(p->a+iExp, p->a, p->nDigit);
167beb9def0Sdrh       memset(p->a, 0, iExp);
168beb9def0Sdrh       p->nDigit += iExp;
169beb9def0Sdrh       p->nFrac += iExp;
170beb9def0Sdrh     }
171beb9def0Sdrh   }
172beb9def0Sdrh   return p;
173beb9def0Sdrh 
174beb9def0Sdrh new_no_mem:
175beb9def0Sdrh   if( pCtx ) sqlite3_result_error_nomem(pCtx);
176beb9def0Sdrh   sqlite3_free(p);
177beb9def0Sdrh   return 0;
178beb9def0Sdrh }
179beb9def0Sdrh 
180beb9def0Sdrh /*
181beb9def0Sdrh ** Make the given Decimal the result.
182beb9def0Sdrh */
decimal_result(sqlite3_context * pCtx,Decimal * p)183beb9def0Sdrh static void decimal_result(sqlite3_context *pCtx, Decimal *p){
184beb9def0Sdrh   char *z;
185beb9def0Sdrh   int i, j;
186beb9def0Sdrh   int n;
187beb9def0Sdrh   if( p==0 || p->oom ){
188beb9def0Sdrh     sqlite3_result_error_nomem(pCtx);
189beb9def0Sdrh     return;
190beb9def0Sdrh   }
191beb9def0Sdrh   if( p->isNull ){
192beb9def0Sdrh     sqlite3_result_null(pCtx);
193beb9def0Sdrh     return;
194beb9def0Sdrh   }
195beb9def0Sdrh   z = sqlite3_malloc( p->nDigit+4 );
196beb9def0Sdrh   if( z==0 ){
197beb9def0Sdrh     sqlite3_result_error_nomem(pCtx);
198beb9def0Sdrh     return;
199beb9def0Sdrh   }
200beb9def0Sdrh   i = 0;
201beb9def0Sdrh   if( p->nDigit==0 || (p->nDigit==1 && p->a[0]==0) ){
202beb9def0Sdrh     p->sign = 0;
203beb9def0Sdrh   }
204beb9def0Sdrh   if( p->sign ){
205beb9def0Sdrh     z[0] = '-';
206beb9def0Sdrh     i = 1;
207beb9def0Sdrh   }
208beb9def0Sdrh   n = p->nDigit - p->nFrac;
209beb9def0Sdrh   if( n<=0 ){
210beb9def0Sdrh     z[i++] = '0';
211beb9def0Sdrh   }
212beb9def0Sdrh   j = 0;
2136b647186Sdrh   while( n>1 && p->a[j]==0 ){
2146b647186Sdrh     j++;
2156b647186Sdrh     n--;
2166b647186Sdrh   }
217beb9def0Sdrh   while( n>0  ){
218beb9def0Sdrh     z[i++] = p->a[j] + '0';
219beb9def0Sdrh     j++;
220beb9def0Sdrh     n--;
221beb9def0Sdrh   }
222beb9def0Sdrh   if( p->nFrac ){
223beb9def0Sdrh     z[i++] = '.';
224beb9def0Sdrh     do{
225beb9def0Sdrh       z[i++] = p->a[j] + '0';
226beb9def0Sdrh       j++;
227beb9def0Sdrh     }while( j<p->nDigit );
228beb9def0Sdrh   }
229beb9def0Sdrh   z[i] = 0;
230beb9def0Sdrh   sqlite3_result_text(pCtx, z, i, sqlite3_free);
231beb9def0Sdrh }
232beb9def0Sdrh 
233beb9def0Sdrh /*
234beb9def0Sdrh ** SQL Function:   decimal(X)
235beb9def0Sdrh **
236beb9def0Sdrh ** Convert input X into decimal and then back into text
237beb9def0Sdrh */
decimalFunc(sqlite3_context * context,int argc,sqlite3_value ** argv)238beb9def0Sdrh static void decimalFunc(
239beb9def0Sdrh   sqlite3_context *context,
240beb9def0Sdrh   int argc,
241beb9def0Sdrh   sqlite3_value **argv
242beb9def0Sdrh ){
243beb9def0Sdrh   Decimal *p = decimal_new(context, argv[0], 0, 0);
244a7c74006Sdrh   UNUSED_PARAMETER(argc);
245beb9def0Sdrh   decimal_result(context, p);
246beb9def0Sdrh   decimal_free(p);
247beb9def0Sdrh }
248beb9def0Sdrh 
249beb9def0Sdrh /*
250beb9def0Sdrh ** Compare to Decimal objects.  Return negative, 0, or positive if the
251beb9def0Sdrh ** first object is less than, equal to, or greater than the second.
252beb9def0Sdrh **
253beb9def0Sdrh ** Preconditions for this routine:
254beb9def0Sdrh **
255beb9def0Sdrh **    pA!=0
256beb9def0Sdrh **    pA->isNull==0
257beb9def0Sdrh **    pB!=0
258beb9def0Sdrh **    pB->isNull==0
259beb9def0Sdrh */
decimal_cmp(const Decimal * pA,const Decimal * pB)260beb9def0Sdrh static int decimal_cmp(const Decimal *pA, const Decimal *pB){
261beb9def0Sdrh   int nASig, nBSig, rc, n;
262beb9def0Sdrh   if( pA->sign!=pB->sign ){
263beb9def0Sdrh     return pA->sign ? -1 : +1;
264beb9def0Sdrh   }
265beb9def0Sdrh   if( pA->sign ){
266beb9def0Sdrh     const Decimal *pTemp = pA;
267beb9def0Sdrh     pA = pB;
268beb9def0Sdrh     pB = pTemp;
269beb9def0Sdrh   }
270beb9def0Sdrh   nASig = pA->nDigit - pA->nFrac;
271beb9def0Sdrh   nBSig = pB->nDigit - pB->nFrac;
272beb9def0Sdrh   if( nASig!=nBSig ){
273beb9def0Sdrh     return nASig - nBSig;
274beb9def0Sdrh   }
275beb9def0Sdrh   n = pA->nDigit;
276beb9def0Sdrh   if( n>pB->nDigit ) n = pB->nDigit;
277beb9def0Sdrh   rc = memcmp(pA->a, pB->a, n);
278beb9def0Sdrh   if( rc==0 ){
279beb9def0Sdrh     rc = pA->nDigit - pB->nDigit;
280beb9def0Sdrh   }
281beb9def0Sdrh   return rc;
282beb9def0Sdrh }
283beb9def0Sdrh 
284beb9def0Sdrh /*
285beb9def0Sdrh ** SQL Function:   decimal_cmp(X, Y)
286beb9def0Sdrh **
287beb9def0Sdrh ** Return negative, zero, or positive if X is less then, equal to, or
288beb9def0Sdrh ** greater than Y.
289beb9def0Sdrh */
decimalCmpFunc(sqlite3_context * context,int argc,sqlite3_value ** argv)290beb9def0Sdrh static void decimalCmpFunc(
291beb9def0Sdrh   sqlite3_context *context,
292beb9def0Sdrh   int argc,
293beb9def0Sdrh   sqlite3_value **argv
294beb9def0Sdrh ){
295beb9def0Sdrh   Decimal *pA = 0, *pB = 0;
296beb9def0Sdrh   int rc;
297beb9def0Sdrh 
298a7c74006Sdrh   UNUSED_PARAMETER(argc);
299beb9def0Sdrh   pA = decimal_new(context, argv[0], 0, 0);
300beb9def0Sdrh   if( pA==0 || pA->isNull ) goto cmp_done;
301beb9def0Sdrh   pB = decimal_new(context, argv[1], 0, 0);
302beb9def0Sdrh   if( pB==0 || pB->isNull ) goto cmp_done;
303beb9def0Sdrh   rc = decimal_cmp(pA, pB);
304beb9def0Sdrh   if( rc<0 ) rc = -1;
305beb9def0Sdrh   else if( rc>0 ) rc = +1;
306beb9def0Sdrh   sqlite3_result_int(context, rc);
307beb9def0Sdrh cmp_done:
308beb9def0Sdrh   decimal_free(pA);
309beb9def0Sdrh   decimal_free(pB);
310beb9def0Sdrh }
311beb9def0Sdrh 
312beb9def0Sdrh /*
313beb9def0Sdrh ** Expand the Decimal so that it has a least nDigit digits and nFrac
314beb9def0Sdrh ** digits to the right of the decimal point.
315beb9def0Sdrh */
decimal_expand(Decimal * p,int nDigit,int nFrac)316beb9def0Sdrh static void decimal_expand(Decimal *p, int nDigit, int nFrac){
317beb9def0Sdrh   int nAddSig;
318beb9def0Sdrh   int nAddFrac;
319beb9def0Sdrh   if( p==0 ) return;
320beb9def0Sdrh   nAddFrac = nFrac - p->nFrac;
321beb9def0Sdrh   nAddSig = (nDigit - p->nDigit) - nAddFrac;
322beb9def0Sdrh   if( nAddFrac==0 && nAddSig==0 ) return;
323beb9def0Sdrh   p->a = sqlite3_realloc64(p->a, nDigit+1);
324beb9def0Sdrh   if( p->a==0 ){
325beb9def0Sdrh     p->oom = 1;
326beb9def0Sdrh     return;
327beb9def0Sdrh   }
328beb9def0Sdrh   if( nAddSig ){
329beb9def0Sdrh     memmove(p->a+nAddSig, p->a, p->nDigit);
330beb9def0Sdrh     memset(p->a, 0, nAddSig);
331beb9def0Sdrh     p->nDigit += nAddSig;
332beb9def0Sdrh   }
333beb9def0Sdrh   if( nAddFrac ){
334beb9def0Sdrh     memset(p->a+p->nDigit, 0, nAddFrac);
335beb9def0Sdrh     p->nDigit += nAddFrac;
336beb9def0Sdrh     p->nFrac += nAddFrac;
337beb9def0Sdrh   }
338beb9def0Sdrh }
339beb9def0Sdrh 
340beb9def0Sdrh /*
341beb9def0Sdrh ** Add the value pB into pA.
342beb9def0Sdrh **
3436b647186Sdrh ** Both pA and pB might become denormalized by this routine.
344beb9def0Sdrh */
decimal_add(Decimal * pA,Decimal * pB)345beb9def0Sdrh static void decimal_add(Decimal *pA, Decimal *pB){
346beb9def0Sdrh   int nSig, nFrac, nDigit;
347beb9def0Sdrh   int i, rc;
348beb9def0Sdrh   if( pA==0 ){
349beb9def0Sdrh     return;
350beb9def0Sdrh   }
351beb9def0Sdrh   if( pA->oom || pB==0 || pB->oom ){
352beb9def0Sdrh     pA->oom = 1;
353beb9def0Sdrh     return;
354beb9def0Sdrh   }
355beb9def0Sdrh   if( pA->isNull || pB->isNull ){
356beb9def0Sdrh     pA->isNull = 1;
357beb9def0Sdrh     return;
358beb9def0Sdrh   }
359beb9def0Sdrh   nSig = pA->nDigit - pA->nFrac;
3606b647186Sdrh   if( nSig && pA->a[0]==0 ) nSig--;
3616b647186Sdrh   if( nSig<pB->nDigit-pB->nFrac ){
3626b647186Sdrh     nSig = pB->nDigit - pB->nFrac;
3636b647186Sdrh   }
364beb9def0Sdrh   nFrac = pA->nFrac;
365beb9def0Sdrh   if( nFrac<pB->nFrac ) nFrac = pB->nFrac;
366beb9def0Sdrh   nDigit = nSig + nFrac + 1;
367beb9def0Sdrh   decimal_expand(pA, nDigit, nFrac);
368beb9def0Sdrh   decimal_expand(pB, nDigit, nFrac);
369beb9def0Sdrh   if( pA->oom || pB->oom ){
370beb9def0Sdrh     pA->oom = 1;
371beb9def0Sdrh   }else{
372beb9def0Sdrh     if( pA->sign==pB->sign ){
373beb9def0Sdrh       int carry = 0;
374beb9def0Sdrh       for(i=nDigit-1; i>=0; i--){
375beb9def0Sdrh         int x = pA->a[i] + pB->a[i] + carry;
376beb9def0Sdrh         if( x>=10 ){
377beb9def0Sdrh           carry = 1;
378beb9def0Sdrh           pA->a[i] = x - 10;
379beb9def0Sdrh         }else{
380beb9def0Sdrh           carry = 0;
381beb9def0Sdrh           pA->a[i] = x;
382beb9def0Sdrh         }
383beb9def0Sdrh       }
384beb9def0Sdrh     }else{
385beb9def0Sdrh       signed char *aA, *aB;
386beb9def0Sdrh       int borrow = 0;
387beb9def0Sdrh       rc = memcmp(pA->a, pB->a, nDigit);
388beb9def0Sdrh       if( rc<0 ){
389beb9def0Sdrh         aA = pB->a;
390beb9def0Sdrh         aB = pA->a;
391beb9def0Sdrh         pA->sign = !pA->sign;
392beb9def0Sdrh       }else{
393beb9def0Sdrh         aA = pA->a;
394beb9def0Sdrh         aB = pB->a;
395beb9def0Sdrh       }
396beb9def0Sdrh       for(i=nDigit-1; i>=0; i--){
397beb9def0Sdrh         int x = aA[i] - aB[i] - borrow;
398beb9def0Sdrh         if( x<0 ){
399beb9def0Sdrh           pA->a[i] = x+10;
400beb9def0Sdrh           borrow = 1;
401beb9def0Sdrh         }else{
402beb9def0Sdrh           pA->a[i] = x;
403beb9def0Sdrh           borrow = 0;
404beb9def0Sdrh         }
405beb9def0Sdrh       }
406beb9def0Sdrh     }
407beb9def0Sdrh   }
408beb9def0Sdrh }
409beb9def0Sdrh 
410beb9def0Sdrh /*
411beb9def0Sdrh ** Compare text in decimal order.
412beb9def0Sdrh */
decimalCollFunc(void * notUsed,int nKey1,const void * pKey1,int nKey2,const void * pKey2)413beb9def0Sdrh static int decimalCollFunc(
414beb9def0Sdrh   void *notUsed,
415beb9def0Sdrh   int nKey1, const void *pKey1,
416beb9def0Sdrh   int nKey2, const void *pKey2
417beb9def0Sdrh ){
418beb9def0Sdrh   const unsigned char *zA = (const unsigned char*)pKey1;
419beb9def0Sdrh   const unsigned char *zB = (const unsigned char*)pKey2;
420beb9def0Sdrh   Decimal *pA = decimal_new(0, 0, nKey1, zA);
421beb9def0Sdrh   Decimal *pB = decimal_new(0, 0, nKey2, zB);
422beb9def0Sdrh   int rc;
423a7c74006Sdrh   UNUSED_PARAMETER(notUsed);
424beb9def0Sdrh   if( pA==0 || pB==0 ){
425beb9def0Sdrh     rc = 0;
426beb9def0Sdrh   }else{
427beb9def0Sdrh     rc = decimal_cmp(pA, pB);
428beb9def0Sdrh   }
429beb9def0Sdrh   decimal_free(pA);
430beb9def0Sdrh   decimal_free(pB);
431beb9def0Sdrh   return rc;
432beb9def0Sdrh }
433beb9def0Sdrh 
434beb9def0Sdrh 
435beb9def0Sdrh /*
436beb9def0Sdrh ** SQL Function:   decimal_add(X, Y)
437beb9def0Sdrh **                 decimal_sub(X, Y)
438beb9def0Sdrh **
439beb9def0Sdrh ** Return the sum or difference of X and Y.
440beb9def0Sdrh */
decimalAddFunc(sqlite3_context * context,int argc,sqlite3_value ** argv)441beb9def0Sdrh static void decimalAddFunc(
442beb9def0Sdrh   sqlite3_context *context,
443beb9def0Sdrh   int argc,
444beb9def0Sdrh   sqlite3_value **argv
445beb9def0Sdrh ){
446beb9def0Sdrh   Decimal *pA = decimal_new(context, argv[0], 0, 0);
447beb9def0Sdrh   Decimal *pB = decimal_new(context, argv[1], 0, 0);
448a7c74006Sdrh   UNUSED_PARAMETER(argc);
449beb9def0Sdrh   decimal_add(pA, pB);
450beb9def0Sdrh   decimal_result(context, pA);
451beb9def0Sdrh   decimal_free(pA);
452beb9def0Sdrh   decimal_free(pB);
453beb9def0Sdrh }
decimalSubFunc(sqlite3_context * context,int argc,sqlite3_value ** argv)454beb9def0Sdrh static void decimalSubFunc(
455beb9def0Sdrh   sqlite3_context *context,
456beb9def0Sdrh   int argc,
457beb9def0Sdrh   sqlite3_value **argv
458beb9def0Sdrh ){
459beb9def0Sdrh   Decimal *pA = decimal_new(context, argv[0], 0, 0);
460beb9def0Sdrh   Decimal *pB = decimal_new(context, argv[1], 0, 0);
461a7c74006Sdrh   UNUSED_PARAMETER(argc);
462*e103a8deSdrh   if( pB ){
463beb9def0Sdrh     pB->sign = !pB->sign;
464beb9def0Sdrh     decimal_add(pA, pB);
465beb9def0Sdrh     decimal_result(context, pA);
466*e103a8deSdrh   }
467beb9def0Sdrh   decimal_free(pA);
468beb9def0Sdrh   decimal_free(pB);
469beb9def0Sdrh }
470beb9def0Sdrh 
471beb9def0Sdrh /* Aggregate funcion:   decimal_sum(X)
472beb9def0Sdrh **
473beb9def0Sdrh ** Works like sum() except that it uses decimal arithmetic for unlimited
474beb9def0Sdrh ** precision.
475beb9def0Sdrh */
decimalSumStep(sqlite3_context * context,int argc,sqlite3_value ** argv)476beb9def0Sdrh static void decimalSumStep(
477beb9def0Sdrh   sqlite3_context *context,
478beb9def0Sdrh   int argc,
479beb9def0Sdrh   sqlite3_value **argv
480beb9def0Sdrh ){
481beb9def0Sdrh   Decimal *p;
482beb9def0Sdrh   Decimal *pArg;
483a7c74006Sdrh   UNUSED_PARAMETER(argc);
484beb9def0Sdrh   p = sqlite3_aggregate_context(context, sizeof(*p));
485beb9def0Sdrh   if( p==0 ) return;
486beb9def0Sdrh   if( !p->isInit ){
487beb9def0Sdrh     p->isInit = 1;
488beb9def0Sdrh     p->a = sqlite3_malloc(2);
489beb9def0Sdrh     if( p->a==0 ){
490beb9def0Sdrh       p->oom = 1;
491beb9def0Sdrh     }else{
492beb9def0Sdrh       p->a[0] = 0;
493beb9def0Sdrh     }
494beb9def0Sdrh     p->nDigit = 1;
495beb9def0Sdrh     p->nFrac = 0;
496beb9def0Sdrh   }
497beb9def0Sdrh   if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
498beb9def0Sdrh   pArg = decimal_new(context, argv[0], 0, 0);
499beb9def0Sdrh   decimal_add(p, pArg);
500beb9def0Sdrh   decimal_free(pArg);
501beb9def0Sdrh }
decimalSumInverse(sqlite3_context * context,int argc,sqlite3_value ** argv)502beb9def0Sdrh static void decimalSumInverse(
503beb9def0Sdrh   sqlite3_context *context,
504beb9def0Sdrh   int argc,
505beb9def0Sdrh   sqlite3_value **argv
506beb9def0Sdrh ){
507beb9def0Sdrh   Decimal *p;
508beb9def0Sdrh   Decimal *pArg;
509a7c74006Sdrh   UNUSED_PARAMETER(argc);
510beb9def0Sdrh   p = sqlite3_aggregate_context(context, sizeof(*p));
511beb9def0Sdrh   if( p==0 ) return;
512beb9def0Sdrh   if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
513beb9def0Sdrh   pArg = decimal_new(context, argv[0], 0, 0);
514beb9def0Sdrh   if( pArg ) pArg->sign = !pArg->sign;
515beb9def0Sdrh   decimal_add(p, pArg);
516beb9def0Sdrh   decimal_free(pArg);
517beb9def0Sdrh }
decimalSumValue(sqlite3_context * context)518beb9def0Sdrh static void decimalSumValue(sqlite3_context *context){
519beb9def0Sdrh   Decimal *p = sqlite3_aggregate_context(context, 0);
520beb9def0Sdrh   if( p==0 ) return;
521beb9def0Sdrh   decimal_result(context, p);
522beb9def0Sdrh }
decimalSumFinalize(sqlite3_context * context)523beb9def0Sdrh static void decimalSumFinalize(sqlite3_context *context){
524beb9def0Sdrh   Decimal *p = sqlite3_aggregate_context(context, 0);
525beb9def0Sdrh   if( p==0 ) return;
526beb9def0Sdrh   decimal_result(context, p);
527beb9def0Sdrh   decimal_clear(p);
528beb9def0Sdrh }
529beb9def0Sdrh 
530427af8dcSdrh /*
531427af8dcSdrh ** SQL Function:   decimal_mul(X, Y)
532427af8dcSdrh **
533427af8dcSdrh ** Return the product of X and Y.
5346b647186Sdrh **
5356b647186Sdrh ** All significant digits after the decimal point are retained.
5366b647186Sdrh ** Trailing zeros after the decimal point are omitted as long as
5376b647186Sdrh ** the number of digits after the decimal point is no less than
5386b647186Sdrh ** either the number of digits in either input.
539427af8dcSdrh */
decimalMulFunc(sqlite3_context * context,int argc,sqlite3_value ** argv)540427af8dcSdrh static void decimalMulFunc(
541427af8dcSdrh   sqlite3_context *context,
542427af8dcSdrh   int argc,
543427af8dcSdrh   sqlite3_value **argv
544427af8dcSdrh ){
545427af8dcSdrh   Decimal *pA = decimal_new(context, argv[0], 0, 0);
546427af8dcSdrh   Decimal *pB = decimal_new(context, argv[1], 0, 0);
547427af8dcSdrh   signed char *acc = 0;
548427af8dcSdrh   int i, j, k;
5496b647186Sdrh   int minFrac;
550a7c74006Sdrh   UNUSED_PARAMETER(argc);
551427af8dcSdrh   if( pA==0 || pA->oom || pA->isNull
552427af8dcSdrh    || pB==0 || pB->oom || pB->isNull
553427af8dcSdrh   ){
554427af8dcSdrh     goto mul_end;
555427af8dcSdrh   }
556427af8dcSdrh   acc = sqlite3_malloc64( pA->nDigit + pB->nDigit + 2 );
557427af8dcSdrh   if( acc==0 ){
558427af8dcSdrh     sqlite3_result_error_nomem(context);
559427af8dcSdrh     goto mul_end;
560427af8dcSdrh   }
561427af8dcSdrh   memset(acc, 0, pA->nDigit + pB->nDigit + 2);
5626b647186Sdrh   minFrac = pA->nFrac;
5636b647186Sdrh   if( pB->nFrac<minFrac ) minFrac = pB->nFrac;
564427af8dcSdrh   for(i=pA->nDigit-1; i>=0; i--){
565427af8dcSdrh     signed char f = pA->a[i];
566427af8dcSdrh     int carry = 0, x;
567427af8dcSdrh     for(j=pB->nDigit-1, k=i+j+3; j>=0; j--, k--){
568e78c027bSdrh       x = acc[k] + f*pB->a[j] + carry;
569427af8dcSdrh       acc[k] = x%10;
570427af8dcSdrh       carry = x/10;
571427af8dcSdrh     }
572427af8dcSdrh     x = acc[k] + carry;
573427af8dcSdrh     acc[k] = x%10;
574427af8dcSdrh     acc[k-1] += x/10;
575427af8dcSdrh   }
576427af8dcSdrh   sqlite3_free(pA->a);
577427af8dcSdrh   pA->a = acc;
578427af8dcSdrh   acc = 0;
579427af8dcSdrh   pA->nDigit += pB->nDigit + 2;
580427af8dcSdrh   pA->nFrac += pB->nFrac;
581427af8dcSdrh   pA->sign ^= pB->sign;
5826b647186Sdrh   while( pA->nFrac>minFrac && pA->a[pA->nDigit-1]==0 ){
5836b647186Sdrh     pA->nFrac--;
5846b647186Sdrh     pA->nDigit--;
5856b647186Sdrh   }
586427af8dcSdrh   decimal_result(context, pA);
587427af8dcSdrh 
588427af8dcSdrh mul_end:
589427af8dcSdrh   sqlite3_free(acc);
590427af8dcSdrh   decimal_free(pA);
591427af8dcSdrh   decimal_free(pB);
592427af8dcSdrh }
593beb9def0Sdrh 
594beb9def0Sdrh #ifdef _WIN32
595beb9def0Sdrh __declspec(dllexport)
596beb9def0Sdrh #endif
sqlite3_decimal_init(sqlite3 * db,char ** pzErrMsg,const sqlite3_api_routines * pApi)597beb9def0Sdrh int sqlite3_decimal_init(
598beb9def0Sdrh   sqlite3 *db,
599beb9def0Sdrh   char **pzErrMsg,
600beb9def0Sdrh   const sqlite3_api_routines *pApi
601beb9def0Sdrh ){
602beb9def0Sdrh   int rc = SQLITE_OK;
603beb9def0Sdrh   static const struct {
604beb9def0Sdrh     const char *zFuncName;
605beb9def0Sdrh     int nArg;
606beb9def0Sdrh     void (*xFunc)(sqlite3_context*,int,sqlite3_value**);
607beb9def0Sdrh   } aFunc[] = {
608beb9def0Sdrh     { "decimal",       1,   decimalFunc        },
609beb9def0Sdrh     { "decimal_cmp",   2,   decimalCmpFunc     },
610beb9def0Sdrh     { "decimal_add",   2,   decimalAddFunc     },
611beb9def0Sdrh     { "decimal_sub",   2,   decimalSubFunc     },
612427af8dcSdrh     { "decimal_mul",   2,   decimalMulFunc     },
613beb9def0Sdrh   };
614a7c74006Sdrh   unsigned int i;
615beb9def0Sdrh   (void)pzErrMsg;  /* Unused parameter */
616beb9def0Sdrh 
6177033ce4fSdrh   SQLITE_EXTENSION_INIT2(pApi);
6187033ce4fSdrh 
619beb9def0Sdrh   for(i=0; i<sizeof(aFunc)/sizeof(aFunc[0]) && rc==SQLITE_OK; i++){
620beb9def0Sdrh     rc = sqlite3_create_function(db, aFunc[i].zFuncName, aFunc[i].nArg,
621beb9def0Sdrh                    SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_DETERMINISTIC,
622beb9def0Sdrh                    0, aFunc[i].xFunc, 0, 0);
623beb9def0Sdrh   }
624beb9def0Sdrh   if( rc==SQLITE_OK ){
625beb9def0Sdrh     rc = sqlite3_create_window_function(db, "decimal_sum", 1,
626beb9def0Sdrh                    SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_DETERMINISTIC, 0,
627beb9def0Sdrh                    decimalSumStep, decimalSumFinalize,
628beb9def0Sdrh                    decimalSumValue, decimalSumInverse, 0);
629beb9def0Sdrh   }
630beb9def0Sdrh   if( rc==SQLITE_OK ){
631beb9def0Sdrh     rc = sqlite3_create_collation(db, "decimal", SQLITE_UTF8,
632beb9def0Sdrh                                   0, decimalCollFunc);
633beb9def0Sdrh   }
634beb9def0Sdrh   return rc;
635beb9def0Sdrh }
636