Compare commits

...

3 Commits

Author SHA1 Message Date
drh d69ffd684b Improvements to the layout and comments for the new round() implementation.
FossilOrigin-Name: d6b1df1a224e06b1fae3c217c334bc0480fa4d824e4a84d6ea690159382d6e18
2024-06-12 10:17:36 +00:00
drh 190546ad7e Test cases for the round() function for values within one epsilon of the 5
round-up threshold.

FossilOrigin-Name: 552b1b106691eddb5b503c94065a1ae08d86a24f573e93fe874c48623dc28b99
2024-06-12 00:30:37 +00:00
drh 83725149c5 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
2024-06-11 22:47:33 +00:00
4 changed files with 105 additions and 30 deletions
+8 -7
View File
@@ -1,5 +1,5 @@
C Remove\ssome\sdead\sJS\scode\sand\supdate\ssome\sJS\sdocs.
D 2024-06-11T17:04:43.812
C Improvements\sto\sthe\slayout\sand\scomments\sfor\sthe\snew\sround()\simplementation.
D 2024-06-12T10:17:36.770
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 36437df3ade81376d188bf5d055caf05247c23b46ac208be4daa8c9c14129fc4
F src/global.c 61a419dd9e993b9be0f91de4c4ccf322b053eb829868e089f0321dd669be3b90
F src/hash.c 9ee4269fb1d6632a6fecfb9479c93a1f29271bddbbaf215dd60420bcb80c7220
F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51
@@ -1543,6 +1543,7 @@ F test/rollback.test 06680159bc6746d0f26276e339e3ae2f951c64812468308838e0a3362d9
F test/rollback2.test 3f3a4e20401825017df7e7671e9f31b6de5fae5620c2b9b49917f52f8c160a8f
F test/rollbackfault.test 0e646aeab8840c399cfbfa43daab46fd609cf04a
F test/round1.test 29c3c9039936ed024d672f003c4d35ee11c14c0acb75c5f7d6188ff16190cfd4
F test/round2.test 628c34321eaec238772ff0fbf37e702c129ee91b1992b5450c36ceb77986a429
F test/rowallock.test 3f88ec6819489d0b2341c7a7528ae17c053ab7cc
F test/rowhash.test 0bc1d31415e4575d10cacf31e1a66b5cc0f8be81
F test/rowid.test d27191b5ce794c05bf61081e8b2c546a1844c1641321dcaf7fb785234256cc8e
@@ -2195,8 +2196,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 06e6f64533563ab9c059b773e5f0d78085df716f2624e547b7259f6789c3ffe0
R 79d342ace6fd539450d6954e121ef97a
U stephan
Z 878c1bfba19ab8a7570c53af656f275c
P 552b1b106691eddb5b503c94065a1ae08d86a24f573e93fe874c48623dc28b99
R 9fe3498fb426f55769f36e23c6d85e1b
U drh
Z 84d74ac6bf55702c81bdfdb6de3981f8
# Remove this line to create a well-formed Fossil manifest.
+1 -1
View File
@@ -1 +1 @@
6935ac71bad3d36cc519f0325ae4447a674f257309d020cdc0741160fcce0580
d6b1df1a224e06b1fae3c217c334bc0480fa4d824e4a84d6ea690159382d6e18
+46 -22
View File
@@ -435,40 +435,65 @@ 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
/*
** This is the value of the least significant bit of the significand
** relative to the total magnitude of the number for an IEEE754 binary64.
** Since the significant is 53 bits, this is pow(2,-52).
*/
#define SQLITE_DOUBLE_EPSILON 2.220446049250313080847263336181640625e-16
/*
** 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 argument */
assert( argc==1 || argc==2 );
if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
r = sqlite3_value_double(argv[0]);
if( r<0 ){
rSgn = -1.0;
r = -r;
}else{
rSgn = 1.0;
}
if( argc==2 ){
double rY = 10.0; /* Use to compute rX */
int i; /* Loop counter for computing rX */
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;
}
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)));
}else{
zBuf = sqlite3_mprintf("%!.*f",n,r);
if( zBuf==0 ){
sqlite3_result_error_nomem(context);
return;
for(i=n, rY=10; i>0; i>>=1, rY=rY*rY){
if( i&1 ) rX *= rY;
}
sqlite3AtoF(zBuf, &r, sqlite3Strlen30(zBuf), SQLITE_UTF8);
sqlite3_free(zBuf);
}
r = rSgn*sqlite3Round(r*rX + rX*r*SQLITE_DOUBLE_EPSILON)/rX;
sqlite3_result_double(context, r);
}
#endif
@@ -2505,7 +2530,6 @@ static void piFunc(
(void)argv;
sqlite3_result_double(context, M_PI);
}
#endif /* SQLITE_ENABLE_MATH_FUNCTIONS */
/*
+50
View File
@@ -0,0 +1,50 @@
# 2024-06-10
#
# 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.
#
#***********************************************************************
#
# https://sqlite.org/forum/forumpost/c0753dfb2d5d7f75
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix round2
load_static_extension db stmtrand ieee754
do_execsql_test 1.1 {
WITH RECURSIVE
c(n) AS (VALUES(0) UNION ALL SELECT n+1 FROM c WHERE n<100000),
r(a,b) AS MATERIALIZED (SELECT stmtrand()%100000, stmtrand()%100000 FROM c),
f(x,y,n) AS (
SELECT CAST(format('%d.%d5',a,b) AS real),
CAST(format('%d.%d6',a,b) AS real),
length(format('%d',b)) FROM r)
SELECT x, n, round(x,n), round(y,n) FROM f
WHERE round(x,n)<>round(y,n);
} {}
do_execsql_test 1.2 {
SELECT round(0.15,1);
} 0.2
do_execsql_test 1.3 {
SELECT round(0.14999999999999999,1);
} 0.2
do_execsql_test 1.4 {
SELECT round(0.1499999999999999944488848768742172978818416595458984375,1);
} 0.2
do_execsql_test 1.5 {
SELECT round(ieee754_from_blob(x'3fc3333333333333'),1);
} 0.2
do_execsql_test 1.6 {
SELECT round(ieee754_from_blob(x'3fc3333333333332'),1);
} 0.1
finish_test