Compare commits

..

2 Commits

Author SHA1 Message Date
drh 0b5e944480 Faster conversion of integers to text, by converting two digits at a time.
FossilOrigin-Name: 90300e02f0de45b57d53976cae72928b3e56532d90b8b8cdc988e14762777930
2026-02-17 00:37:12 +00:00
drh 63338e3ba8 Simplifications to sqlite3AtoF(), resulting in slightly faster performance
and slightly smaller size.

FossilOrigin-Name: 6b9ab641763bc1620a01beec71589506b3b0827bff1c6cd98a5d17c6070050b3
2026-02-16 23:52:51 +00:00
4 changed files with 78 additions and 65 deletions
+6 -6
View File
@@ -1,5 +1,5 @@
C Fix\sa\sbad\sassert()\sin\sthe\sprevious\scheck-in.
D 2026-02-16T17:22:17.815
C Faster\sconversion\sof\sintegers\sto\stext,\sby\sconverting\stwo\sdigits\sat\sa\stime.
D 2026-02-17T00:37:12.629
F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
@@ -803,7 +803,7 @@ F src/trigger.c a40440614bdf523090cc07223f4878f7e3c892bcd1a13afe18f90190daa5945d
F src/update.c 3e5e7ff66fa19ebe4d1b113d480639a24cc1175adbefabbd1a948a07f28e37cf
F src/upsert.c 215328c3f91623c520ec8672c44323553f12caeb4f01b1090ebdca99fdf7b4f1
F src/utf.c 7267c3fb9e2467020507601af3354c2446c61f444387e094c779dccd5ca62165
F src/util.c 16c7fcce87e43c612dd579c87d11a085ce5243565b7c324806f4a506c5e696a4
F src/util.c a5d1c01e9ac773b2a783db45169fc7674ed2f6e05dadc88052702273ec94928c
F src/vacuum.c d3d35d8ae893d419ade5fa196d761a83bddcbb62137a1a157ae751ef38b26e82
F src/vdbe.c 5328c99dd256ee8132383565a86e253543a85daccfd7477c52f20bac6b385a7f
F src/vdbe.h 966d0677a540b7ea6549b7c4e1312fc0d830fce3a235a58c801f2cc31cf5ecf9
@@ -2194,8 +2194,8 @@ F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee
F tool/warnings.sh d924598cf2f55a4ecbc2aeb055c10bd5f48114793e7ba25f9585435da29e7e98
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
F tool/winmain.c 00c8fb88e365c9017db14c73d3c78af62194d9644feaf60e220ab0f411f3604c
P 67c7c72e9bdf04c920d77006538a202c923fa74b47c81dc3014c2929dac7277d
R 94ab950169198f260c23800402fd70a5
P 6b9ab641763bc1620a01beec71589506b3b0827bff1c6cd98a5d17c6070050b3
R 576ef9ddbda75f09f3eafbf37da65a3c
U drh
Z c0318b1fd81a3ec64d379bf447b9b4ea
Z 308ac5fa17afdaa5c0816c0d53c230b6
# Remove this line to create a well-formed Fossil manifest.
+2 -2
View File
@@ -1,2 +1,2 @@
branch numeric-conversion-perf
tag numeric-conversion-perf
branch numeric-conversion
tag numeric-conversion
+1 -1
View File
@@ -1 +1 @@
a4540582b5b704af13b570b3dc609dbacada719302372a038cf74eee3688d5e7
90300e02f0de45b57d53976cae72928b3e56532d90b8b8cdc988e14762777930
+69 -56
View File
@@ -738,12 +738,9 @@ static double sqlite3Fp10Convert2(u64 d, int p){
int sqlite3AtoF(const char *z, double *pResult){
#ifndef SQLITE_OMIT_FLOATING_POINT
/* sign * significand * (10 ^ (esign * exponent)) */
int sign = 1; /* sign of 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 */
int neg = 0; /* True for a negative value */
u64 s = 0; /* mantissa */
int d = 0; /* Value is s * pow(10,d) */
int nDigit = 0; /* Number of digits processed */
int eType = 1; /* 1: pure integer, 2+: fractional */
@@ -754,7 +751,7 @@ int sqlite3AtoF(const char *z, double *pResult){
/* get sign of significand */
if( *z=='-' ){
sign = -1;
neg = 1;
z++;
}else if( *z=='+' ){
z++;
@@ -789,8 +786,8 @@ int sqlite3AtoF(const char *z, double *pResult){
/* if exponent is present */
if( *z=='e' || *z=='E' ){
int esign = 1; /* sign of exponent */
z++;
eValid = 0;
eType++;
/* get sign of exponent */
@@ -801,10 +798,16 @@ int sqlite3AtoF(const char *z, double *pResult){
z++;
}
/* copy digits to exponent */
while( sqlite3Isdigit(*z) ){
e = e<10000 ? (e*10 + (*z - '0')) : 10000;
if( sqlite3Isdigit(*z) ){
int exp = *z - '0';
z++;
eValid = 1;
while( sqlite3Isdigit(*z) ){
exp = exp<10000 ? (exp*10 + (*z - '0')) : 10000;
z++;
}
d += esign*exp;
}else{
eType = -1;
}
}
@@ -813,22 +816,17 @@ int sqlite3AtoF(const char *z, double *pResult){
/* Zero is a special case */
if( s==0 ){
*pResult = sign<0 ? -0.0 : +0.0;
goto atofz_return;
*pResult = neg ? -0.0 : +0.0;
}else{
*pResult = sqlite3Fp10Convert2(s,d);
if( neg ) *pResult = -*pResult;
assert( !sqlite3IsNaN(*pResult) );
}
/* adjust exponent by d, and update sign */
e = (e*esign) + d;
*pResult = sqlite3Fp10Convert2(s,e);
if( sign<0 ) *pResult = -*pResult;
assert( !sqlite3IsNaN(*pResult) );
atofz_return:
/* return true if number and no extra non-whitespace characters after */
if( z[0]==0 && nDigit>0 && eValid ){
if( z[0]==0 && nDigit>0 ){
return eType;
}else if( eType>=2 && (eType==3 || eValid) && nDigit>0 ){
}else if( eType>=2 && nDigit>0 ){
return -1;
}else{
return 0;
@@ -841,7 +839,25 @@ atofz_return:
#pragma warning(default : 4756)
#endif
/*
** Digit pairs used to convert a U64 or I64 into text, two digits
** at a time.
*/
static const union {
char a[200];
short int forceAlignment;
} sqlite3DigitPairs = {
"00010203040506070809"
"10111213141516171819"
"20212223242526272829"
"30313233343536373839"
"40414243444546474849"
"50515253545556575859"
"60616263646566676869"
"70717273747576777879"
"80818283848586878889"
"90919293949596979899"
};
/*
@@ -855,23 +871,35 @@ atofz_return:
int sqlite3Int64ToText(i64 v, char *zOut){
int i;
u64 x;
char zTemp[22];
if( v<0 ){
x = (v==SMALLEST_INT64) ? ((u64)1)<<63 : (u64)-v;
}else{
union {
char a[23];
u16 forceAlignment;
} u;
if( v>0 ){
x = v;
}else if( v==0 ){
zOut[0] = '0';
zOut[1] = 0;
return 1;
}else{
x = (v==SMALLEST_INT64) ? ((u64)1)<<63 : (u64)-v;
}
i = sizeof(zTemp)-2;
zTemp[sizeof(zTemp)-1] = 0;
while( 1 /*exit-by-break*/ ){
zTemp[i] = (x%10) + '0';
x = x/10;
if( x==0 ) break;
i--;
};
if( v<0 ) zTemp[--i] = '-';
memcpy(zOut, &zTemp[i], sizeof(zTemp)-i);
return sizeof(zTemp)-1-i;
i = sizeof(u.a)-1;
u.a[i] = 0;
while( x>=10 ){
int kk = (x%100)*2;
assert( TWO_BYTE_ALIGNMENT(&sqlite3DigitPairs.a[kk]) );
assert( TWO_BYTE_ALIGNMENT(&u.a[i-2]) );
*(u16*)(&u.a[i-2]) = *(u16*)&sqlite3DigitPairs.a[kk];
i -= 2;
x /= 100;
}
if( x ){
u.a[--i] = x + '0';
}
if( v<0 ) u.a[--i] = '-';
memcpy(zOut, &u.a[i], sizeof(u.a)-i);
return sizeof(u.a)-1-i;
}
/*
@@ -1186,25 +1214,10 @@ void sqlite3FpDecode(FpDecode *p, double r, int iRound, int mxRound){
i = sizeof(p->zBuf)-1;
assert( v>0 );
while( v>=10 ){
static const union {
char a[200];
short int forAlignment;
} dig = {
"00010203040506070809"
"10111213141516171819"
"20212223242526272829"
"30313233343536373839"
"40414243444546474849"
"50515253545556575859"
"60616263646566676869"
"70717273747576777879"
"80818283848586878889"
"90919293949596979899"
};
int kk = (v%100)*2;
assert( TWO_BYTE_ALIGNMENT(&dig.a[kk]) );
assert( TWO_BYTE_ALIGNMENT(&sqlite3DigitPairs.a[kk]) );
assert( TWO_BYTE_ALIGNMENT(&p->zBuf[i-1]) );
*(u16*)(&p->zBuf[i-1]) = *(u16*)&dig.a[kk];
*(u16*)(&p->zBuf[i-1]) = *(u16*)&sqlite3DigitPairs.a[kk];
i -= 2;
v /= 100;
}