]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Add the ieee754_mantissa() and ieee754_exponent() functions to the iee754
authordrh <drh@noemail.net>
Wed, 24 Jun 2020 15:06:29 +0000 (15:06 +0000)
committerdrh <drh@noemail.net>
Wed, 24 Jun 2020 15:06:29 +0000 (15:06 +0000)
extension.  Build the ieee754 extension into the CLI.

FossilOrigin-Name: db2f0836b64cd2e119684f1cf75fa3b19a84ca6aca1a239f7e2b9298016e2c95

Makefile.in
Makefile.msc
ext/misc/ieee754.c
main.mk
manifest
manifest.uuid
src/shell.c.in

index 081d29482b9ebc2eedb356ff3039e659eaa0ee87..3fc984cff7a091b3842e7308d36906ecdf5b7406 100644 (file)
@@ -1082,10 +1082,11 @@ keywordhash.h:  $(TOP)/tool/mkkeywordhash.c
 SHELL_SRC = \
        $(TOP)/src/shell.c.in \
         $(TOP)/ext/misc/appendvfs.c \
-       $(TOP)/ext/misc/shathree.c \
+       $(TOP)/ext/misc/completion.c \
         $(TOP)/ext/misc/decimal.c \
        $(TOP)/ext/misc/fileio.c \
-       $(TOP)/ext/misc/completion.c \
+        $(TOP)/ext/misc/ieee754.c \
+       $(TOP)/ext/misc/shathree.c \
        $(TOP)/ext/misc/sqlar.c \
         $(TOP)/ext/misc/uint.c \
        $(TOP)/ext/expert/sqlite3expert.c \
index ca643d084284db57d2210536db81746f14e2b70c..47857d9d8d0b938e2c25e6f45cfaf88104237bb3 100644 (file)
@@ -2204,10 +2204,11 @@ keywordhash.h:  $(TOP)\tool\mkkeywordhash.c mkkeywordhash.exe
 SHELL_SRC = \
        $(TOP)\src\shell.c.in \
        $(TOP)\ext\misc\appendvfs.c \
-       $(TOP)\ext\misc\shathree.c \
+       $(TOP)\ext\misc\completion.c \
         $(TOP)\ext\misc\decimal.c \
        $(TOP)\ext\misc\fileio.c \
-       $(TOP)\ext\misc\completion.c \
+        $(TOP)\ext\misc\ieee754.c \
+       $(TOP)\ext\misc\shathree.c \
        $(TOP)\ext\misc\uint.c \
        $(TOP)\ext\expert\sqlite3expert.c \
        $(TOP)\ext\expert\sqlite3expert.h \
index 403b08aba1a7eeea3769ea031f7441ce667b561a..40744052b10c735c57f424f3844266062b06536c 100644 (file)
 **
 ** Examples:
 **
-**     ieee754(2.0)       ->     'ieee754(2,0)'
-**     ieee754(45.25)     ->     'ieee754(181,-2)'
-**     ieee754(2, 0)      ->     2.0
-**     ieee754(181, -2)   ->     45.25
+**     ieee754(2.0)             ->     'ieee754(2,0)'
+**     ieee754(45.25)           ->     'ieee754(181,-2)'
+**     ieee754(2, 0)            ->     2.0
+**     ieee754(181, -2)         ->     45.25
+**
+** Two additional functions break apart the one-argument ieee754()
+** result into separate integer values:
+**
+**     ieee754_mantissa(45.25)  ->     181
+**     ieee754_exponent(45.25)  ->     -2
+**
+** In all single-argument functions, if the argument is an 8-byte blob
+** then that blob is interpreted as a big-endian binary64 value.
+**
+**
+** EXACT DECIMAL REPRESENTATION OF BINARY64 VALUES
+** -----------------------------------------------
+**
+** This extension in combination with the separate 'decimal' extension
+** can be used to compute the exact decimal representation of binary64
+** values.  To begin, first compute a table of exponent values:
+**
+**    CREATE TABLE pow2(x INTEGER PRIMARY KEY, v TEXT);
+**    WITH RECURSIVE c(x,v) AS (
+**      VALUES(0,'1')
+**      UNION ALL
+**      SELECT x+1, decimal_mul(v,'2') FROM c WHERE x+1<=971
+**    ) INSERT INTO pow2(x,v) SELECT x, v FROM c;
+**    WITH RECURSIVE c(x,v) AS (
+**      VALUES(-1,'0.5')
+**      UNION ALL
+**      SELECT x-1, decimal_mul(v,'0.5') FROM c WHERE x-1>=-1075
+**    ) INSERT INTO pow2(x,v) SELECT x, v FROM c;
+**
+** Then, to compute the exact decimal representation of a floating
+** point value (the value 47.49 is used in the example) do:
+**
+**    WITH c(n) AS (VALUES(47.49))
+**          ---------------^^^^^---- Replace with whatever you want
+**    SELECT decimal_mul(ieee754_mantissa(c.n),pow2.v)
+**      FROM pow2, c WHERE pow2.x=ieee754_exponent(c.n);
+**
+** Here is a query to show various boundry values for the binary64
+** number format:
+**
+**    WITH c(name,bin) AS (VALUES
+**       ('minimum positive value',        x'0000000000000001'),
+**       ('maximum subnormal value',       x'000fffffffffffff'),
+**       ('mininum positive nornal value', x'0010000000000000'),
+**       ('maximum value',                 x'7fefffffffffffff'))
+**    SELECT c.name, decimal_mul(ieee754_mantissa(c.bin),pow2.v)
+**      FROM pow2, c WHERE pow2.x=ieee754_exponent(c.bin);
+**
 */
 #include "sqlite3ext.h"
 SQLITE_EXTENSION_INIT1
@@ -88,10 +137,20 @@ static void ieee754func(
       }
       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 ){
+    switch( *(int*)sqlite3_user_data(context) ){
+      case 0:
+        sqlite3_snprintf(sizeof(zResult), zResult, "ieee754(%lld,%d)",
+                         m, e-1075);
+        sqlite3_result_text(context, zResult, -1, SQLITE_TRANSIENT);
+        break;
+      case 1:
+        sqlite3_result_int64(context, m);
+        break;
+      case 2:
+        sqlite3_result_int(context, e-1075);
+        break;
+    }
+  }else{
     sqlite3_int64 m, e, a;
     double r;
     int isNeg = 0;
@@ -133,16 +192,25 @@ int sqlite3_ieee_init(
   char **pzErrMsg, 
   const sqlite3_api_routines *pApi
 ){
+  static const struct {
+    char *zFName;
+    int nArg;
+    int iAux;
+  } aFunc[] = {
+    { "ieee754",          1,   0 },
+    { "ieee754",          2,   0 },
+    { "ieee754_mantissa", 1,   1 },
+    { "ieee754_exponent", 1,   2 },
+  };
+  int i;
   int rc = SQLITE_OK;
   SQLITE_EXTENSION_INIT2(pApi);
   (void)pzErrMsg;  /* Unused parameter */
-  rc = sqlite3_create_function(db, "ieee754", 1, 
-                               SQLITE_UTF8|SQLITE_INNOCUOUS, 0,
+  for(i=0; i<sizeof(aFunc)/sizeof(aFunc[0]) && rc==SQLITE_OK; i++){
+    rc = sqlite3_create_function(db, aFunc[i].zFName, aFunc[i].nArg,   
+                               SQLITE_UTF8|SQLITE_INNOCUOUS,
+                               (void*)&aFunc[i].iAux,
                                ieee754func, 0, 0);
-  if( rc==SQLITE_OK ){
-    rc = sqlite3_create_function(db, "ieee754", 2,
-                                 SQLITE_UTF8|SQLITE_INNOCUOUS, 0,
-                                 ieee754func, 0, 0);
   }
   return rc;
 }
diff --git a/main.mk b/main.mk
index 707a82175fc7c62832e2734be679a3549c67b74f..693887bd664603ee1651adea38a7a1ccc943c719 100644 (file)
--- a/main.mk
+++ b/main.mk
@@ -742,10 +742,11 @@ keywordhash.h:    $(TOP)/tool/mkkeywordhash.c
 SHELL_SRC = \
        $(TOP)/src/shell.c.in \
         $(TOP)/ext/misc/appendvfs.c \
-       $(TOP)/ext/misc/shathree.c \
+       $(TOP)/ext/misc/completion.c \
         $(TOP)/ext/misc/decimal.c \
        $(TOP)/ext/misc/fileio.c \
-       $(TOP)/ext/misc/completion.c \
+        $(TOP)/ext/misc/ieee754.c \
+       $(TOP)/ext/misc/shathree.c \
        $(TOP)/ext/misc/sqlar.c \
         $(TOP)/ext/misc/uint.c \
        $(TOP)/ext/expert/sqlite3expert.c \
index ca3555092de9a8b67326d36a4755d0d121c30a84..56768b3a54b7910246e2b911b4f74657815e34a3 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,22 +1,22 @@
 B 7a876209a678a34c198b54ceef9e3c041f128a14dc73357f6a57cadadaa6cf7b
-C Fix\sthe\sdecoding\sof\ssubnormal\svalues\sin\sthe\sieee754\sextension.
-D 2020-06-24T13:52:10.631
-F Makefile.in 014ad669b4a5809752939c2dea83722992711b464aa56adebca80c5cc98cfdc2
-F Makefile.msc 08c8bbedfa51e21b57153370edbfee86d35bbefb53e3773a3e086fe654facccb
+C Add\sthe\sieee754_mantissa()\sand\sieee754_exponent()\sfunctions\sto\sthe\siee754\nextension.\s\sBuild\sthe\sieee754\sextension\sinto\sthe\sCLI.
+D 2020-06-24T15:06:29.041
+F Makefile.in 19374a5db06c3199ec1bab71ab74a103d8abf21053c05e9389255dc58083f806
+F Makefile.msc 48f5a3fc32672c09ad73795749f6253e406a31526935fbbffd8f021108d54574
 F autoconf/Makefile.am a8d1d24affe52ebf8d7ddcf91aa973fa0316618ab95bb68c87cabf8faf527dc8
 F ext/lsm1/lsm_unix.c 11e0a5c19d754a4e1d93dfad06de8cc201f10f886b8e61a4c599ed34e334fc24
 F ext/misc/decimal.c c1897f624893d1c12e3c879d97ca7d1c4a36cae10d32afe632779de78c4aaa4f
-F ext/misc/ieee754.c 94846ee4b2e7a77faf9980b36b9862b67735991448665a1ef9888254697e60db
-F main.mk c99e452dd4edd0bea28547259421bd6cf24d41d928d24720737efc548958ca39
+F ext/misc/ieee754.c 7303cc27dfaf08dbe187bd63185dae7310e73f63f2e0aaa1d3bd8cee65173281
+F main.mk b1cd0bc6aedad7ebb667b7f74f835f932f60ee33be2a5c3051fd93eb465f5c75
 F src/build.c ba1bbe563a3dc02d5fed20537603181e5289c13ea30ae5e775f552e7557adbfa
-F src/shell.c.in a46df1496dea229614a14ca1c517f9e4bfecf6e3867cc6a4a129b311f3ad8c9c
+F src/shell.c.in d663152487d4bfddea0f6d21ebc2ed51575d22657a02c6828afd344bbd4651af
 F src/test1.c fe56c4bcaa2685ca9aa25d817a0ee9345e189aff4a5a71a3d8ba946c7776feb8
 F test/decimal.test 12739a01bdba4c4d79f95b323e6b67b9fad1ab6ffb56116bd2b9c81a5b19e1d9
 F test/speedtest1.c ea201573f9b27542ea1e74a68e74f121e0eb04c89e67039f40ed68f1b833339f
 F tool/mkautoconfamal.sh f62353eb6c06ab264da027fd4507d09914433dbdcab9cb011cdc18016f1ab3b8
 F tool/mksqlite3c.tcl f4ef476510eca4124c874a72029f1e01bc54a896b1724e8f9eef0d8bfae0e84c
 F tool/mksqlite3h.tcl 1f5e4a1dbbbc43c83cc6e74fe32c6c620502240b66c7c0f33a51378e78fc4edf
-P 4199c1e8aa47d77df3ef598cb6f5418f67970dd00f34823463c85eabfc8d2b77
-R ba2656328834bfd4a44f83b197706ae6
+P 838817b680f02b3845d6d56f85d5d36fa5ae7453afef7a1a5a24624255f2dc3e
+R 6e286f8b0cf2dcbbb10b38a65d995df9
 U drh
-Z 3f979f9393c7d6c04f34a16bcf1ccd28
+Z 549c83ceeab0b10ef9bb12772423a56c
index aceb83dacbde533eb43502ab8e6fbd4245b42519..766ebfb8a35d73c5a87f2c3d0e92c1a243174edb 100644 (file)
@@ -1 +1 @@
-838817b680f02b3845d6d56f85d5d36fa5ae7453afef7a1a5a24624255f2dc3e
\ No newline at end of file
+db2f0836b64cd2e119684f1cf75fa3b19a84ca6aca1a239f7e2b9298016e2c95
\ No newline at end of file
index be858f0132ea864155210bfaf2518f9cabd41654..2ad7f990dc4a63f5815e8e550b7d61b0c40391b7 100644 (file)
@@ -1012,6 +1012,7 @@ INCLUDE ../ext/misc/appendvfs.c
 INCLUDE ../ext/misc/memtrace.c
 INCLUDE ../ext/misc/uint.c
 INCLUDE ../ext/misc/decimal.c
+INCLUDE ../ext/misc/ieee754.c
 #ifdef SQLITE_HAVE_ZLIB
 INCLUDE ../ext/misc/zipfile.c
 INCLUDE ../ext/misc/sqlar.c
@@ -4558,6 +4559,7 @@ static void open_db(ShellState *p, int openFlags){
     sqlite3_completion_init(p->db, 0, 0);
     sqlite3_uint_init(p->db, 0, 0);
     sqlite3_decimal_init(p->db, 0, 0);
+    sqlite3_ieee_init(p->db, 0, 0);
 #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
     sqlite3_dbdata_init(p->db, 0, 0);
 #endif