From: drh <> Date: Mon, 3 Jul 2023 12:58:18 +0000 (+0000) Subject: New test cases for floating-point conversions. X-Git-Tag: version-3.43.0~162^2~1 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=0478d1d88a523d3d8e5c8d5acd7eb9649937ec65;p=thirdparty%2Fsqlite.git New test cases for floating-point conversions. FossilOrigin-Name: 9435ed76cd9bb1be02768b3853a2323834f67bda75d3e3f76f6aa7bd0bade3d7 --- diff --git a/manifest b/manifest index fd10ee4899..0c46f90368 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Use\sDekker\sdouble-precision\sfloating\spoint\sto\sdo\sthe\svalue\snormalization\nstep\sin\ssqlite3FpDecode()\sfor\ssystems\son\swhich\s"long\sdouble"\sis\s8\sbytes\sor\nless. -D 2023-07-03T11:44:15.056 +C New\stest\scases\sfor\sfloating-point\sconversions. +D 2023-07-03T12:58:18.851 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -647,7 +647,7 @@ F src/sqliteLimit.h 33b1c9baba578d34efe7dfdb43193b366111cdf41476b1e82699e14c11ee F src/status.c 160c445d7d28c984a0eae38c144f6419311ed3eace59b44ac6dafc20db4af749 F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1 F src/tclsqlite.c ecbc3c99c0d0c3ed122a913f143026c26d38d57f33e06bb71185dd5c1efe37cd -F src/test1.c 64b8462099618a6243f63ba701eea8913046cd7377a7a77a7e3a0ada42219275 +F src/test1.c ac81daaee5135d210f926e7d1501d6065d396decac57af94083e677cf7e175bd F src/test2.c 827446e259a3b7ab949da1542953edda7b5117982576d3e6f1c24a0dd20a5cef F src/test3.c e5178558c41ff53236ae0271e9acb3d6885a94981d2eb939536ee6474598840e F src/test4.c 4533b76419e7feb41b40582554663ed3cd77aaa54e135cf76b3205098cd6e664 @@ -705,7 +705,7 @@ F src/trigger.c ad6ab9452715fa9a8075442e15196022275b414b9141b566af8cdb7a1605f2b0 F src/update.c 0aa36561167a7c40d01163238c297297962f31a15a8d742216b3c37cdf25f731 F src/upsert.c 5303dc6c518fa7d4b280ec65170f465c7a70b7ac2b22491598f6d0b4875b3145 F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0 -F src/util.c 44855f67ac96b546b77b6c2ad128d1e28a56c495038cdda3cae25b8407442f3c +F src/util.c 97f9a7a1a22db23984ca3ced12ed666327c17beeaf8481c3325a0c74369060dc F src/vacuum.c 604fcdaebe76f3497c855afcbf91b8fa5046b32de3045bab89cc008d68e40104 F src/vdbe.c 74282a947234513872a83b0bab1b8c644ece64b3e27b053ef17677c8ff9c81e0 F src/vdbe.h 41485521f68e9437fdb7ec4a90f9d86ab294e9bb8281e33b235915e29122cfc0 @@ -1014,6 +1014,7 @@ F test/fkey8.test 51deda7f1a1448bca95875e4a6e1a3a75b4bd7215e924e845bd60de60e4d84 F test/fkey_malloc.test 594a7ea1fbab553c036c70813cd8bd9407d63749 F test/fordelete.test ba98f14446b310f9c9d935b97ec748753d0144a28b356ba30d1f4f6958fdde5c F test/format4.test eeae341953db8b6bda7f549044797c3278a6cc345d11ada81471671b654f8ef4 +F test/fpconv1.test d5d8aa0c427533006c112fb1957cdd1ea68c1d0709470dabb9ca02c2e4c06ad8 F test/fts-9fd058691.test 78b887e30ae6816df0e1fed6259de4b5a64ad33c F test/fts3.test 672a040ea57036fb4b6fdc09027c18d7d24ab654 F test/fts3_common.tcl dffad248f9ce090800e272017d2898005c28ee6314fc1dd5550643a02666907a @@ -2041,9 +2042,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P ce06982f880339cf46704e95c907249827c3e44af2b9420005200ca8abd3f371 40285d631072b79aba39cc20d4b217bdf0069f29ac9902cb97dec28d3e4cde11 -R 8a559af6860b1623fc9d9f5fb9393b11 -T +closed 40285d631072b79aba39cc20d4b217bdf0069f29ac9902cb97dec28d3e4cde11 +P 51f492b440728151ce64168d5436ba87ca60d84b89408e47c593fa731355afe4 +R 610c019b12f01dbb4053eb803e9a81bd U drh -Z 98f04f31ed955532d376706d5d138150 +Z 391291e9df52bc2766a8acd3f9c94d15 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index b3071eda1b..f201e504af 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -51f492b440728151ce64168d5436ba87ca60d84b89408e47c593fa731355afe4 \ No newline at end of file +9435ed76cd9bb1be02768b3853a2323834f67bda75d3e3f76f6aa7bd0bade3d7 \ No newline at end of file diff --git a/src/test1.c b/src/test1.c index c77aff2ed2..013adcbcb0 100644 --- a/src/test1.c +++ b/src/test1.c @@ -991,6 +991,46 @@ static void intrealFunction( sqlite3_test_control(SQLITE_TESTCTRL_RESULT_INTREAL, context); } +/* +** SQL function: strtod(X) +** +** Use the C-library strtod() function to convert string X into a double. +** Used for comparing the accuracy of SQLite's internal text-to-float conversion +** routines against the C-library. +*/ +static void shellStrtod( + sqlite3_context *pCtx, + int nVal, + sqlite3_value **apVal +){ + char *z = (char*)sqlite3_value_text(apVal[0]); + UNUSED_PARAMETER(nVal); + if( z==0 ) return; + sqlite3_result_double(pCtx, strtod(z,0)); +} + +/* +** SQL function: dtostr(X) +** +** Use the C-library printf() function to convert real value X into a string. +** Used for comparing the accuracy of SQLite's internal float-to-text conversion +** routines against the C-library. +*/ +static void shellDtostr( + sqlite3_context *pCtx, + int nVal, + sqlite3_value **apVal +){ + double r = sqlite3_value_double(apVal[0]); + int n = nVal>=2 ? sqlite3_value_int(apVal[1]) : 26; + char z[400]; + if( n<1 ) n = 1; + if( n>350 ) n = 350; + sprintf(z, "%#+.*e", n, r); + sqlite3_result_text(pCtx, z, -1, SQLITE_TRANSIENT); +} + + /* ** Usage: sqlite3_create_function DB ** @@ -1063,6 +1103,27 @@ static int SQLITE_TCLAPI test_create_function( 0, intrealFunction, 0, 0); } + /* Functions strtod() and dtostr() work as in the shell. These routines + ** use the standard C library to convert between floating point and + ** text. This is used to compare SQLite's internal conversion routines + ** against the standard library conversion routines. + ** + ** Both routines copy/pasted from the shell.c.in implementation + ** on 2023-07-03. + */ + if( rc==SQLITE_OK ){ + rc = sqlite3_create_function(db, "strtod", 1, SQLITE_UTF8, 0, + shellStrtod, 0, 0); + } + if( rc==SQLITE_OK ){ + rc = sqlite3_create_function(db, "dtostr", 1, SQLITE_UTF8, 0, + shellDtostr, 0, 0); + } + if( rc==SQLITE_OK ){ + rc = sqlite3_create_function(db, "dtostr", 2, SQLITE_UTF8, 0, + shellDtostr, 0, 0); + } + #ifndef SQLITE_OMIT_UTF16 /* Use the sqlite3_create_function16() API here. Mainly for fun, but also ** because it is not tested anywhere else. */ diff --git a/src/util.c b/src/util.c index cf4745bd0b..7642a29bca 100644 --- a/src/util.c +++ b/src/util.c @@ -934,7 +934,7 @@ int sqlite3Atoi(const char *z){ ** T. J. Dekker, "A Floating-Point Technique for Extending the ** Available Precision". 1971-07-26. */ -static void mul2( +static void dekkerMul2( double x, double xx, double y, double yy, double *z, double *zz @@ -1025,28 +1025,28 @@ void sqlite3FpDecode(FpDecode *p, double r, int iRound, int mxRound){ if( r>1.84e+19 ){ while( r>1.84e+119 ){ exp += 100; - mul2(r, rr, 1.0e-100, -1.99918998026028836196e-117, &r, &rr); + dekkerMul2(r, rr, 1.0e-100, -1.99918998026028836196e-117, &r, &rr); } while( r>1.84e+29 ){ exp += 10; - mul2(r,rr, 1.0e-10, -3.6432197315497741579e-27, &r, &rr); + dekkerMul2(r,rr, 1.0e-10, -3.6432197315497741579e-27, &r, &rr); } while( r>1.84e+19 ){ exp += 1; - mul2(r,rr, 1.0e-01, -5.5511151231257827021e-18, &r, &rr); + dekkerMul2(r,rr, 1.0e-01, -5.5511151231257827021e-18, &r, &rr); } }else{ while( r<1.84e-82 ){ exp -= 100; - mul2(r, rr, 1.0e+100, -1.5902891109759918046e+83, &r, &rr); + dekkerMul2(r, rr, 1.0e+100, -1.5902891109759918046e+83, &r, &rr); } while( r<1.84e+08 ){ exp -= 10; - mul2(r, rr, 1.0e+10, 0.0, &r, &rr); + dekkerMul2(r, rr, 1.0e+10, 0.0, &r, &rr); } while( r<1.84e+18 ){ exp -= 1; - mul2(r, rr, 1.0e+01, 0.0, &r, &rr); + dekkerMul2(r, rr, 1.0e+01, 0.0, &r, &rr); } } v = (u64)(r)+(u64)(rr); diff --git a/test/fpconv1.test b/test/fpconv1.test new file mode 100644 index 0000000000..195fdf9904 --- /dev/null +++ b/test/fpconv1.test @@ -0,0 +1,44 @@ +# 2023-07-03 +# +# 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. +# +#*********************************************************************** +# +# This file contains a test that attempts to verify the claim that the +# floatpoint-to-text conversion routines built into SQLite maintain at +# least 15 significant digits of accuracy. +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl + +if {[catch {load_static_extension db decimal} error]} { + puts "Skipping decimal tests, hit load error: $error" + finish_test; return +} + +sqlite3_create_function db +do_execsql_test fpconv1-1.0 { + WITH RECURSIVE + /* Number of random floating-point values to try. + ** On a circa 2016 x64 linux box, this test runs at + ** about 80000 cases per second -------------------vvvvvv */ + c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<100000), + fp(y) AS MATERIALIZED ( + SELECT CAST( format('%+d.%019d0e%+03d', + random()%10,abs(random()),random()%200) AS real) + FROM c + ) + SELECT y FROM fp + WHERE -log10(abs(decimal_sub(dtostr(y,24),format('%!.24e',y))/y))<15.0; + /* Number of digits of accuracy required -------^^^^ */ +} {} +# ^---- Expect a empty set as the result. The output is all tested numbers +# that fail to preserve at least 15 significant digits of accuracy. + +finish_test