From: drh <> Date: Sun, 22 Mar 2026 02:26:38 +0000 (+0000) Subject: Performance improvements in the floating-point number parser. X-Git-Tag: major-release~62^2~2 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=99571bf3c371076f85ace7e13ac8cdcb8f81e5c6;p=thirdparty%2Fsqlite.git Performance improvements in the floating-point number parser. FossilOrigin-Name: aea648f3668219a2539160eb68c77ddd06aa8eac235c1326fe7b1547288b11ee --- diff --git a/manifest b/manifest index 499ce65cdd..785e7550f3 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Because\sversion\s3.52.0\swas\swithdrawn,\sthat\smeans\sQRF\shas\snever\sbeen\nofficially\sreleased.\s\sHence\sthe\snew\snMultiInsert\sfield\sof\sthe\sspec\ncan\sbe\smoved\sout\sof\sthe\sextensions\sarea\sand\sinto\sthe\smain\spart\sof\sthe\nspec,\sand\sthe\sversion\snumber\scan\sdrop\sback\sfrom\s2\sto\s1. -D 2026-03-21T19:49:38.046 +C Performance\simprovements\sin\sthe\sfloating-point\snumber\sparser. +D 2026-03-22T02:26:38.451 F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea @@ -798,7 +798,7 @@ F src/trigger.c 4bf3bfb3851d165e4404a9f9e69357345f3f7103378c07e07139fdd8aeb7bd20 F src/update.c 3e5e7ff66fa19ebe4d1b113d480639a24cc1175adbefabbd1a948a07f28e37cf F src/upsert.c 215328c3f91623c520ec8672c44323553f12caeb4f01b1090ebdca99fdf7b4f1 F src/utf.c 7267c3fb9e2467020507601af3354c2446c61f444387e094c779dccd5ca62165 -F src/util.c 51662502243422f3238a7220fe00de32d9a7d0d3149dd33c6d721d7039cb2e74 +F src/util.c 024100479ff7cf06a5635d4353e0ba1f1b9b6d24930b5d88fbe33afc4d85b825 F src/vacuum.c d3d35d8ae893d419ade5fa196d761a83bddcbb62137a1a157ae751ef38b26e82 F src/vdbe.c dbafc6f5762f9ae90d9dc9ed065a31743a8ceafbdbfb1a0a3a228921fb3cc36a F src/vdbe.h 70e862ac8a11b590f8c1eaac17a0078429d42bc4ea3f757a9af0f451dd966a71 @@ -2195,8 +2195,11 @@ F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee F tool/warnings.sh a554d13f6e5cf3760f041b87939e3d616ec6961859c3245e8ef701d1eafc2ca2 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f F tool/winmain.c 00c8fb88e365c9017db14c73d3c78af62194d9644feaf60e220ab0f411f3604c -P 8e1d0c4eac303cd0834449f4792605c0ed983db1f360af42300f0048dadbbef8 -R a41bf058e42684a09ca798bb17f3d8b8 +P cf19982241afb17e3db4148b8257f6737141935a291c340ab085c42ed946af1a +R fb2b20242625ffa81d29970e27082419 +T *branch * optimize-atof +T *sym-optimize-atof * +T -sym-trunk * U drh -Z 3d0e6419f275717c17fd604ea7b5f9df +Z e1f1ebc5f1aeac5a9d37ac5faaa6d91b # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.tags b/manifest.tags index bec971799f..b5d58b07d5 100644 --- a/manifest.tags +++ b/manifest.tags @@ -1,2 +1,2 @@ -branch trunk -tag trunk +branch optimize-atof +tag optimize-atof diff --git a/manifest.uuid b/manifest.uuid index f9384f17f2..7c4f608cc7 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -cf19982241afb17e3db4148b8257f6737141935a291c340ab085c42ed946af1a +aea648f3668219a2539160eb68c77ddd06aa8eac235c1326fe7b1547288b11ee diff --git a/src/util.c b/src/util.c index ae6b231ad1..08798226b4 100644 --- a/src/util.c +++ b/src/util.c @@ -842,99 +842,112 @@ static double sqlite3Fp10Convert2(u64 d, int p){ #endif int sqlite3AtoF(const char *z, double *pResult){ #ifndef SQLITE_OMIT_FLOATING_POINT - /* sign * significand * (10 ^ (esign * exponent)) */ - 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 */ - - *pResult = 0.0; /* Default return value, in case of an error */ - - /* skip leading spaces */ - while( sqlite3Isspace(*z) ) z++; - - /* get sign of significand */ - if( *z=='-' ){ + int neg = 0; /* True for a negative value */ + u64 s = 0; /* mantissa */ + int d = 0; /* Value is s * pow(10,d) */ + int seenDigit = 0; /* true if any digits seen */ + int seenFP = 0; /* True if we've seen a "." or a "e" */ + + start_of_text: + if( sqlite3Isdigit(z[0]) ){ + parse_integer_part: + seenDigit = 1; + s = z[0] - '0'; + z++; + while( sqlite3Isdigit(z[0]) ){ + s = s*10 + (z[0] - '0'); + z++; + if( s>=(LARGEST_INT64-9)/10 ){ + while( sqlite3Isdigit(z[0]) ){ z++; d++; } + break; + } + } + }else if( z[0]=='-' ){ neg = 1; z++; - }else if( *z=='+' ){ + if( sqlite3Isdigit(z[0]) ) goto parse_integer_part; + }else if( z[0]=='+' ){ z++; - } - - /* copy max significant digits to significand */ - while( sqlite3Isdigit(*z) ){ - s = s*10 + (*z - '0'); - z++; nDigit++; - if( s>=((LARGEST_INT64-9)/10) ){ - /* skip non-significant significand digits - ** (increase exponent by d to shift decimal left) */ - while( sqlite3Isdigit(*z) ){ z++; d++; } - } + if( sqlite3Isdigit(z[0]) ) goto parse_integer_part; + }else if( sqlite3Isspace(z[0]) ){ + do{ z++; }while( sqlite3Isspace(z[0]) ); + goto start_of_text; + }else{ + s = 0; } /* if decimal point is present */ if( *z=='.' ){ z++; - eType++; - /* copy digits from after decimal to significand - ** (decrease exponent by d to shift decimal right) */ - while( sqlite3Isdigit(*z) ){ + seenFP = 1; + if( sqlite3Isdigit(z[0]) ){ + seenDigit = 1; if( s<((LARGEST_INT64-9)/10) ){ - s = s*10 + (*z - '0'); - d--; - nDigit++; + s = s*10 + z[0] - '0'; + d = -1; } z++; + while( sqlite3Isdigit(z[0]) ){ + if( s<((LARGEST_INT64-9)/10) ){ + s = s*10 + (*z - '0'); + d--; + } + z++; + } } } + if( !seenDigit ){ + *pResult = 0.0; + return 0; + } + /* if exponent is present */ if( *z=='e' || *z=='E' ){ - int esign = 1; /* sign of exponent */ + int esign; z++; - eType++; - + /* get sign of exponent */ if( *z=='-' ){ esign = -1; z++; - }else if( *z=='+' ){ - z++; + }else{ + esign = +1; + if( *z=='+' ){ + z++; + } } /* copy digits to exponent */ if( sqlite3Isdigit(*z) ){ int exp = *z - '0'; z++; + seenFP = 1; while( sqlite3Isdigit(*z) ){ exp = exp<10000 ? (exp*10 + (*z - '0')) : 10000; z++; } d += esign*exp; }else{ - eType = -1; + z--; /* Leave z[0] at 'e' or '+' or '-', + ** so that the return is 0 or -1 */ } } /* skip trailing spaces */ while( sqlite3Isspace(*z) ) z++; - /* Zero is a special case */ - if( s==0 ){ - *pResult = neg ? -0.0 : +0.0; - }else{ - *pResult = sqlite3Fp10Convert2(s,d); - if( neg ) *pResult = -*pResult; - assert( !sqlite3IsNaN(*pResult) ); - } + /* Convert s*pow(10,d) into real */ + *pResult = s ? sqlite3Fp10Convert2(s,d) : 0.0; + if( neg ) *pResult = -*pResult; + assert( !sqlite3IsNaN(*pResult) ); /* return true if number and no extra non-whitespace characters after */ - if( z[0]==0 && nDigit>0 ){ - return eType; - }else if( eType>=2 && nDigit>0 ){ - return -1; + if( z[0]==0 ){ + return seenFP+1; + }else if( seenFP ){ + return -1; /* Prefix is a floating point number */ }else{ - return 0; + return 0; /* Prefix is just an integer */ } #else return !sqlite3Atoi64(z, pResult, strlen(z), SQLITE_UTF8);