]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Performance improvements in the floating-point number parser.
authordrh <>
Sun, 22 Mar 2026 02:26:38 +0000 (02:26 +0000)
committerdrh <>
Sun, 22 Mar 2026 02:26:38 +0000 (02:26 +0000)
FossilOrigin-Name: aea648f3668219a2539160eb68c77ddd06aa8eac235c1326fe7b1547288b11ee

manifest
manifest.tags
manifest.uuid
src/util.c

index 499ce65cdd333acab64e60c975de79edd6abd25b..785e7550f3a48ae3ea59bd77b7362e9be78a5561 100644 (file)
--- 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.
index bec971799ff1b8ee641c166c7aeb22d12c785393..b5d58b07d5efa671d43541f482d92de1a3341dd1 100644 (file)
@@ -1,2 +1,2 @@
-branch trunk
-tag trunk
+branch optimize-atof
+tag optimize-atof
index f9384f17f27676b9dde5eae55a06678886b8f3d3..7c4f608cc7f9f103281a269d01ad53c98b84608c 100644 (file)
@@ -1 +1 @@
-cf19982241afb17e3db4148b8257f6737141935a291c340ab085c42ed946af1a
+aea648f3668219a2539160eb68c77ddd06aa8eac235c1326fe7b1547288b11ee
index ae6b231ad1f104b156e20e3c16626fb100b87ef4..08798226b429ee58e246bb106cbbd1ea47a27579 100644 (file)
@@ -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);