aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/func.c22
-rw-r--r--src/sqliteInt.h15
-rw-r--r--src/util.c63
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.
**