[prev in list] [next in list] [prev in thread] [next in thread] 

List:       sqlite-dev
Subject:    [sqlite-dev] Patch to allow sqlite to be compiled with _Decimal64 or double controlled by definition
From:       Domingo Alvarez Duarte <mingodad () gmail ! com>
Date:       2011-12-17 18:17:43
Message-ID: CALCTSagcYCM2KFkEXB82ADEhXVCq=Myt0BQVx5_p5Gr5MG-1uA () mail ! gmail ! com
[Download RAW message or body]

Here is a patch that allow sqlite3 be compiled to use _Decimal64 or
double controlled be definition of SQLITE_USE_DECIMAl.

What the patch does is replace any occurrence of double and change it
by sqlite_double this way we can redefine it to whatever makes sense
(instead of the redefinition of "double" keyword) and define another
macro to surround floating point literals LITDBL(n) when used for
_Decimal64 has this value n##dd otherwise the parameter replaced
without any modification.

It compiles cleanly but the results when using _Decimal64 are wrong
more work should be done to discover the problem also on windows the
executable size goes from around 500KB without _Decimal64 to 3MB with
_Decimal64, more work should be done to discover why it's giving wrong
results with _Decima64.

Even without working properly I think the patch has merit to enter on
the official sqlite3 repository.

Thanks for any help/comments/sugestions !

["sqlite3-gcc-decimal.patch" (application/octet-stream)]

Index: src/date.c
==================================================================
--- src/date.c
+++ src/date.c
@@ -58,11 +58,11 @@
 struct DateTime {
   sqlite3_int64 iJD; /* The julian day number times 86400000 */
   int Y, M, D;       /* Year, month, and day */
   int h, m;          /* Hour and minutes */
   int tz;            /* Timezone offset in minutes */
-  double s;          /* Seconds */
+  sqlite_double  s;          /* Seconds */
   char validYMD;     /* True (1) if Y,M,D are valid */
   char validHMS;     /* True (1) if h,m,s are valid */
   char validJD;      /* True (1) if iJD is valid */
   char validTZ;      /* True (1) if tz is valid */
 };
@@ -168,11 +168,11 @@
 **
 ** Return 1 if there is a parsing error and 0 on success.
 */
 static int parseHhMmSs(const char *zDate, DateTime *p){
   int h, m, s;
-  double ms = 0.0;
+  sqlite_double  ms = 0.0;
   if( getDigits(zDate, 2, 0, 24, ':', &h, 2, 0, 59, 0, &m)!=2 ){
     return 1;
   }
   zDate += 5;
   if( *zDate==':' ){
@@ -180,15 +180,15 @@
     if( getDigits(zDate, 2, 0, 59, 0, &s)!=1 ){
       return 1;
     }
     zDate += 2;
     if( *zDate=='.' && sqlite3Isdigit(zDate[1]) ){
-      double rScale = 1.0;
+      sqlite_double  rScale = 1.0;
       zDate++;
       while( sqlite3Isdigit(*zDate) ){
-        ms = ms*10.0 + *zDate - '0';
-        rScale *= 10.0;
+        ms = ms*LITDBL(10.0) + *zDate - '0';
+        rScale *= LITDBL(10.0);
         zDate++;
       }
       ms /= rScale;
     }
   }else{
@@ -229,11 +229,11 @@
   }
   A = Y/100;
   B = 2 - A + (A/4);
   X1 = 36525*(Y+4716)/100;
   X2 = 306001*(M+1)/10000;
-  p->iJD = (sqlite3_int64)((X1 + X2 + D + B - 1524.5 ) * 86400000);
+  p->iJD = (sqlite3_int64)((X1 + X2 + D + B - LITDBL(1524.5) ) * \
86400000);  p->validJD = 1;
   if( p->validHMS ){
     p->iJD += p->h*3600000 + p->m*60000 + (sqlite3_int64)(p->s*1000);
     if( p->validTZ ){
       p->iJD -= p->tz*60000;
@@ -322,19 +322,19 @@
 static int parseDateOrTime(
   sqlite3_context *context, 
   const char *zDate, 
   DateTime *p
 ){
-  double r;
+  sqlite_double  r;
   if( parseYyyyMmDd(zDate,p)==0 ){
     return 0;
   }else if( parseHhMmSs(zDate, p)==0 ){
     return 0;
   }else if( sqlite3StrICmp(zDate,"now")==0){
     return setDateTimeToCurrent(context, p);
   }else if( sqlite3AtoF(zDate, &r, sqlite3Strlen30(zDate), SQLITE_UTF8) ){
-    p->iJD = (sqlite3_int64)(r*86400000.0 + 0.5);
+    p->iJD = (sqlite3_int64)(r*LITDBL(86400000.0) + LITDBL(0.5));
     p->validJD = 1;
     return 0;
   }
   return 1;
 }
@@ -349,17 +349,17 @@
     p->Y = 2000;
     p->M = 1;
     p->D = 1;
   }else{
     Z = (int)((p->iJD + 43200000)/86400000);
-    A = (int)((Z - 1867216.25)/36524.25);
+    A = (int)((Z - LITDBL(1867216.25))/LITDBL(36524.25));
     A = Z + 1 + A - (A/4);
     B = A + 1524;
-    C = (int)((B - 122.1)/365.25);
+    C = (int)((B - LITDBL(122.1))/LITDBL(365.25));
     D = (36525*C)/100;
-    E = (int)((B-D)/30.6001);
-    X1 = (int)(30.6001*E);
+    E = (int)((B-D)/LITDBL(30.6001));
+    X1 = (int)(LITDBL(30.6001)*E);
     p->D = B - D - X1;
     p->M = E<14 ? E-1 : E-13;
     p->Y = p->M>2 ? C - 4716 : C - 4715;
   }
   p->validYMD = 1;
@@ -371,11 +371,11 @@
 static void computeHMS(DateTime *p){
   int s;
   if( p->validHMS ) return;
   computeJD(p);
   s = (int)((p->iJD + 43200000) % 86400000);
-  p->s = s/1000.0;
+  p->s = s/LITDBL(1000.0);
   s = (int)p->s;
   p->s -= s;
   p->h = s/3600;
   s -= p->h*3600;
   p->m = s/60;
@@ -485,13 +485,13 @@
     x.Y = 2000;
     x.M = 1;
     x.D = 1;
     x.h = 0;
     x.m = 0;
-    x.s = 0.0;
+    x.s = LITDBL(0.0);
   } else {
-    int s = (int)(x.s + 0.5);
+    int s = (int)(x.s + LITDBL(0.5));
     x.s = s;
   }
   x.tz = 0;
   x.validJD = 0;
   computeJD(&x);
@@ -542,11 +542,11 @@
 ** written to pCtx.
 */
 static int parseModifier(sqlite3_context *pCtx, const char *zMod, DateTime \
*p){  int rc = 1;
   int n;
-  double r;
+  sqlite_double  r;
   char *z, zBuf[30];
   z = zBuf;
   for(n=0; n<ArraySize(zBuf)-1 && zMod[n]; n++){
     z[n] = (char)sqlite3UpperToLower[(u8)zMod[n]];
   }
@@ -655,11 +655,11 @@
     case '5':
     case '6':
     case '7':
     case '8':
     case '9': {
-      double rRounder;
+      sqlite_double  rRounder;
       for(n=1; z[n] && z[n]!=':' && !sqlite3Isspace(z[n]); n++){}
       if( !sqlite3AtoF(z, &r, n, SQLITE_UTF8) ){
         rc = 1;
         break;
       }
@@ -691,19 +691,19 @@
       n = sqlite3Strlen30(z);
       if( n>10 || n<3 ) break;
       if( z[n-1]=='s' ){ z[n-1] = 0; n--; }
       computeJD(p);
       rc = 0;
-      rRounder = r<0 ? -0.5 : +0.5;
+      rRounder = r<0 ? LITDBL(-0.5) : LITDBL(+0.5);
       if( n==3 && strcmp(z,"day")==0 ){
-        p->iJD += (sqlite3_int64)(r*86400000.0 + rRounder);
+        p->iJD += (sqlite3_int64)(r*LITDBL(86400000.0) + rRounder);
       }else if( n==4 && strcmp(z,"hour")==0 ){
-        p->iJD += (sqlite3_int64)(r*(86400000.0/24.0) + rRounder);
+        p->iJD += (sqlite3_int64)(r*(LITDBL(86400000.0)/LITDBL(24.0)) + \
rRounder);  }else if( n==6 && strcmp(z,"minute")==0 ){
-        p->iJD += (sqlite3_int64)(r*(86400000.0/(24.0*60.0)) + rRounder);
+        p->iJD += (sqlite3_int64)(r*(LITDBL(86400000.0)/(LITDBL(24.0)*LITDBL(60.0))) \
+ rRounder);  }else if( n==6 && strcmp(z,"second")==0 ){
-        p->iJD += (sqlite3_int64)(r*(86400000.0/(24.0*60.0*60.0)) + \
rRounder); +        p->iJD += \
(sqlite3_int64)(r*(LITDBL(86400000.0)/(LITDBL(24.0)*LITDBL(60.0)*LITDBL(60.0))) \
+ rRounder);  }else if( n==5 && strcmp(z,"month")==0 ){
         int x, y;
         computeYMD_HMS(p);
         p->M += (int)r;
         x = p->M>0 ? (p->M-1)/12 : (p->M-12)/12;
@@ -711,20 +711,20 @@
         p->M -= x*12;
         p->validJD = 0;
         computeJD(p);
         y = (int)r;
         if( y!=r ){
-          p->iJD += (sqlite3_int64)((r - y)*30.0*86400000.0 + rRounder);
+          p->iJD += (sqlite3_int64)((r - \
y)*LITDBL(30.0)*LITDBL(86400000.0) + rRounder);  }
       }else if( n==4 && strcmp(z,"year")==0 ){
         int y = (int)r;
         computeYMD_HMS(p);
         p->Y += y;
         p->validJD = 0;
         computeJD(p);
         if( y!=r ){
-          p->iJD += (sqlite3_int64)((r - y)*365.0*86400000.0 + rRounder);
+          p->iJD += (sqlite3_int64)((r - \
y)*LITDBL(365.0)*LITDBL(86400000.0) + rRounder);  }
       }else{
         rc = 1;
       }
       clearYMD_HMS_TZ(p);
@@ -759,11 +759,11 @@
   if( argc==0 ){
     return setDateTimeToCurrent(context, p);
   }
   if( (eType = sqlite3_value_type(argv[0]))==SQLITE_FLOAT
                    || eType==SQLITE_INTEGER ){
-    p->iJD = (sqlite3_int64)(sqlite3_value_double(argv[0])*86400000.0 + \
0.5); +    p->iJD = (sqlite3_int64)(sqlite3_value_double(argv[0])*LITDBL(86400000.0) \
+ LITDBL(0.5));  p->validJD = 1;
   }else{
     z = sqlite3_value_text(argv[0]);
     if( !z || parseDateOrTime(context, (char*)z, p) ){
       return 1;
@@ -793,11 +793,11 @@
   sqlite3_value **argv
 ){
   DateTime x;
   if( isDate(context, argc, argv, &x)==0 ){
     computeJD(&x);
-    sqlite3_result_double(context, x.iJD/86400000.0);
+    sqlite3_result_double(context, x.iJD/LITDBL(86400000.0));
   }
 }
 
 /*
 **    datetime( TIMESTRING, MOD, MOD, ...)
@@ -947,12 +947,12 @@
     }else{
       i++;
       switch( zFmt[i] ){
         case 'd':  sqlite3_snprintf(3, &z[j],"%02d",x.D); j+=2; break;
         case 'f': {
-          double s = x.s;
-          if( s>59.999 ) s = 59.999;
+          sqlite_double  s = x.s;
+          if( s>LITDBL(59.999) ) s = LITDBL(59.999);
           sqlite3_snprintf(7, &z[j],"%06.3f", s);
           j += sqlite3Strlen30(&z[j]);
           break;
         }
         case 'H':  sqlite3_snprintf(3, &z[j],"%02d",x.h); j+=2; break;
@@ -975,11 +975,11 @@
             j += 3;
           }
           break;
         }
         case 'J': {
-          sqlite3_snprintf(20, &z[j],"%.16g",x.iJD/86400000.0);
+          sqlite3_snprintf(20, &z[j],"%.16g",x.iJD/LITDBL(86400000.0));
           j+=sqlite3Strlen30(&z[j]);
           break;
         }
         case 'm':  sqlite3_snprintf(3, &z[j],"%02d",x.M); j+=2; break;
         case 'M':  sqlite3_snprintf(3, &z[j],"%02d",x.m); j+=2; break;

Index: src/func.c
==================================================================
--- src/func.c
+++ src/func.c
@@ -150,11 +150,11 @@
       /* Because sqlite3_value_double() returns 0.0 if the argument is not
       ** something that can be converted into a number, we have:
       ** IMP: R-57326-31541 Abs(X) return 0.0 if X is a string or blob \
                that
       ** cannot be converted to a numeric value. 
       */
-      double rVal = sqlite3_value_double(argv[0]);
+      sqlite_double  rVal = sqlite3_value_double(argv[0]);
       if( rVal<0 ) rVal = -rVal;
       sqlite3_result_double(context, rVal);
       break;
     }
   }
@@ -258,11 +258,11 @@
 ** Implementation of the round() function
 */
 #ifndef SQLITE_OMIT_FLOATING_POINT
 static void roundFunc(sqlite3_context *context, int argc, sqlite3_value \
**argv){  int n = 0;
-  double r;
+  sqlite_double  r;
   char *zBuf;
   assert( argc==1 || argc==2 );
   if( argc==2 ){
     if( SQLITE_NULL==sqlite3_value_type(argv[1]) ) return;
     n = sqlite3_value_int(argv[1]);
@@ -274,13 +274,13 @@
   /* If Y==0 and X will fit in a 64-bit int,
   ** handle the rounding directly,
   ** otherwise use printf.
   */
   if( n==0 && r>=0 && r<LARGEST_INT64-1 ){
-    r = (double)((sqlite_int64)(r+0.5));
+    r = (sqlite_double )((sqlite_int64)(r+LITDBL(0.5)));
   }else if( n==0 && r<0 && (-r)<LARGEST_INT64-1 ){
-    r = -(double)((sqlite_int64)((-r)+0.5));
+    r = -(sqlite_double )((sqlite_int64)((-r)+LITDBL(0.5)));
   }else{
     zBuf = sqlite3_mprintf("%.*f",n,r);
     if( zBuf==0 ){
       sqlite3_result_error_nomem(context);
       return;
@@ -1221,11 +1221,11 @@
 ** An instance of the following structure holds the context of a
 ** sum() or avg() aggregate computation.
 */
 typedef struct SumCtx SumCtx;
 struct SumCtx {
-  double rSum;      /* Floating point sum */
+  sqlite_double  rSum;      /* Floating point sum */
   i64 iSum;         /* Integer sum */   
   i64 cnt;          /* Number of elements summed */
   u8 overflow;      /* True if integer overflow seen */
   u8 approx;        /* True if non-integer value was input to the sum */
 };
@@ -1276,18 +1276,18 @@
 }
 static void avgFinalize(sqlite3_context *context){
   SumCtx *p;
   p = sqlite3_aggregate_context(context, 0);
   if( p && p->cnt>0 ){
-    sqlite3_result_double(context, p->rSum/(double)p->cnt);
+    sqlite3_result_double(context, p->rSum/(sqlite_double )p->cnt);
   }
 }
 static void totalFinalize(sqlite3_context *context){
   SumCtx *p;
   p = sqlite3_aggregate_context(context, 0);
-  /* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */
-  sqlite3_result_double(context, p ? p->rSum : (double)0);
+  /* (sqlite_double )0 In case of SQLITE_OMIT_FLOATING_POINT... */
+  sqlite3_result_double(context, p ? p->rSum : (sqlite_double )0);
 }
 
 /*
 ** The following structure keeps track of state information for the
 ** count() aggregate function.

Index: src/os.c
==================================================================
--- src/os.c
+++ src/os.c
@@ -201,13 +201,13 @@
   ** unavailable.
   */
   if( pVfs->iVersion>=2 && pVfs->xCurrentTimeInt64 ){
     rc = pVfs->xCurrentTimeInt64(pVfs, pTimeOut);
   }else{
-    double r;
+    sqlite_double  r;
     rc = pVfs->xCurrentTime(pVfs, &r);
-    *pTimeOut = (sqlite3_int64)(r*86400000.0);
+    *pTimeOut = (sqlite3_int64)(r*LITDBL(86400000.0));
   }
   return rc;
 }
 
 int sqlite3OsOpenMalloc(

Index: src/printf.c
==================================================================
--- src/printf.c
+++ src/printf.c
@@ -107,11 +107,11 @@
 ** If SQLITE_OMIT_FLOATING_POINT is defined, then none of the floating \
                point
 ** conversions will work.
 */
 #ifndef SQLITE_OMIT_FLOATING_POINT
 /*
-** "*val" is a double such that 0.1 <= *val < 10.0
+** "*val" is a sqlite_double  such that 0.1 <= *val < 10.0
 ** Return the ascii code for the leading digit of *val, then
 ** multiply "*val" by 10.0 to renormalize.
 **
 ** Example:
 **     input:     *val = 3.14159
@@ -122,15 +122,15 @@
 ** always returned.
 */
 static char et_getdigit(LONGDOUBLE_TYPE *val, int *cnt){
   int digit;
   LONGDOUBLE_TYPE d;
-  if( (*cnt)++ >= 16 ) return '0';
+  if( (*cnt)++ >= DOUBLE_SIGNIFICANT_DIGITS ) return '0';
   digit = (int)*val;
   d = digit;
   digit += '0';
-  *val = (*val - d)*10.0;
+  *val = (*val - d)*LITDBL(10.0);
   return (char)digit;
 }
 #endif /* SQLITE_OMIT_FLOATING_POINT */
 
 /*
@@ -189,11 +189,11 @@
   int nOut;                  /* Size of the rendering buffer */
   char *zExtra;              /* Malloced memory used by some conversion */
 #ifndef SQLITE_OMIT_FLOATING_POINT
   int  exp, e2;              /* exponent of real numbers */
   int nsd;                   /* Number of significant digits returned */
-  double rounder;            /* Used for rounding floating point values */
+  sqlite_double  rounder;            /* Used for rounding floating point \
values */  etByte flag_dp;            /* True if decimal point should be \
shown */  etByte flag_rtz;           /* True if trailing zeros should be \
removed */  #endif
   char buf[etBUFSIZE];       /* Conversion buffer */
 
@@ -396,16 +396,16 @@
         length = (int)(&zOut[nOut-1]-bufpt);
         break;
       case etFLOAT:
       case etEXP:
       case etGENERIC:
-        realvalue = va_arg(ap,double);
+        realvalue = va_arg(ap,sqlite_double );
 #ifdef SQLITE_OMIT_FLOATING_POINT
         length = 0;
 #else
         if( precision<0 ) precision = 6;         /* Set default precision \
                */
-        if( realvalue<0.0 ){
+        if( realvalue<LITDBL(0.0) ){
           realvalue = -realvalue;
           prefix = '-';
         }else{
           if( flag_plussign )          prefix = '+';
           else if( flag_blanksign )    prefix = ' ';
@@ -412,29 +412,29 @@
           else                         prefix = 0;
         }
         if( xtype==etGENERIC && precision>0 ) precision--;
 #if 0
         /* Rounding works like BSD when the constant 0.4999 is used.  \
                Wierd! */
-        for(idx=precision, rounder=0.4999; idx>0; idx--, rounder*=0.1);
+        for(idx=precision, rounder=LITDBL(0.4999); idx>0; idx--, \
rounder*=LITDBL(0.1));  #else
         /* It makes more sense to use 0.5 */
-        for(idx=precision, rounder=0.5; idx>0; idx--, rounder*=0.1){}
+        for(idx=precision, rounder=LITDBL(0.5); idx>0; idx--, \
rounder*=LITDBL(0.1)){}  #endif
         if( xtype==etFLOAT ) realvalue += rounder;
         /* Normalize realvalue to within 10.0 > realvalue >= 1.0 */
         exp = 0;
-        if( sqlite3IsNaN((double)realvalue) ){
+        if( sqlite3IsNaN((sqlite_double )realvalue) ){
           bufpt = "NaN";
           length = 3;
           break;
         }
-        if( realvalue>0.0 ){
-          while( realvalue>=1e32 && exp<=350 ){ realvalue *= 1e-32; \
                exp+=32; }
-          while( realvalue>=1e8 && exp<=350 ){ realvalue *= 1e-8; exp+=8; \
                }
-          while( realvalue>=10.0 && exp<=350 ){ realvalue *= 0.1; exp++; }
-          while( realvalue<1e-8 ){ realvalue *= 1e8; exp-=8; }
-          while( realvalue<1.0 ){ realvalue *= 10.0; exp--; }
+        if( realvalue>LITDBL(0.0) ){
+          while( realvalue>=LITDBL(1e32) && exp<=350 ){ realvalue *= \
LITDBL(1e-32); exp+=32; } +          while( realvalue>=LITDBL(1e8) && \
exp<=350 ){ realvalue *= LITDBL(1e-8); exp+=8; } +          while( \
realvalue>=LITDBL(10.0) && exp<=350 ){ realvalue *= LITDBL(0.1); exp++; } + \
while( realvalue<LITDBL(1e-8) ){ realvalue *= LITDBL(1e8); exp-=8; } +      \
while( realvalue<LITDBL(1.0) ){ realvalue *= LITDBL(10.0); exp--; }  if( \
exp>350 ){  if( prefix=='-' ){
               bufpt = "-Inf";
             }else if( prefix=='+' ){
               bufpt = "+Inf";
@@ -450,11 +450,11 @@
         ** If the field type is etGENERIC, then convert to either etEXP
         ** or etFLOAT, as appropriate.
         */
         if( xtype!=etFLOAT ){
           realvalue += rounder;
-          if( realvalue>=10.0 ){ realvalue *= 0.1; exp++; }
+          if( realvalue>=LITDBL(10.0) ){ realvalue *= LITDBL(0.1); exp++; \
}  }
         if( xtype==etGENERIC ){
           flag_rtz = !flag_alternateform;
           if( exp<-4 || exp>precision ){
             xtype = etEXP;

Index: src/sqlite.h.in
==================================================================
--- src/sqlite.h.in
+++ src/sqlite.h.in
@@ -253,11 +253,21 @@
 /*
 ** If compiling for a processor that lacks floating point support,
 ** substitute integer for floating-point.
 */
 #ifdef SQLITE_OMIT_FLOATING_POINT
-# define double sqlite3_int64
+# define sqlite_double  sqlite3_int64
+#else
+# ifdef SQLITE_USE_DECIMAL
+#  define sqlite_double  _Decimal64
+#  define LITDBL(n) n##dd
+#  define LONGDOUBLE_TYPE _Decimal128
+# else
+#  define sqlite_double  double
+#  define LITDBL(n) n
+#  define LONGDOUBLE_TYPE long double
+# endif
 #endif
 
 /*
 ** CAPI3REF: Closing A Database Connection
 **
@@ -983,11 +993,11 @@
   void (*xDlError)(sqlite3_vfs*, int nByte, char *zErrMsg);
   void (*(*xDlSym)(sqlite3_vfs*,void*, const char *zSymbol))(void);
   void (*xDlClose)(sqlite3_vfs*, void*);
   int (*xRandomness)(sqlite3_vfs*, int nByte, char *zOut);
   int (*xSleep)(sqlite3_vfs*, int microseconds);
-  int (*xCurrentTime)(sqlite3_vfs*, double*);
+  int (*xCurrentTime)(sqlite3_vfs*, sqlite_double *);
   int (*xGetLastError)(sqlite3_vfs*, int, char *);
   /*
   ** The methods above are in version 1 of the sqlite_vfs object
   ** definition.  Those that follow are added in version 2 or later
   */
@@ -3104,11 +3114,11 @@
 **
 ** See also: [sqlite3_bind_parameter_count()],
 ** [sqlite3_bind_parameter_name()], and [sqlite3_bind_parameter_index()].
 */
 int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, \
                void(*)(void*));
-int sqlite3_bind_double(sqlite3_stmt*, int, double);
+int sqlite3_bind_double(sqlite3_stmt*, int, sqlite_double );
 int sqlite3_bind_int(sqlite3_stmt*, int, int);
 int sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64);
 int sqlite3_bind_null(sqlite3_stmt*, int);
 int sqlite3_bind_text(sqlite3_stmt*, int, const char*, int n, \
void(*)(void*));  int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, \
int, void(*)(void*)); @@ -3605,11 +3615,11 @@
 ** [SQLITE_NOMEM].)^
 */
 const void *sqlite3_column_blob(sqlite3_stmt*, int iCol);
 int sqlite3_column_bytes(sqlite3_stmt*, int iCol);
 int sqlite3_column_bytes16(sqlite3_stmt*, int iCol);
-double sqlite3_column_double(sqlite3_stmt*, int iCol);
+sqlite_double  sqlite3_column_double(sqlite3_stmt*, int iCol);
 int sqlite3_column_int(sqlite3_stmt*, int iCol);
 sqlite3_int64 sqlite3_column_int64(sqlite3_stmt*, int iCol);
 const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol);
 const void *sqlite3_column_text16(sqlite3_stmt*, int iCol);
 int sqlite3_column_type(sqlite3_stmt*, int iCol);
@@ -3866,11 +3876,11 @@
 ** the SQL function that supplied the [sqlite3_value*] parameters.
 */
 const void *sqlite3_value_blob(sqlite3_value*);
 int sqlite3_value_bytes(sqlite3_value*);
 int sqlite3_value_bytes16(sqlite3_value*);
-double sqlite3_value_double(sqlite3_value*);
+sqlite_double  sqlite3_value_double(sqlite3_value*);
 int sqlite3_value_int(sqlite3_value*);
 sqlite3_int64 sqlite3_value_int64(sqlite3_value*);
 const unsigned char *sqlite3_value_text(sqlite3_value*);
 const void *sqlite3_value_text16(sqlite3_value*);
 const void *sqlite3_value_text16le(sqlite3_value*);
@@ -4117,11 +4127,11 @@
 ** If these routines are called from within the different thread
 ** than the one containing the application-defined function that received
 ** the [sqlite3_context] pointer, the results are undefined.
 */
 void sqlite3_result_blob(sqlite3_context*, const void*, int, \
                void(*)(void*));
-void sqlite3_result_double(sqlite3_context*, double);
+void sqlite3_result_double(sqlite3_context*, sqlite_double );
 void sqlite3_result_error(sqlite3_context*, const char*, int);
 void sqlite3_result_error16(sqlite3_context*, const void*, int);
 void sqlite3_result_error_toobig(sqlite3_context*);
 void sqlite3_result_error_nomem(sqlite3_context*);
 void sqlite3_result_error_code(sqlite3_context*, int);
@@ -4965,11 +4975,11 @@
   } *aConstraintUsage;
   int idxNum;                /* Number used to identify the index */
   char *idxStr;              /* String, possibly obtained from \
sqlite3_malloc */  int needToFreeIdxStr;      /* Free idxStr using \
sqlite3_free() if true */  int orderByConsumed;       /* True if output is \
                already ordered */
-  double estimatedCost;      /* Estimated cost of using this index */
+  sqlite_double  estimatedCost;      /* Estimated cost of using this index \
*/  };
 
 /*
 ** CAPI3REF: Virtual Table Constraint Operator Codes
 **
@@ -6833,20 +6843,10 @@
 #define SQLITE_ROLLBACK 1
 /* #define SQLITE_IGNORE 2 // Also used by sqlite3_authorizer() callback \
*/  #define SQLITE_FAIL     3
 /* #define SQLITE_ABORT 4  // Also an error code */
 #define SQLITE_REPLACE  5
-
-
-
-/*
-** Undo the hack that converts floating point types to integer for
-** builds on processors without floating point support.
-*/
-#ifdef SQLITE_OMIT_FLOATING_POINT
-# undef double
-#endif
 
 #ifdef __cplusplus
 }  /* End of the 'extern "C"' block */
 #endif
 #endif

Index: src/sqliteInt.h
==================================================================
--- src/sqliteInt.h
+++ src/sqliteInt.h
@@ -310,23 +310,38 @@
 /*
 ** If compiling for a processor that lacks floating point support,
 ** substitute integer for floating-point
 */
 #ifdef SQLITE_OMIT_FLOATING_POINT
-# define double sqlite_int64
+# define sqlite_double  sqlite_int64
 # define float sqlite_int64
 # define LONGDOUBLE_TYPE sqlite_int64
 # ifndef SQLITE_BIG_DBL
 #   define SQLITE_BIG_DBL (((sqlite3_int64)1)<<50)
 # endif
 # define SQLITE_OMIT_DATETIME_FUNCS 1
 # define SQLITE_OMIT_TRACE 1
 # undef SQLITE_MIXED_ENDIAN_64BIT_FLOAT
 # undef SQLITE_HAVE_ISNAN
+# define LITDBL(n) n
+#else
+# ifdef SQLITE_USE_DECIMAL
+#  define sqlite_double  _Decimal64
+#  define LITDBL(n) n##dd
+#  define LONGDOUBLE_TYPE _Decimal128
+# else
+#  define sqlite_double  double
+#  define LITDBL(n) n
+#  define LONGDOUBLE_TYPE long double
+# endif
 #endif
 #ifndef SQLITE_BIG_DBL
-# define SQLITE_BIG_DBL (1e99)
+# define SQLITE_BIG_DBL (LITDBL(1e99))
+#endif
+
+#ifndef DOUBLE_SIGNIFICANT_DIGITS
+# define DOUBLE_SIGNIFICANT_DIGITS 16
 #endif
 
 /*
 ** OMIT_TEMPDB is set to 1 if SQLITE_OMIT_TEMPDB is defined, or 0
 ** afterward. Having this macro allows us to cause the C compiler 
@@ -424,11 +439,11 @@
 # else
 #  define INT8_TYPE signed char
 # endif
 #endif
 #ifndef LONGDOUBLE_TYPE
-# define LONGDOUBLE_TYPE long double
+# define LONGDOUBLE_TYPE long double 
 #endif
 typedef sqlite_int64 i64;          /* 8-byte signed integer */
 typedef sqlite_uint64 u64;         /* 8-byte unsigned integer */
 typedef UINT32_TYPE u32;           /* 4-byte unsigned integer */
 typedef UINT16_TYPE u16;           /* 2-byte unsigned integer */
@@ -865,11 +880,11 @@
   sqlite3_value *pErr;          /* Most recent error message */
   char *zErrMsg;                /* Most recent error message (UTF-8 \
encoded) */  char *zErrMsg16;              /* Most recent error message \
(UTF-16 encoded) */  union {
     volatile int isInterrupted; /* True if sqlite3_interrupt has been \
                called */
-    double notUsed1;            /* Spacer */
+    sqlite_double  notUsed1;            /* Spacer */
   } u1;
   Lookaside lookaside;          /* Lookaside malloc configuration */
 #ifndef SQLITE_OMIT_AUTHORIZATION
   int (*xAuth)(void*,int,const char*,const char*,const char*,const char*);
                                 /* Access authorization function */
@@ -1500,11 +1515,11 @@
 ** analyze.c source file for additional information.
 */
 struct IndexSample {
   union {
     char *z;        /* Value if eType is SQLITE_TEXT or SQLITE_BLOB */
-    double r;       /* Value if eType is SQLITE_FLOAT */
+    sqlite_double  r;       /* Value if eType is SQLITE_FLOAT */
     i64 i;          /* Value if eType is SQLITE_INTEGER */
   } u;
   u8 eType;         /* SQLITE_NULL, SQLITE_INTEGER ... etc. */
   int nByte;        /* Size in byte of text or blob. */
   tRowcnt nEq;      /* Est. number of rows where the key equals this \
sample */ @@ -1898,11 +1913,11 @@
 ** case that more than one of these conditions is true.
 */
 struct WherePlan {
   u32 wsFlags;                   /* WHERE_* flags that describe the \
strategy */  u32 nEq;                       /* Number of == constraints */
-  double nRow;                   /* Estimated number of rows (for EQP) */
+  sqlite_double  nRow;                   /* Estimated number of rows (for \
EQP) */  union {
     Index *pIdx;                   /* Index when WHERE_INDEXED is true */
     struct WhereTerm *pTerm;       /* WHERE clause term for OR-search */
     sqlite3_index_info *pVtabIdx;  /* Virtual table index to use */
   } u;
@@ -1983,12 +1998,12 @@
   int iTop;                      /* The very beginning of the WHERE loop \
*/  int iContinue;                 /* Jump here to continue with next \
record */  int iBreak;                    /* Jump here to break out of the \
loop */  int nLevel;                    /* Number of nested loop */
   struct WhereClause *pWC;       /* Decomposition of the WHERE clause */
-  double savedNQueryLoop;        /* pParse->nQueryLoop outside the WHERE \
                loop */
-  double nRowOut;                /* Estimated number of output rows */
+  sqlite_double  savedNQueryLoop;        /* pParse->nQueryLoop outside the \
WHERE loop */ +  sqlite_double  nRowOut;                /* Estimated number \
of output rows */  WhereLevel a[1];               /* Information about each \
nest loop in WHERE */  };
 
 #define WHERE_DISTINCT_UNIQUE 1
 #define WHERE_DISTINCT_ORDERED 2
@@ -2063,11 +2078,11 @@
   Select *pRightmost;    /* Right-most select in a compound select \
statement */  Expr *pLimit;          /* LIMIT expression. NULL means not \
used. */  Expr *pOffset;         /* OFFSET expression. NULL means not used. \
*/  int iLimit, iOffset;   /* Memory registers holding LIMIT & OFFSET \
counters */  int addrOpenEphm[3];   /* OP_OpenEphem opcodes related to this \
                select */
-  double nSelectRow;     /* Estimated number of result rows */
+  sqlite_double  nSelectRow;     /* Estimated number of result rows */
 };
 
 /*
 ** Allowed values for Select.selFlags.  The "SF" prefix stands for
 ** "Select Flag".
@@ -2239,11 +2254,11 @@
   u32 oldmask;         /* Mask of old.* columns referenced */
   u32 newmask;         /* Mask of new.* columns referenced */
   u8 eTriggerOp;       /* TK_UPDATE, TK_INSERT or TK_DELETE */
   u8 eOrconf;          /* Default ON CONFLICT policy for trigger steps */
   u8 disableTriggers;  /* True to disable triggers */
-  double nQueryLoop;   /* Estimated number of iterations of a query */
+  sqlite_double  nQueryLoop;   /* Estimated number of iterations of a \
query */  
   /* Above is constant between recursions.  Below is reset before and \
                after
   ** each recursion */
 
   int nVar;            /* Number of '?' variables seen in the SQL so far \
*/ @@ -2631,11 +2646,11 @@
 int sqlite3StatusValue(int);
 void sqlite3StatusAdd(int, int);
 void sqlite3StatusSet(int, int);
 
 #ifndef SQLITE_OMIT_FLOATING_POINT
-  int sqlite3IsNaN(double);
+  int sqlite3IsNaN(sqlite_double );
 #else
 # define sqlite3IsNaN(X)  0
 #endif
 
 void sqlite3VXPrintf(StrAccum*, int, const char*, va_list);
@@ -2915,11 +2930,11 @@
 int sqlite3FixSrcList(DbFixer*, SrcList*);
 int sqlite3FixSelect(DbFixer*, Select*);
 int sqlite3FixExpr(DbFixer*, Expr*);
 int sqlite3FixExprList(DbFixer*, ExprList*);
 int sqlite3FixTriggerStep(DbFixer*, TriggerStep*);
-int sqlite3AtoF(const char *z, double*, int, u8);
+int sqlite3AtoF(const char *z, sqlite_double *, int, u8);
 int sqlite3GetInt32(const char *, int*);
 int sqlite3Atoi(const char*);
 int sqlite3Utf16ByteLen(const void *pData, int nChar);
 int sqlite3Utf8CharLen(const char *pData, int nByte);
 u32 sqlite3Utf8Read(const u8*, const u8**);

Index: src/util.c
==================================================================
--- src/util.c
+++ src/util.c
@@ -36,11 +36,11 @@
 ** Return true if the floating point value is Not a Number (NaN).
 **
 ** Use the math library isnan() function if compiled with \
                SQLITE_HAVE_ISNAN.
 ** Otherwise, we have our own implementation that works on most systems.
 */
-int sqlite3IsNaN(double x){
+int sqlite3IsNaN(sqlite_double  x){
   int rc;   /* The value return */
 #if !defined(SQLITE_HAVE_ISNAN)
   /*
   ** Systems that support the isnan() library function should probably
   ** make use of it by compiling with -DSQLITE_HAVE_ISNAN.  But we have
@@ -65,12 +65,12 @@
   **      ...
   */
 #ifdef __FAST_MATH__
 # error SQLite will not work correctly with the -ffast-math option of GCC.
 #endif
-  volatile double y = x;
-  volatile double z = y;
+  volatile sqlite_double  y = x;
+  volatile sqlite_double  z = y;
   rc = (y!=z);
 #else  /* if defined(SQLITE_HAVE_ISNAN) */
   rc = isnan(x);
 #endif /* SQLITE_HAVE_ISNAN */
   testcase( rc );
@@ -237,11 +237,11 @@
   return N<0 ? 0 : UpperToLower[*a] - UpperToLower[*b];
 }
 
 /*
 ** The string z[] is an text representation of a real number.
-** Convert this string to a double and write it into *pResult.
+** Convert this string to a sqlite_double  and write it into *pResult.
 **
 ** The string z[] is length bytes in length (bytes, not characters) and
 ** uses the encoding enc.  The string is not necessarily zero-terminated.
 **
 ** Return TRUE if the result is a valid real number (or integer) and FALSE
@@ -257,11 +257,11 @@
 **
 ** If some prefix of the input string is a valid number, this routine
 ** returns FALSE but it still converts the prefix and writes the result
 ** into *pResult.
 */
-int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){
+int sqlite3AtoF(const char *z, sqlite_double  *pResult, int length, u8 \
enc){  #ifndef SQLITE_OMIT_FLOATING_POINT
   int incr = (enc==SQLITE_UTF8?1:2);
   const char *zEnd = z + length;
   /* sign * significand * (10 ^ (esign * exponent)) */
   int sign = 1;    /* sign of significand */
@@ -268,11 +268,11 @@
   i64 s = 0;       /* significand */
   int d = 0;       /* adjust exponent for shifting decimal point */
   int esign = 1;   /* sign of exponent */
   int e = 0;       /* exponent */
   int eValid = 1;  /* True exponent is either not used or is well-formed \
                */
-  double result;
+  sqlite_double  result;
   int nDigits = 0;
 
   *pResult = 0.0;   /* Default return value, in case of an error */
 
   if( enc==SQLITE_UTF16BE ) z++;
@@ -354,11 +354,11 @@
 
   /* if 0 significand */
   if( !s ) {
     /* In the IEEE 754 standard, zero is signed.
     ** Add the sign if we've seen at least one digit */
-    result = (sign<0 && nDigits) ? -(double)0 : (double)0;
+    result = (sign<0 && nDigits) ? -(sqlite_double )0 : (sqlite_double )0;
   } else {
     /* attempt to reduce exponent */
     if( esign>0 ){
       while( s<(LARGEST_INT64/10) && e>0 ) e--,s*=10;
     }else{
@@ -369,40 +369,40 @@
     s = sign<0 ? -s : s;
 
     /* if exponent, scale significand as appropriate
     ** and store in result. */
     if( e ){
-      double scale = 1.0;
+      sqlite_double  scale = 1.0;
       /* attempt to handle extremely small/large numbers better */
       if( e>307 && e<342 ){
-        while( e%308 ) { scale *= 1.0e+1; e -= 1; }
+        while( e%308 ) { scale *= LITDBL(1.0e+1); e -= 1; }
         if( esign<0 ){
           result = s / scale;
-          result /= 1.0e+308;
+          result /= LITDBL(1.0e+308);
         }else{
           result = s * scale;
-          result *= 1.0e+308;
+          result *= LITDBL(1.0e+308);
         }
       }else if( e>=342 ){
         if( esign<0 ){
-          result = 0.0*s;
+          result = LITDBL(0.0)*s;
         }else{
-          result = 1e308*1e308*s;  /* Infinity */
+          result = LITDBL(1e308)*LITDBL(1e308)*s;  /* Infinity */
         }
       }else{
         /* 1.0e+22 is the largest power of 10 than can be 
         ** represented exactly. */
-        while( e%22 ) { scale *= 1.0e+1; e -= 1; }
-        while( e>0 ) { scale *= 1.0e+22; e -= 22; }
+        while( e%22 ) { scale *= LITDBL(1.0e+1); e -= 1; }
+        while( e>0 ) { scale *= LITDBL(1.0e+22); e -= 22; }
         if( esign<0 ){
           result = s / scale;
         }else{
           result = s * scale;
         }
       }
     } else {
-      result = (double)s;
+      result = (sqlite_double )s;
     }
   }
 
   /* store the result */
   *pResult = result;

Index: src/vdbe.c
==================================================================
--- src/vdbe.c
+++ src/vdbe.c
@@ -254,11 +254,11 @@
 ** looks like a number, convert it into a number.  If it does not
 ** look like a number, leave it alone.
 */
 static void applyNumericAffinity(Mem *pRec){
   if( (pRec->flags & (MEM_Real|MEM_Int))==0 ){
-    double rValue;
+    sqlite_double  rValue;
     i64 iValue;
     u8 enc = pRec->enc;
     if( (pRec->flags&MEM_Str)==0 ) return;
     if( sqlite3AtoF(pRec->z, &rValue, pRec->n, enc)==0 ) return;
     if( 0==sqlite3Atoi64(pRec->z, &iValue, pRec->n, enc) ){
@@ -1259,12 +1259,12 @@
 case OP_Divide:                /* same as TK_SLASH, in1, in2, out3 */
 case OP_Remainder: {           /* same as TK_REM, in1, in2, out3 */
   int flags;      /* Combined MEM_* flags from both inputs */
   i64 iA;         /* Integer value of left operand */
   i64 iB;         /* Integer value of right operand */
-  double rA;      /* Real value of left operand */
-  double rB;      /* Real value of right operand */
+  sqlite_double  rA;      /* Real value of left operand */
+  sqlite_double  rB;      /* Real value of right operand */
 
   pIn1 = &aMem[pOp->p1];
   applyNumericAffinity(pIn1);
   pIn2 = &aMem[pOp->p2];
   applyNumericAffinity(pIn2);
@@ -1300,21 +1300,21 @@
     switch( pOp->opcode ){
       case OP_Add:         rB += rA;       break;
       case OP_Subtract:    rB -= rA;       break;
       case OP_Multiply:    rB *= rA;       break;
       case OP_Divide: {
-        /* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */
-        if( rA==(double)0 ) goto arithmetic_result_is_null;
+        /* (sqlite_double )0 In case of SQLITE_OMIT_FLOATING_POINT... */
+        if( rA==(sqlite_double )0 ) goto arithmetic_result_is_null;
         rB /= rA;
         break;
       }
       default: {
         iA = (i64)rA;
         iB = (i64)rB;
         if( iA==0 ) goto arithmetic_result_is_null;
         if( iA==-1 ) iA = 1;
-        rB = (double)(iB % iA);
+        rB = (sqlite_double )(iB % iA);
         break;
       }
     }
 #ifdef SQLITE_OMIT_FLOATING_POINT
     pOut->u.i = rB;
@@ -2072,11 +2072,11 @@
     c = pOp->p3;
   }else{
 #ifdef SQLITE_OMIT_FLOATING_POINT
     c = sqlite3VdbeIntValue(pIn1)!=0;
 #else
-    c = sqlite3VdbeRealValue(pIn1)!=0.0;
+    c = sqlite3VdbeRealValue(pIn1)!=LITDBL(0.0);
 #endif
     if( pOp->opcode==OP_IfNot ) c = !c;
   }
   if( c ){
     pc = pOp->p2-1;
@@ -3397,11 +3397,11 @@
         }
         /* If we reach this point, then the P3 value must be a floating
         ** point number. */
         assert( (pIn3->flags & MEM_Real)!=0 );
 
-        if( iKey==SMALLEST_INT64 && (pIn3->r<(double)iKey || pIn3->r>0) ){
+        if( iKey==SMALLEST_INT64 && (pIn3->r<(sqlite_double )iKey || \
pIn3->r>0) ){  /* The P3 value is too large in magnitude to be expressed as \
                an
           ** integer. */
           res = 1;
           if( pIn3->r<0 ){
             if( oc>=OP_SeekGe ){  assert( oc==OP_SeekGe || oc==OP_SeekGt \
); @@ -3418,15 +3418,15 @@
             pc = pOp->p2 - 1;
           }
           break;
         }else if( oc==OP_SeekLt || oc==OP_SeekGe ){
           /* Use the ceiling() function to convert real->int */
-          if( pIn3->r > (double)iKey ) iKey++;
+          if( pIn3->r > (sqlite_double )iKey ) iKey++;
         }else{
           /* Use the floor() function to convert real->int */
           assert( oc==OP_SeekLe || oc==OP_SeekGt );
-          if( pIn3->r < (double)iKey ) iKey--;
+          if( pIn3->r < (sqlite_double )iKey ) iKey--;
         }
       } 
       rc = sqlite3BtreeMovetoUnpacked(pC->pCursor, 0, (u64)iKey, 0, &res);
       if( rc!=SQLITE_OK ){
         goto abort_due_to_error;



[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic