From 89f15088f0bc72252fcbda6981a56e80ba7d739c Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 19 Jun 2012 00:45:16 +0000 Subject: [PATCH] Improved rounding accuracy on test-to-float conversions. FossilOrigin-Name: 699b792c6a0e989994549959b11ec1bfad8bbd92 --- manifest | 17 +++++++++-------- manifest.uuid | 2 +- src/test_func.c | 38 ++++++++++++++++++++++++++++++++++++++ src/util.c | 2 +- test/atof1.test | 36 ++++++++++++++++++++++++++++++++++++ 5 files changed, 85 insertions(+), 10 deletions(-) create mode 100644 test/atof1.test diff --git a/manifest b/manifest index b57416185b..9606896e10 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\sproblem\swith\sidentifying\swhite-space\scharacters\soutside\sof\sthe\sascii\srange\sin\sthe\sICU\stokenizer. -D 2012-06-18T20:52:32.200 +C Improved\srounding\saccuracy\son\stest-to-float\sconversions. +D 2012-06-19T00:45:16.776 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in d17fddaa4e81f93a7c9c7c0808aacb3fc95f79f4 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -203,7 +203,7 @@ F src/test_btree.c 5b89601dcb42a33ba8b820a6b763cc9cb48bac16 F src/test_config.c 4f7b8030287d62fe56a1d99e68b41760feae381a F src/test_demovfs.c 20a4975127993f4959890016ae9ce5535a880094 F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc -F src/test_func.c 090f2c3339e85c2c964435f99aed6f3da9d59525 +F src/test_func.c 3a8dd37c08ab43b76d38eea2836e34a3897bf170 F src/test_fuzzer.c 1d26aa965120420bc14807da29d4d4541bfa6148 F src/test_hexio.c abfdecb6fa58c354623978efceb088ca18e379cd F src/test_init.c 3cbad7ce525aec925f8fda2192d576d47f0d478a @@ -237,7 +237,7 @@ F src/tokenize.c 1e86210d3976717a19238ea7b047fac481fe8c12 F src/trigger.c ee7e178fb9188f44b532cebd449a7c1df90fb684 F src/update.c d3076782c887c10e882996550345da9c4c9f9dea F src/utf.c 890c67dcfcc7a74623c95baac7535aadfe265e84 -F src/util.c 4f6cfad661b2e3454b0cdd5b1b9d39a54942d0e3 +F src/util.c 0af2e515dc0dabacec931bca39525f6c3f1c5455 F src/vacuum.c 587a52bb8833d7ac15af8916f25437e2575028bd F src/vdbe.c f5ad3c06dc3fe647097065829c013f3f1b9eadca F src/vdbe.h 18f581cac1f4339ec3299f3e0cc6e11aec654cdb @@ -274,6 +274,7 @@ F test/async2.test c0a9bd20816d7d6a2ceca7b8c03d3d69c28ffb8b F test/async3.test d73a062002376d7edc1fe3edff493edbec1fc2f7 F test/async4.test 1787e3952128aa10238bf39945126de7ca23685a F test/async5.test 0dd8701bd588bf6e70c2557a22ae3f22b2567b4c +F test/atof1.test 1f6dc0f47f6697e32fa51dd154412e1172984928 F test/attach.test 0d112b7713611fdf0340260192749737135fda5f F test/attach2.test e54436ed956d3d88bdee61221da59bf3935a0966 F test/attach3.test d89ccfe4fe6e2b5e368d480fcdfe4b496c54cf4e @@ -1005,7 +1006,7 @@ F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 -P 0c2fb18d25217ada7e75dcab8b342bbc632875d8 -R de31ab49b2137fc2f97d1253270053d5 -U dan -Z 2c0f1a3c7e342f99735e428af302d9d8 +P 892b74116a3b23268895b96433d18ef00c1433d8 +R f92cf3b5f19c2cdf0a1f4043259e76e0 +U drh +Z 37917877b4f7a2aac8f4f47ec8031274 diff --git a/manifest.uuid b/manifest.uuid index 75492d0b49..9a76fd8178 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -892b74116a3b23268895b96433d18ef00c1433d8 \ No newline at end of file +699b792c6a0e989994549959b11ec1bfad8bbd92 \ No newline at end of file diff --git a/src/test_func.c b/src/test_func.c index c4fe351cb9..6f9bb03dc8 100644 --- a/src/test_func.c +++ b/src/test_func.c @@ -422,6 +422,43 @@ static void testHexToUtf16le( } #endif +/* +** SQL function: real2hex(X) +** +** If argument X is a real number, then convert it into a string which is +** the big-endian hexadecimal representation of the ieee754 encoding of +** that number. If X is not a real number, return NULL. +*/ +static void real2hex( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + union { + sqlite3_uint64 i; + double r; + unsigned char x[8]; + } v; + char zOut[20]; + int i; + int bigEndian; + v.i = 1; + bigEndian = v.x[0]==0; + v.r = sqlite3_value_double(argv[0]); + for(i=0; i<8; i++){ + if( bigEndian ){ + zOut[i*2] = "0123456789abcdef"[v.x[i]>>4]; + zOut[i*2+1] = "0123456789abcdef"[v.x[i]&0xf]; + }else{ + zOut[14-i*2] = "0123456789abcdef"[v.x[i]>>4]; + zOut[14-i*2+1] = "0123456789abcdef"[v.x[i]&0xf]; + } + } + zOut[16] = 0; + sqlite3_result_text(context, zOut, -1, SQLITE_TRANSIENT); +} + + static int registerTestFunctions(sqlite3 *db){ static const struct { char *zName; @@ -444,6 +481,7 @@ static int registerTestFunctions(sqlite3 *db){ { "test_eval", 1, SQLITE_UTF8, test_eval}, { "test_isolation", 2, SQLITE_UTF8, test_isolation}, { "test_counter", 1, SQLITE_UTF8, counterFunc}, + { "real2hex", 1, SQLITE_UTF8, real2hex}, }; int i; diff --git a/src/util.c b/src/util.c index dd3b08ae46..5cf8ebacb5 100644 --- a/src/util.c +++ b/src/util.c @@ -371,7 +371,7 @@ do_atof_calc: /* if exponent, scale significand as appropriate ** and store in result. */ if( e ){ - double scale = 1.0; + LONGDOUBLE_TYPE scale = 1.0; /* attempt to handle extremely small/large numbers better */ if( e>307 && e<342 ){ while( e%308 ) { scale *= 1.0e+1; e -= 1; } diff --git a/test/atof1.test b/test/atof1.test new file mode 100644 index 0000000000..dff5e2a3d8 --- /dev/null +++ b/test/atof1.test @@ -0,0 +1,36 @@ +# 2012 June 18 +# +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#*********************************************************************** +# +# Tests of the sqlite3AtoF() function. +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl + +expr srand(1) +for {set i 1} {$i<10000} {incr i} { + do_test 1.$i { + set pow [expr {int((rand()-0.5)*100)}] + set x [expr {pow((rand()-0.5)*2*rand(),$pow)}] + set xf [format %.45e $x] + set y [db eval "SELECT $xf=\$x"] + if {!$y} { + puts -nonewline \173[db eval "SELECT real2hex($xf), real2hex(\$x)"]\175 + db eval "SELECT $xf+0.0 AS a, \$x AS b" { + puts [format "\n%.60e\n%.60e\n%.60e" $x $a $b] + } + } + set y + } {1} +} + + +finish_test