From: drh <> Date: Tue, 11 Jun 2024 22:47:33 +0000 (+0000) Subject: A second approach to working on the round() function so that it gives a X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=83725149c5e5bc2851a222acc603f2eb6f919472;p=thirdparty%2Fsqlite.git A second approach to working on the round() function so that it gives a small boost to numbers that are ...49999999 such that they round up. FossilOrigin-Name: 44dd632896e688a7d73707f43261577b237628a587800b94f1b77d3ab0cedc2e --- diff --git a/manifest b/manifest index 2724500b35..7e95f13f30 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Remove\ssome\sdead\sJS\scode\sand\supdate\ssome\sJS\sdocs. -D 2024-06-11T17:04:43.812 +C A\ssecond\sapproach\sto\sworking\son\sthe\sround()\sfunction\sso\sthat\sit\sgives\sa\nsmall\sboost\sto\snumbers\sthat\sare\s...49999999\ssuch\sthat\sthey\sround\sup. +D 2024-06-11T22:47:33.094 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -708,7 +708,7 @@ F src/delete.c cb766727c78e715f9fb7ec8a7d03658ed2a3016343ca687acfcec9083cdca500 F src/expr.c af9c9242be0df17280faf36c9810339de9df3d7a64ac8d33a5190a1400086ee5 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fkey.c 852f93c0ef995e0c2b8983059a2b97151c194cc8259e21f5bc2b7ac508348c2a -F src/func.c 1f61e32e7a357e615b5d2e774bee563761fce4f2fd97ecb0f72c33e62a2ada5f +F src/func.c a7c6f4af5fa85ece25e5ff3228d182b4928461aaf5e5450e3c6f88767ff01d64 F src/global.c 61a419dd9e993b9be0f91de4c4ccf322b053eb829868e089f0321dd669be3b90 F src/hash.c 9ee4269fb1d6632a6fecfb9479c93a1f29271bddbbaf215dd60420bcb80c7220 F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51 @@ -2195,8 +2195,11 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 06e6f64533563ab9c059b773e5f0d78085df716f2624e547b7259f6789c3ffe0 -R 79d342ace6fd539450d6954e121ef97a -U stephan -Z 878c1bfba19ab8a7570c53af656f275c +P 6935ac71bad3d36cc519f0325ae4447a674f257309d020cdc0741160fcce0580 +R 20f10f21aa5a26361938ba3edec94cb0 +T *branch * round-up-2 +T *sym-round-up-2 * +T -sym-trunk * +U drh +Z 72a6e77fd70156feb2a1bdd4868e4b54 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 214309359d..7bbac74375 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -6935ac71bad3d36cc519f0325ae4447a674f257309d020cdc0741160fcce0580 \ No newline at end of file +44dd632896e688a7d73707f43261577b237628a587800b94f1b77d3ab0cedc2e \ No newline at end of file diff --git a/src/func.c b/src/func.c index 8fcda11dc0..99949dd44e 100644 --- a/src/func.c +++ b/src/func.c @@ -435,40 +435,60 @@ static void substrFunc( } } +/* +** The library round() function is only available if +** SQLITE_ENABLE_MATH_FUNCTIONS is defined. Without that macro, we +** have to grow our own. +** +** The sqlite3Round(x) routine only needs to deal with non-negative +** numbers. +*/ +#ifdef SQLITE_ENABLE_MATH_FUNCTIONS +# define sqlite3Round(X) round(X) +#else +static double sqlite3Round(double x){ + assert( x>=0.0 ); + if( x>+4503599627370496.0 ){ + return x; + }else{ + sqlite3_int64 ii = (sqlite3_int64)(x+0.5); + return (double)ii; + } +} +#endif + /* ** Implementation of the round() function */ #ifndef SQLITE_OMIT_FLOATING_POINT static void roundFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ - int n = 0; - double r; - char *zBuf; + int n = 0; /* Second argument. Digits to the right of decimal point */ + double r; /* First argument. Value to be rounded */ + double rX = 1.0; /* Scaling factor. pow(10,n) */ + double rSgn; /* Sign of the first first */ + static const double rTwoPowerMinus52 = /* pow(2,-52) */ + 2.220446049250313080847263336181640625e-16; assert( argc==1 || argc==2 ); if( argc==2 ){ + double rY = 10; + int i; if( SQLITE_NULL==sqlite3_value_type(argv[1]) ) return; n = sqlite3_value_int(argv[1]); if( n>30 ) n = 30; if( n<0 ) n = 0; + for(i=n, rY=10; i>0; i>>=1, rY=rY*rY){ + if( i&1 ) rX *= rY; + } } if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return; r = sqlite3_value_double(argv[0]); - /* If Y==0 and X will fit in a 64-bit int, - ** handle the rounding directly, - ** otherwise use printf. - */ - if( r<-4503599627370496.0 || r>+4503599627370496.0 ){ - /* The value has no fractional part so there is nothing to round */ - }else if( n==0 ){ - r = (double)((sqlite_int64)(r+(r<0?-0.5:+0.5))); + if( r<0 ){ + rSgn = -1.0; + r = -r; }else{ - zBuf = sqlite3_mprintf("%!.*f",n,r); - if( zBuf==0 ){ - sqlite3_result_error_nomem(context); - return; - } - sqlite3AtoF(zBuf, &r, sqlite3Strlen30(zBuf), SQLITE_UTF8); - sqlite3_free(zBuf); + rSgn = 1.0; } + r = rSgn*sqlite3Round(r*rX + rX*r*rTwoPowerMinus52)/rX; sqlite3_result_double(context, r); } #endif @@ -2505,7 +2525,6 @@ static void piFunc( (void)argv; sqlite3_result_double(context, M_PI); } - #endif /* SQLITE_ENABLE_MATH_FUNCTIONS */ /*