# Measure the performance of floating-point conversions.
#
fp-speed-test: fp-speed-1.exe fp-speed-2.exe
- fp-speed-1 10000000
- fp-speed-2 10000000
+ fp-speed-1 1000000
+ fp-speed-2 1000000
shelltest:
$(TCLSH_CMD) $(TOP)\test\testrunner.tcl release shell
# Test performance of floating-point conversions.
#
fp-speed-test: fp-speed-1$(T.exe) fp-speed-2$(T.exe)
- ./fp-speed-1 10000000
- ./fp-speed-2 10000000
+ ./fp-speed-1 1000000
+ ./fp-speed-2 1000000
#
# sqlite3_analyzer.c build depends on $(LINK_TOOLS_DYNAMICALLY).
-C The\s_umulh()\sintrinsic\sfunction\sis\snot\savailable\son\s32-bit\swindows.\s\sSo\sdon't\nuse\sit\sthere.
-D 2026-03-29T10:32:25.815
+C Avoid\susing\sunsigned\s64-bit\sinteger\sdivision\son\splatforms\sthat\sdo\snot\ssupport\nit\sin\shardware.
+D 2026-03-29T19:06:36.213
F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md 6bc480fc673fb4acbc4094e77edb326267dd460162d7723c7f30bee2d3d9e97d
F Makefile.in 3ce07126d7e87c7464301482e161fdae6a51d0a2aa06b200b8f0000ef4d6163b
F Makefile.linux-generic bd3e3cacd369821a6241d4ea1967395c962dfe3057e38cb0a435cee0e8b789d0
-F Makefile.msc 05dffae7914a3e3accd6056d71ec2bf5dff563a728592373b828882a52141067
+F Makefile.msc 92391304cf70f4c178b127aa83b88637abd28d1b83ede451616144037ea1d3dd
F README.md 3fa51fc7ababc32edd175ae8b2986c86d5ea120c1cb1e57c7f7849492d1405ec
F VERSION 31435e19ded2aae3c1c67dacf06a995a37fd1b253baec5899b78d64cd29db4f7
F art/icon-243x273.gif 9750b734f82fdb3dc43127753d5e6fbf3b62c9f4e136c2fbf573b2f57ea87af5
F ext/wasm/tests/opfs/sahpool/sahpool-pausing.js f264925cfc82155de38cecb3d204c36e0f6991460fff0cb7c15079454679a4e2
F ext/wasm/tests/opfs/sahpool/sahpool-worker.js bd25a43fc2ab2d1bafd8f2854ad3943ef673f7c3be03e95ecf1612ff6e8e2a61
F magic.txt 5ade0bc977aa135e79e3faaea894d5671b26107cc91e70783aa7dc83f22f3ba0
-F main.mk ac1cafc6f08d108f99cf74f686f1a7f8a08569279341f9d6ffb7745c1fba66f6
+F main.mk 0ed98e9faa3a8e2ce40ec5b55781101048c13c6970bc50d456d4c2834e74f4ea
F make.bat a136fd0b1c93e89854a86d5f4edcf0386d211e5d5ec2434480f6eea436c7420c
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
F src/sqlite.h.in e7acbb01518f05c5a342149ec1eeb1afcdccf9b90a6e9770a4893ae9a3c756ae
F src/sqlite3.rc 015537e6ac1eec6c7050e17b616c2ffe6f70fca241835a84a4f0d5937383c479
F src/sqlite3ext.h 1b7a0ee438bb5c2896d0609c537e917d8057b3340f6ad004d2de44f03e3d3cca
-F src/sqliteInt.h 9716721fb57e32938a1d30a84560ce7633c63860a2209e188c87afad15d4b464
+F src/sqliteInt.h 9d6e04c079cade18c32bcf615552ac5dfba6a151b29abd2319c368764a5d297e
F src/sqliteLimit.h c70656b67ab5b96741a8f1c812bdd80c81f2b1c1e443d0cc3ea8c33bb1f1a092
F src/status.c 7565d63a79aa2f326339a24a0461a60096d0bd2bce711fefb50b5c89335f3592
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
F src/update.c 3e5e7ff66fa19ebe4d1b113d480639a24cc1175adbefabbd1a948a07f28e37cf
F src/upsert.c 215328c3f91623c520ec8672c44323553f12caeb4f01b1090ebdca99fdf7b4f1
F src/utf.c 7267c3fb9e2467020507601af3354c2446c61f444387e094c779dccd5ca62165
-F src/util.c 1fe895c652b3b1b9f4a298b95ebfcfd95e3383952dd26a5baf1c47655c483e5d
+F src/util.c f264a84eda716ae009089f1d788b55718062810792b0bfa331e7899f2add39c6
F src/vacuum.c d3d35d8ae893d419ade5fa196d761a83bddcbb62137a1a157ae751ef38b26e82
F src/vdbe.c 6c57525d7db0232d52687d30da1093db0c152f14206c2ef1adf0c19a09d863e3
F src/vdbe.h 70e862ac8a11b590f8c1eaac17a0078429d42bc4ea3f757a9af0f451dd966a71
F tool/warnings.sh a554d13f6e5cf3760f041b87939e3d616ec6961859c3245e8ef701d1eafc2ca2
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
F tool/winmain.c 00c8fb88e365c9017db14c73d3c78af62194d9644feaf60e220ab0f411f3604c
-P ff9008e7615d877e6cc852c60097777006b274971646d368eaa56b99a7acf6c7
-R ff4274da2fda9408dbca94e175d79321
+P e75f30c7e66e725a2f3f46c7d4d69a2ff925e2de9a86c3a6ec38897545b43a58
+R afdcaa646f7e2c48f9521367d5bf245b
U drh
-Z 399684f83892f09fa733c31059114ff6
+Z d27904683472a5531629ef5a5e64c8f1
# Remove this line to create a well-formed Fossil manifest.
-e75f30c7e66e725a2f3f46c7d4d69a2ff925e2de9a86c3a6ec38897545b43a58
+2197677491dfc5ec87b57bbf807776875248a250f80ce9a5ce94ae385bb1d2bc
sqlite3_value **apArg; /* The argument values */
};
+/*
+** Maxium number of base-10 digits in an unsigned 64-bit integer
+*/
+#define SQLITE_U64_DIGITS 20
+
/*
** An instance of this object receives the decoding of a floating point
** value into an approximate decimal representation.
*/
struct FpDecode {
- int n; /* Significant digits in the decode */
- int iDP; /* Location of the decimal point */
- char *z; /* Start of significant digits */
- char zBuf[20]; /* Storage for significant digits */
- char sign; /* '+' or '-' */
- char isSpecial; /* 1: Infinity 2: NaN */
+ int n; /* Significant digits in the decode */
+ int iDP; /* Location of the decimal point */
+ char *z; /* Start of significant digits */
+ char zBuf[SQLITE_U64_DIGITS+1]; /* Storage for significant digits */
+ char sign; /* '+' or '-' */
+ char isSpecial; /* 1: Infinity 2: NaN */
};
void sqlite3FpDecode(FpDecode*,double,int,int);
"90919293949596979899"
};
+/*
+** ARMv6, ARMv7, PPC32 are known to not support hardware u64 division.
+*/
+#if (defined(__arm__) && !defined(__aarch64__)) || \
+ (defined(__ppc__) && !defined(__ppc64__))
+# define SQLITE_AVOID_U64_DIVIDE 1
+#endif
+
+#ifdef SQLITE_AVOID_U64_DIVIDE
+/*
+** Render an unsigned 64-bit integer as text onto the end of a 2-byte
+** aligned buffer that is SQLITE_U64_DIGIT+1 bytes long. The last byte
+** of the buffer will be filled with a \000 byte.
+**
+** Return the index into the buffer of the first byte.
+**
+** This routine is used on platforms where u64-division is slow because
+** it is not available in hardware and has to be emulated in software.
+** It seeks to minimize the number of u64 divisions and use u32 divisions
+** instead. It is slower on platforms that have hardware u64 division,
+** but much faster on platforms that do not.
+*/
+static int sqlite3UInt64ToText(u64 v, char *zOut){
+ u32 x32, kk;
+ int i;
+ zOut[SQLITE_U64_DIGITS] = 0;
+ i = SQLITE_U64_DIGITS;
+ assert( TWO_BYTE_ALIGNMENT(&sqlite3DigitPairs.a[0]) );
+ assert( TWO_BYTE_ALIGNMENT(zOut) );
+ while( (v>>32)!=0 ){
+ u32 y, x0, x1, y0, y1;
+ x32 = v % 100000000;
+ v = v / 100000000;
+ y = x32 % 10000;
+ x32 /= 10000;
+ x1 = x32 / 100;
+ x0 = x32 % 100;
+ y1 = y / 100;
+ y0 = y % 100;
+ assert( i>=8 );
+ i -= 8;
+ *(u16*)(&zOut[i]) = *(u16*)&sqlite3DigitPairs.a[x1*2];
+ *(u16*)(&zOut[i+2]) = *(u16*)&sqlite3DigitPairs.a[x0*2];
+ *(u16*)(&zOut[i+4]) = *(u16*)&sqlite3DigitPairs.a[y1*2];
+ *(u16*)(&zOut[i+6]) = *(u16*)&sqlite3DigitPairs.a[y0*2];
+ }
+ x32 = v;
+ while( x32>=10 ){
+ kk = x32 % 100;
+ x32 = x32 / 100;
+ assert( TWO_BYTE_ALIGNMENT(&sqlite3DigitPairs.a[kk*2]) );
+ assert( i>=2 );
+ i -= 2;
+ assert( TWO_BYTE_ALIGNMENT(&zOut[i]) );
+ *(u16*)(&zOut[i]) = *(u16*)&sqlite3DigitPairs.a[kk*2];
+ }
+ if( x32 ){
+ assert( i>0 );
+ zOut[--i] = x32 + '0';
+ }
+ return i;
+}
+#endif /* defined(SQLITE_AVOID_U64_DIVIDE) */
/*
** Render an signed 64-bit integer as text. Store the result in zOut[] and
int i;
u64 x;
union {
- char a[23];
+ char a[SQLITE_U64_DIGITS+1];
u16 forceAlignment;
} u;
if( v>0 ){
}else{
x = (v==SMALLEST_INT64) ? ((u64)1)<<63 : (u64)-v;
}
+#ifdef SQLITE_AVOID_U64_DIVIDE
+ i = sqlite3UInt64ToText(x, u.a);
+#else
i = sizeof(u.a)-1;
u.a[i] = 0;
while( x>=10 ){
if( x ){
u.a[--i] = x + '0';
}
+#endif /* SQLITE_AVOID_U64_DIVIDE */
if( v<0 ) u.a[--i] = '-';
memcpy(zOut, &u.a[i], sizeof(u.a)-i);
return sizeof(u.a)-1-i;
/* Extract significant digits, start at the right-most slot in p->zBuf
** and working back to the right. "i" keeps track of the next slot in
** which to store a digit. */
- i = sizeof(p->zBuf)-1;
- zBuf = p->zBuf;
+ assert( sizeof(p->zBuf)==SQLITE_U64_DIGITS+1 );
assert( v>0 );
+ zBuf = p->zBuf;
+#ifdef SQLITE_AVOID_U64_DIVIDE
+ i = sqlite3UInt64ToText(v, zBuf);
+#else
+ i = SQLITE_U64_DIGITS;
while( v>=10 ){
int kk = (v%100)*2;
assert( TWO_BYTE_ALIGNMENT(&sqlite3DigitPairs.a[kk]) );
- assert( TWO_BYTE_ALIGNMENT(&zBuf[i-1]) );
- *(u16*)(&zBuf[i-1]) = *(u16*)&sqlite3DigitPairs.a[kk];
+ assert( TWO_BYTE_ALIGNMENT(&zBuf[i]) );
+ assert( i-2>=0 );
+ *(u16*)(&zBuf[i-2]) = *(u16*)&sqlite3DigitPairs.a[kk];
i -= 2;
v /= 100;
}
if( v ){
assert( v<10 );
- zBuf[i--] = v + '0';
+ assert( i>0 );
+ zBuf[--i] = v + '0';
}
- assert( i>=0 && i<sizeof(p->zBuf)-1 );
- n = sizeof(p->zBuf) - 1 - i; /* Total number of digits extracted */
+#endif /* SQLITE_AVOID_U64_DIVIDE */
+ assert( i>=0 && i<SQLITE_U64_DIGITS );
+ n = SQLITE_U64_DIGITS - i; /* Total number of digits extracted */
assert( n>0 );
- assert( n<sizeof(p->zBuf) );
- testcase( n==sizeof(p->zBuf)-1 );
+ assert( n<=SQLITE_U64_DIGITS );
p->iDP = n + exp;
if( iRound<=0 ){
iRound = p->iDP - iRound;
- if( iRound==0 && zBuf[i+1]>='5' ){
+ if( iRound==0 && zBuf[i]>='5' ){
iRound = 1;
- zBuf[i--] = '0';
+ zBuf[--i] = '0';
n++;
p->iDP++;
}
}
- z = &zBuf[i+1]; /* z points to the first digit */
+ z = &zBuf[i]; /* z points to the first digit */
if( iRound>0 && (iRound<n || n>mxRound) ){
if( iRound>mxRound ) iRound = mxRound;
if( iRound==17 ){