diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/func.c | 22 | ||||
-rw-r--r-- | src/sqliteInt.h | 15 | ||||
-rw-r--r-- | src/util.c | 63 |
3 files changed, 100 insertions, 0 deletions
diff --git a/src/func.c b/src/func.c index b24359186..4cf930b20 100644 --- a/src/func.c +++ b/src/func.c @@ -2371,6 +2371,23 @@ static void signFunc( sqlite3_result_int(context, x<0.0 ? -1 : x>0.0 ? +1 : 0); } + +#if 1 /* Temporary prototyping logic */ +static void fpdecodeFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + double r = sqlite3_value_double(argv[0]); + FpDecode s; + char zBuf[50]; + UNUSED_PARAMETER(argc); + sqlite3FpDecode(&s, r); + sqlite3_snprintf(sizeof(zBuf), zBuf, "%c%.*s/%d", s.sign, s.n, s.z, s.iDP); + sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT); +} +#endif /* Temporary prototyping logic */ + /* ** All of the FuncDef structures in the aBuiltinFunc[] array above ** to the global function hash table. This occurs at start-time (as @@ -2442,6 +2459,11 @@ void sqlite3RegisterBuiltinFunctions(void){ FUNCTION(unicode, 1, 0, 0, unicodeFunc ), FUNCTION(char, -1, 0, 0, charFunc ), FUNCTION(abs, 1, 0, 0, absFunc ), + +#if 1 /* Temporary prototyping function */ + FUNCTION(fpdecode, 1, 0, 0, fpdecodeFunc ), +#endif + #ifndef SQLITE_OMIT_FLOATING_POINT FUNCTION(round, 1, 0, 0, roundFunc ), FUNCTION(round, 2, 0, 0, roundFunc ), diff --git a/src/sqliteInt.h b/src/sqliteInt.h index d7a2d90fc..b4705b5e2 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -1239,6 +1239,7 @@ typedef struct Schema Schema; typedef struct Expr Expr; typedef struct ExprList ExprList; typedef struct FKey FKey; +typedef struct FpDecode FpDecode; typedef struct FuncDestructor FuncDestructor; typedef struct FuncDef FuncDef; typedef struct FuncDefHash FuncDefHash; @@ -4597,6 +4598,20 @@ struct PrintfArguments { sqlite3_value **apArg; /* The argument values */ }; +/* +** An instance of this object receives the decoding of a floating point +** value into an approximate decimal representation. +*/ +struct FpDecode { + char sign; /* '+' or '-' */ + char isNan; /* True if not-a-number */ + char isInf; /* True if infinity */ + int n; /* Significant digits in the decode */ + int iDP; /* Location of the decimal point */ + char z[24]; /* Significiant digits */ +}; + +void sqlite3FpDecode(FpDecode*,double); char *sqlite3MPrintf(sqlite3*,const char*, ...); char *sqlite3VMPrintf(sqlite3*,const char*, va_list); #if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE) diff --git a/src/util.c b/src/util.c index abd36eda8..29bc8524d 100644 --- a/src/util.c +++ b/src/util.c @@ -929,6 +929,69 @@ int sqlite3Atoi(const char *z){ } /* +** Decode a floating-point value into an approximate decimal +** representation. +*/ +void sqlite3FpDecode(FpDecode *p, double r){ + int i; + u64 v; + int e, exp = 0; + if( r<0.0 ){ + p->sign = '-'; + r = -r; + }else if( r==0.0 ){ + p->sign = '+'; + p->n = 1; + p->iDP = 1; + p->z[0] = '0'; + return; + }else{ + p->sign = '+'; + } + memcpy(&v,&r,8); + e = v>>52; + if( e==0x7ff ){ + if( v==0x7ff0000000000000L ){ + p->isInf = 1; + p->isNan = 0; + p->z[0] = 'I'; + p->z[1] = 'n'; + p->z[2] = 'f'; + }else{ + p->isInf = 0; + p->isNan = 1; + p->z[0] = 'N'; + p->z[1] = 'a'; + p->z[2] = 'N'; + } + p->n = 3; + p->iDP = 3; + return; + } + /* At this point, r is positive (non-zero) and is not Inf or NaN. + ** The strategy is to multiple or divide r by powers of 10 until + ** it is in between 1.0e+17 and 1.0e+19. Then convert r into + ** an unsigned 64-bit integer v, and extract digits from v. + */ + if( r>=1.0e+19 ){ + while( r>=1.0e+119 ){ exp+=100; r /= 1.0e+100; } + while( r>=1.0e+29 ){ exp+=10; r /= 1.0e+10; } + while( r>=1.0e+19 ){ exp++; r /= 10.0; } + }else if( r<1.0e+17 ){ + while( r<1.0e-97 ){ exp-=100; r *= 1.0e+100; } + while( r<1.0e+07 ){ exp-=10; r *= 1.0e+10; } + while( r<1.0e+17 ){ exp--; r *= 10.0; } + } + v = (u64)r; + i = sizeof(p->z); + while( v ){ p->z[i--] = (v%10) + '0'; v /= 10; } + p->n = sizeof(p->z) - i; + p->iDP = p->n + exp; + memmove(p->z, &p->z[i+1], p->n); + while( p->n>0 && p->z[p->n-1]=='0' ){ p->n--; } +} + +/* ** Try to convert z into an unsigned 32-bit integer. Return true on ** success and false if there is an error. ** |