]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Make the ieee754() a built-in function. Add the --ieee754 option to the
authordrh <drh@noemail.net>
Tue, 19 Jun 2018 21:15:51 +0000 (21:15 +0000)
committerdrh <drh@noemail.net>
Tue, 19 Jun 2018 21:15:51 +0000 (21:15 +0000)
".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

ext/misc/ieee754.c
manifest
manifest.uuid
src/func.c
src/shell.c.in

index 20c5e6143347ca712183145a3ea7f23a4288fc72..76dc96fa04fb7fb68be47a0d360ed3ec7a3f6a65 100644 (file)
 **     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
index 3668ff9309cab28ce915887f9937cb2eba9118a7..559b1447c123bf3846add544e5d7c9ddf7c92354 100644 (file)
--- 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
index dda5fdd11b66ffdab54ea82130cd617e0fbd3830..bbd445ce8a89b080ccc67baab29987ce40383ea1 100644 (file)
@@ -1 +1 @@
-320fa69e6aa2a7d67f6444d6c13de9893e27b85c36a933b06da113d753b6aafc
\ No newline at end of file
+7fa8f16e586a52ac8b7f4991bdd31912ee61bd4845bdeced4c0dac363b7e823d
\ No newline at end of file
index 17a267e22392ddef72bb4326911541be4d7c0c08..ac5ddf85fdaa5dc13c1a9f4a237009cbeeb23fa2 100644 (file)
@@ -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        ),
index 38a8991b9d58457aff95f3584610ee808b77bbb0..e0ad77fccfd76432fda6c6c380ea8773b70e4056 100644 (file)
@@ -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<nArg; i++){
       if( azArg[i][0]=='-' ){
         const char *z = azArg[i]+1;
@@ -5880,6 +5912,9 @@ static int do_meta_command(char *zLine, ShellState *p){
         if( strcmp(z,"newlines")==0 ){
           ShellSetFlag(p, SHFLG_Newlines);
         }else
+        if( strcmp(z,"ieee754")==0 ){
+          ShellSetFlag(p, SHFLG_UseIeee754Func);
+        }else
         {
           raw_printf(stderr, "Unknown option \"%s\" on \".dump\"\n", azArg[i]);
           rc = 1;