From: drh <> Date: Mon, 3 Jul 2023 18:18:35 +0000 (+0000) Subject: Enhance sqlite3AtoF() so that it honors the USELONGDOUBLE test-control. X-Git-Tag: version-3.43.0~159^2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=refs%2Fheads%2Ffp-to-decimal-refactor;p=thirdparty%2Fsqlite.git Enhance sqlite3AtoF() so that it honors the USELONGDOUBLE test-control. Enable the test/atof1.test module on non-intel platforms. FossilOrigin-Name: b7850fd480535980d66f107c2746e7f7fc0a5379ec8244d84f7785533c83f276 --- diff --git a/manifest b/manifest index 7cabc9b86f..4bb15daf33 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Whether\sor\snot\sto\suse\sthe\slong-double\sfloating\spoint\sconversion\stechnique\nis\snow\sa\stest-control\ssetting. -D 2023-07-03T14:56:49.741 +C Enhance\ssqlite3AtoF()\sso\sthat\sit\shonors\sthe\sUSELONGDOUBLE\stest-control.\nEnable\sthe\stest/atof1.test\smodule\son\snon-intel\splatforms. +D 2023-07-03T18:18:35.350 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -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 452f1e5e4a85b7869daf15d9b6468ac754836467004fa04c3419f2bd628eb6ad +F src/util.c 5c6a3c7a88af0cbabb17707314b07f6026410610be73c6b6fba163b1cbf8b5ea F src/vacuum.c 604fcdaebe76f3497c855afcbf91b8fa5046b32de3045bab89cc008d68e40104 F src/vdbe.c 74282a947234513872a83b0bab1b8c644ece64b3e27b053ef17677c8ff9c81e0 F src/vdbe.h 41485521f68e9437fdb7ec4a90f9d86ab294e9bb8281e33b235915e29122cfc0 @@ -775,7 +775,7 @@ F test/async2.test c0a9bd20816d7d6a2ceca7b8c03d3d69c28ffb8b F test/async3.test d73a062002376d7edc1fe3edff493edbec1fc2f7 F test/async4.test 1787e3952128aa10238bf39945126de7ca23685a F test/async5.test 383ab533fdb9f7ad228cc99ee66e1acb34cc0dc0 -F test/atof1.test 191ce0d7b0d527aafeafe659c31e2433e430324b5ebce3fb066178b4d9035767 +F test/atof1.test f2765d7fdc1348ae58b279d096d301a208e46da623213877b2ba580dc2768975 F test/atomic.test 065a453dde33c77ff586d91ccaa6ed419829d492dbb1a5694b8a09f3f9d7d061 F test/atomic2.test b6863b4aa552543874f80b42fb3063f1c8c2e3d8e56b6562f00a3cc347b5c1da F test/atrc.c c388fac43dbba05c804432a7135ae688b32e8f25818e9994ffba4b64cf60c27c @@ -2042,8 +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 9435ed76cd9bb1be02768b3853a2323834f67bda75d3e3f76f6aa7bd0bade3d7 -R c19a4cd19e732c53bd925a8fc2b0f976 +P 02ae6caff1f7925c696ad263fe78b1036364d24b6373e1baec10d53aafb14a12 +R bad32f05b3c6a0ddbf09f09fc45b76f6 U drh -Z ccc178a785227b10fda86cb46a381790 +Z 7edb4dd9862f63ed43ef736b26696576 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 64fd4d3539..ecc3aca4fd 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -02ae6caff1f7925c696ad263fe78b1036364d24b6373e1baec10d53aafb14a12 \ No newline at end of file +b7850fd480535980d66f107c2746e7f7fc0a5379ec8244d84f7785533c83f276 \ No newline at end of file diff --git a/src/util.c b/src/util.c index dbf31d30f3..f14cbf2594 100644 --- a/src/util.c +++ b/src/util.c @@ -386,43 +386,34 @@ u8 sqlite3StrIHash(const char *z){ return h; } -/* -** Compute 10 to the E-th power. Examples: E==1 results in 10. -** E==2 results in 100. E==50 results in 1.0e50. +/* Double-Double multiplication. *(z,zz) = (x,xx) * (y,yy) ** -** This routine only works for values of E between 1 and 341. +** Reference: +** T. J. Dekker, "A Floating-Point Technique for Extending the +** Available Precision". 1971-07-26. */ -static LONGDOUBLE_TYPE sqlite3Pow10(int E){ -#if defined(_MSC_VER) - static const LONGDOUBLE_TYPE x[] = { - 1.0e+001L, - 1.0e+002L, - 1.0e+004L, - 1.0e+008L, - 1.0e+016L, - 1.0e+032L, - 1.0e+064L, - 1.0e+128L, - 1.0e+256L - }; - LONGDOUBLE_TYPE r = 1.0; - int i; - assert( E>=0 && E<=307 ); - for(i=0; E!=0; i++, E >>=1){ - if( E & 1 ) r *= x[i]; - } - return r; -#else - LONGDOUBLE_TYPE x = 10.0; - LONGDOUBLE_TYPE r = 1.0; - while(1){ - if( E & 1 ) r *= x; - E >>= 1; - if( E==0 ) break; - x *= x; - } - return r; -#endif +static void dekkerMul2( + double x, double xx, + double y, double yy, + double *z, double *zz +){ + double hx, tx, hy, ty, p, q, c, cc; + u64 m; + memcpy(&m, &x, 8); + m &= 0xfffffffffc000000L; + memcpy(&hx, &m, 8); + tx = x - hx; + memcpy(&m, &y, 8); + m &= 0xfffffffffc000000L; + memcpy(&hy, &m, 8); + ty = y - hy; + p = hx*hy; + q = hx*ty + tx*hy; + c = p+q; + cc = p - c + q + tx*ty; + cc = x*yy + xx*y + cc; + *z = c + cc; + *zz = c - *z + cc; } /* @@ -463,12 +454,11 @@ int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){ const char *zEnd; /* sign * significand * (10 ^ (esign * exponent)) */ int sign = 1; /* sign of significand */ - i64 s = 0; /* significand */ + u64 s = 0; /* significand */ int d = 0; /* adjust exponent for shifting decimal point */ int esign = 1; /* sign of exponent */ int e = 0; /* exponent */ int eValid = 1; /* True exponent is either not used or is well-formed */ - LONGDOUBLE_TYPE result; int nDigit = 0; /* Number of digits processed */ int eType = 1; /* 1: pure integer, 2+: fractional -1 or less: bad UTF16 */ @@ -508,7 +498,7 @@ int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){ while( z=((LARGEST_INT64-9)/10) ){ + if( s>=((LARGEST_UINT64-9)/10) ){ /* skip non-significant significand digits ** (increase exponent by d to shift decimal left) */ while( z0 ){ /*OPTIMIZATION-IF-TRUE*/ - if( esign>0 ){ - if( s>=(LARGEST_INT64/10) ) break; /*OPTIMIZATION-IF-FALSE*/ - s *= 10; - }else{ - if( s%10!=0 ) break; /*OPTIMIZATION-IF-FALSE*/ - s /= 10; - } - e--; - } - /* adjust the sign of significand */ - s = sign<0 ? -s : s; + /* Try to adjust the exponent to make it smaller */ + while( e>0 && s<(LARGEST_UINT64/10) ){ + s *= 10; + e--; + } + while( e<0 && (s%10)==0 ){ + s /= 10; + e++; + } - if( e==0 ){ /*OPTIMIZATION-IF-TRUE*/ - result = (LONGDOUBLE_TYPE)s; + if( e==0 ){ + *pResult = s; + }else if( sqlite3Config.bUseLongDouble ){ + LONGDOUBLE_TYPE r = (LONGDOUBLE_TYPE)s; + if( e>0 ){ + while( e>=100 ){ e-=100; r *= 1.0e+100L; } + while( e>=10 ){ e-=10; r *= 1.0e+10L; } + while( e>=1 ){ e-=1; r *= 1.0e+01L; } }else{ - /* attempt to handle extremely small/large numbers better */ - if( e>307 ){ /*OPTIMIZATION-IF-TRUE*/ - if( e<342 ){ /*OPTIMIZATION-IF-TRUE*/ - LONGDOUBLE_TYPE scale = sqlite3Pow10(e-308); - if( esign<0 ){ - result = s / scale; - result /= 1.0e+308L; - }else{ - result = s * scale; - result *= 1.0e+308L; - } - }else{ assert( e>=342 ); - if( esign<0 ){ - result = 0.0*s; - }else{ -#ifdef INFINITY - result = INFINITY*s; -#else - result = 1e308*1e308*s; /* Infinity */ -#endif - } - } - }else{ - LONGDOUBLE_TYPE scale = sqlite3Pow10(e); - if( esign<0 ){ - result = s / scale; - }else{ - result = s * scale; - } + while( e<=-100 ){ e+=100; r *= 1.0e-100L; } + while( e<=-10 ){ e+=10; r *= 1.0e-10L; } + while( e<=-1 ){ e+=1; r *= 1.0e-01L; } + } + *pResult = r; + }else{ + double r, rr; + u64 s2; + r = (double)s; + s2 = (u64)r; + rr = s>=s2 ? (double)(s - s2) : -(double)(s2 - s); + if( e>0 ){ + while( e>=100 ){ + e -= 100; + dekkerMul2(r, rr, 1.0e+100, -1.5902891109759918046e+83, &r, &rr); + } + while( e>=10 ){ + e -= 10; + dekkerMul2(r, rr, 1.0e+10, 0.0, &r, &rr); + } + while( e>=1 ){ + e -= 1; + dekkerMul2(r, rr, 1.0e+01, 0.0, &r, &rr); + } + }else{ + while( e<=-100 ){ + e += 100; + dekkerMul2(r, rr, 1.0e-100, -1.99918998026028836196e-117, &r, &rr); + } + while( e<=-10 ){ + e += 10; + dekkerMul2(r,rr, 1.0e-10, -3.6432197315497741579e-27, &r, &rr); + } + while( e<=-1 ){ + e += 1; + dekkerMul2(r,rr, 1.0e-01, -5.5511151231257827021e-18, &r, &rr); } } + *pResult = r+rr; + if( sqlite3IsNaN(*pResult) ) *pResult = 1e300*1e300; } + if( sign<0 ) *pResult = -*pResult; + assert( !sqlite3IsNaN(*pResult) ); - /* store the result */ - *pResult = result; - +atof_return: /* return true if number and no extra non-whitespace characters after */ if( z==zEnd && nDigit>0 && eValid && eType>0 ){ return eType; @@ -928,36 +919,6 @@ int sqlite3Atoi(const char *z){ return x; } -/* Double-Double multiplication. *(z,zz) = (x,xx) * (y,yy) -** -** Reference: -** T. J. Dekker, "A Floating-Point Technique for Extending the -** Available Precision". 1971-07-26. -*/ -static void dekkerMul2( - double x, double xx, - double y, double yy, - double *z, double *zz -){ - double hx, tx, hy, ty, p, q, c, cc; - u64 m; - memcpy(&m, &x, 8); - m &= 0xfffffffffc000000L; - memcpy(&hx, &m, 8); - tx = x - hx; - memcpy(&m, &y, 8); - m &= 0xfffffffffc000000L; - memcpy(&hy, &m, 8); - ty = y - hy; - p = hx*hy; - q = hx*ty + tx*hy; - c = p+q; - cc = p - c + q + tx*ty; - cc = x*yy + xx*y + cc; - *z = c + cc; - *zz = c - *z + cc; -} - /* ** Decode a floating-point value into an approximate decimal ** representation. diff --git a/test/atof1.test b/test/atof1.test index 9386fb0589..95f443ce0d 100644 --- a/test/atof1.test +++ b/test/atof1.test @@ -15,18 +15,10 @@ set testdir [file dirname $argv0] source $testdir/tester.tcl -if {$::longdouble_size<=8} { - finish_test - return -} -if {$::tcl_platform(machine)!="x86_64"} { - finish_test - return -} - +set mxpow [expr {[use_long_double]?100:35}] expr srand(1) for {set i 1} {$i<20000} {incr i} { - set pow [expr {int((rand()-0.5)*100)}] + set pow [expr {int((rand()-0.5)*$mxpow)}] set x [expr {pow((rand()-0.5)*2*rand(),$pow)}] set xf [format %.32e $x]