From: drh Date: Tue, 19 Jun 2018 21:15:51 +0000 (+0000) Subject: Make the ieee754() a built-in function. Add the --ieee754 option to the X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=b06782f467af80a77a706984d5e6d8d7793c81e2;p=thirdparty%2Fsqlite.git Make the ieee754() a built-in function. Add the --ieee754 option to the ".dump" command in the shell to cause it to output floating-point values as ieee754() calls, so that the floating point number will be reproduced exactly. Not sure yet that we want to go this way, but it is one option. FossilOrigin-Name: 7fa8f16e586a52ac8b7f4991bdd31912ee61bd4845bdeced4c0dac363b7e823d --- diff --git a/ext/misc/ieee754.c b/ext/misc/ieee754.c index 20c5e61433..76dc96fa04 100644 --- a/ext/misc/ieee754.c +++ b/ext/misc/ieee754.c @@ -30,6 +30,10 @@ ** ieee754(45.25) -> 'ieee754(181,-2)' ** ieee754(2, 0) -> 2.0 ** ieee754(181, -2) -> 45.25 +** +** ieee754(4503599627370496,972) -> +Inf +** ieee754(4503599627370496,972) -> -Inf +** */ #include "sqlite3ext.h" SQLITE_EXTENSION_INIT1 diff --git a/manifest b/manifest index 3668ff9309..559b1447c1 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Minor\schange\sto\sthe\sinput\sgrammar\sto\smake\sthe\sparser\stables\sslightly\ssmaller. -D 2018-06-19T11:15:19.013 +C Make\sthe\sieee754()\sa\sbuilt-in\sfunction.\s\sAdd\sthe\s--ieee754\soption\sto\sthe\n".dump"\scommand\sin\sthe\sshell\sto\scause\sit\sto\soutput\sfloating-point\svalues\sas\nieee754()\scalls,\sso\sthat\sthe\sfloating\spoint\snumber\swill\sbe\sreproduced\sexactly.\nNot\ssure\syet\sthat\swe\swant\sto\sgo\sthis\sway,\sbut\sit\sis\sone\soption. +D 2018-06-19T21:15:51.406 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in bfc40f350586923e0419d2ea4b559c37ec10ee4b6e210e08c14401f8e340f0da @@ -280,7 +280,7 @@ F ext/misc/dbdump.c 12389a10c410fadf1e68eeb382def92d5a7fa9ce7cce4fb86a736fa2bac1 F ext/misc/eval.c 6ea9b22a5fa0dd973b67ca4e53555be177bc0b7b263aadf1024429457c82c0e3 F ext/misc/fileio.c 48c7751c78fc4cdd29d8c862fd2f3f98bbfefa2a3cf1ca1496df4bf02eb8cded F ext/misc/fuzzer.c 7c64b8197bb77b7d64eff7cac7848870235d4c25 -F ext/misc/ieee754.c f190d0cc5182529acb15babd177781be1ac1718c +F ext/misc/ieee754.c aea0fff2ae7d031ecb973a5256e612fea14d61386f672ab6179845addbc54dee F ext/misc/json1.c 02f5f0d9c131df79f4ee168d2b426f0f0d273b7771fc0bb5293c4e7692d9a2ee F ext/misc/memvfs.c ab36f49e02ebcdf85a1e08dc4d8599ea8f343e073ac9e0bca18a98b7e1ec9567 F ext/misc/mmapwarm.c 70b618f2d0bde43fae288ad0b7498a629f2b6f61b50a27e06fae3cd23c83af29 @@ -450,7 +450,7 @@ F src/delete.c 4c8c7604277a2041647f96b78f4b9a47858e9217e4fb333d35e7b5ab32c5b57f F src/expr.c 3ab855fb882d8758220edaf261d8d56ad2cb3736f92c818f4ae250ac4a2752a4 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fkey.c b1da9ef8dc834603bb0d28972378a7ce65897847f9a1e89ab800bbdf24c788ee -F src/func.c e2e3c02621a528a472933fd4733a5da635676f1461be73293f6e9f62f18d4eaa +F src/func.c 23d9499688bc862cbb78026670e22140a0c6129527a1470b9b2913d854576153 F src/global.c 9bf034fd560bdd514715170ed8460bb7f823cec113f0569ef3f18a20c7ccd128 F src/hash.c a12580e143f10301ed5166ea4964ae2853d3905a511d4e0c44497245c7ce1f7a F src/hash.h ab34c5c54a9e9de2e790b24349ba5aab3dbb4fd4 @@ -496,7 +496,7 @@ F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384 F src/resolve.c 14602f46800ba182ea6a490e0f304127d29ac1f724bdadcc639e25d3223fcf6e F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac F src/select.c 8d3176c5258cc83942815ebe75b4c1f8dcf62b5e0f4d37373a14ebf23c046f9f -F src/shell.c.in 8578421c5fb2a972461b2a996f7173646e55e0dbd2a2eee30c8f5dc7d3dbadfd +F src/shell.c.in 5473740b6985a14a90ce4bf5adb395b39af17baa4a3043604dedaf7df055413f F src/sqlite.h.in 19de593baa0667854730e7b8bc2e3039c20ee80a4d537e9b5ec2038947fe3daf F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 9887b27e69c01e79c2cbe74ef73bf01af5b5703d6a7f0a4371e386d7249cb1c7 @@ -1731,7 +1731,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 39434262d5cf1af197ce0abb1f1ee84ee0797823e290a493c5bf8376fbe287a6 -R b6cf2872dc6b136d2f9f02df3a45f74e +P 320fa69e6aa2a7d67f6444d6c13de9893e27b85c36a933b06da113d753b6aafc +R 84eaf5b540bd61da1f0a39dda242e449 +T *branch * ieee754 +T *sym-ieee754 * +T -sym-trunk * U drh -Z ca3608404058acf123d3efb518cfb804 +Z 7780acb924c455e866caa4faf522bb89 diff --git a/manifest.uuid b/manifest.uuid index dda5fdd11b..bbd445ce8a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -320fa69e6aa2a7d67f6444d6c13de9893e27b85c36a933b06da113d753b6aafc \ No newline at end of file +7fa8f16e586a52ac8b7f4991bdd31912ee61bd4845bdeced4c0dac363b7e823d \ No newline at end of file diff --git a/src/func.c b/src/func.c index 17a267e223..ac5ddf85fd 100644 --- a/src/func.c +++ b/src/func.c @@ -1438,6 +1438,82 @@ static void soundexFunc( } #endif /* SQLITE_SOUNDEX */ +#ifndef SQLITE_OMIT_FLOATING_POINT +/* +** Implementation of the ieee754() function +*/ +static void ieee754func( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + if( argc==1 ){ + sqlite3_int64 m, a; + double r; + int e; + int isNeg; + char zResult[100]; + assert( sizeof(m)==sizeof(r) ); + if( sqlite3_value_type(argv[0])!=SQLITE_FLOAT ) return; + r = sqlite3_value_double(argv[0]); + if( r<0.0 ){ + isNeg = 1; + r = -r; + }else{ + isNeg = 0; + } + memcpy(&a,&r,sizeof(a)); + if( a==0 ){ + e = 0; + m = 0; + }else{ + e = a>>52; + m = a & ((((sqlite3_int64)1)<<52)-1); + m |= ((sqlite3_int64)1)<<52; + while( e<1075 && m>0 && (m&1)==0 ){ + m >>= 1; + e++; + } + if( isNeg ) m = -m; + } + sqlite3_snprintf(sizeof(zResult), zResult, "ieee754(%lld,%d)", + m, e-1075); + sqlite3_result_text(context, zResult, -1, SQLITE_TRANSIENT); + }else if( argc==2 ){ + sqlite3_int64 m, e, a; + double r; + int isNeg = 0; + m = sqlite3_value_int64(argv[0]); + e = sqlite3_value_int64(argv[1]); + if( m<0 ){ + isNeg = 1; + m = -m; + if( m<0 ) return; + }else if( m==0 && e>1000 && e<1000 ){ + sqlite3_result_double(context, 0.0); + return; + } + while( (m>>32)&0xffe00000 ){ + m >>= 1; + e++; + } + while( m!=0 && ((m>>32)&0xfff00000)==0 ){ + m <<= 1; + e--; + } + e += 1075; + if( e<0 ) e = m = 0; + if( e>0x7ff ) e = 0x7ff; + a = m & ((((sqlite3_int64)1)<<52)-1); + a |= e<<52; + if( isNeg ) a |= ((sqlite3_uint64)1)<<63; + memcpy(&r, &a, sizeof(r)); + sqlite3_result_double(context, r); + } +} + +#endif /* SQLITE_OMIT_FLOATING_POINT */ + #ifndef SQLITE_OMIT_LOAD_EXTENSION /* ** A function that loads a shared-library extension then returns NULL. @@ -1840,6 +1916,8 @@ void sqlite3RegisterBuiltinFunctions(void){ #ifndef SQLITE_OMIT_FLOATING_POINT FUNCTION(round, 1, 0, 0, roundFunc ), FUNCTION(round, 2, 0, 0, roundFunc ), + FUNCTION(ieee754, 1, 0, 0, ieee754func ), + FUNCTION(ieee754, 2, 0, 0, ieee754func ), #endif FUNCTION(upper, 1, 0, 0, upperFunc ), FUNCTION(lower, 1, 0, 0, lowerFunc ), diff --git a/src/shell.c.in b/src/shell.c.in index 38a8991b9d..e0ad77fccf 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -1078,6 +1078,7 @@ struct ShellState { #define SHFLG_Newlines 0x00000010 /* .dump --newline flag */ #define SHFLG_CountChanges 0x00000020 /* .changes setting */ #define SHFLG_Echo 0x00000040 /* .echo or --echo setting */ +#define SHFLG_UseIeee754Func 0x00000080 /* .dump --ieee754 flag */ /* ** Macros for testing and setting shellFlgs @@ -2031,17 +2032,48 @@ static int shell_callback( }else if( aiType && aiType[i]==SQLITE_INTEGER ){ utf8_printf(p->out,"%s", azArg[i]); }else if( aiType && aiType[i]==SQLITE_FLOAT ){ - char z[50]; - double r = sqlite3_column_double(p->pStmt, i); - sqlite3_uint64 ur; - memcpy(&ur,&r,sizeof(r)); - if( ur==0x7ff0000000000000LL ){ - raw_printf(p->out, "1e999"); - }else if( ur==0xfff0000000000000LL ){ - raw_printf(p->out, "-1e999"); - }else{ - sqlite3_snprintf(50,z,"%!.20g", r); + sqlite3_int64 m, a; + double r; + int e; + int isNeg; + char z[100]; + assert( sizeof(m)==sizeof(r) ); + r = sqlite3_column_double(p->pStmt, i); + if( ShellHasFlag(p, SHFLG_UseIeee754Func) ){ + if( r<0.0 ){ + isNeg = 1; + r = -r; + }else{ + isNeg = 0; + } + memcpy(&a,&r,sizeof(a)); + if( a==0 ){ + e = 0; + m = 0; + }else{ + e = a>>52; + m = a & ((((sqlite3_int64)1)<<52)-1); + m |= ((sqlite3_int64)1)<<52; + while( e<1075 && m>0 && (m&1)==0 ){ + m >>= 1; + e++; + } + if( isNeg ) m = -m; + } + sqlite3_snprintf(sizeof(z), z, "ieee754(%lld,%d)", + m, e-1075); raw_printf(p->out, "%s", z); + }else{ + sqlite3_uint64 ur; + memcpy(&ur,&r,sizeof(r)); + if( ur==0x7ff0000000000000LL ){ + raw_printf(p->out, "1e999"); + }else if( ur==0xfff0000000000000LL ){ + raw_printf(p->out, "-1e999"); + }else{ + sqlite3_snprintf(50,z,"%!.20g", r); + raw_printf(p->out, "%s", z); + } } }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){ const void *pBlob = sqlite3_column_blob(p->pStmt, i); @@ -5862,7 +5894,7 @@ static int do_meta_command(char *zLine, ShellState *p){ const char *zLike = 0; int i; int savedShowHeader = p->showHeader; - ShellClearFlag(p, SHFLG_PreserveRowid|SHFLG_Newlines); + ShellClearFlag(p, SHFLG_PreserveRowid|SHFLG_Newlines|SHFLG_UseIeee754Func); for(i=1; i