]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Enhance sqlite3AtoF() so that it honors the USELONGDOUBLE test-control. fp-to-decimal-refactor
authordrh <>
Mon, 3 Jul 2023 18:18:35 +0000 (18:18 +0000)
committerdrh <>
Mon, 3 Jul 2023 18:18:35 +0000 (18:18 +0000)
Enable the test/atof1.test module on non-intel platforms.

FossilOrigin-Name: b7850fd480535980d66f107c2746e7f7fc0a5379ec8244d84f7785533c83f276

manifest
manifest.uuid
src/util.c
test/atof1.test

index 7cabc9b86fffbe3868e582786fbd05aa65c60318..4bb15daf3351c263a41c4e38c738cb81e6fe49e8 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Whether\sor\snot\sto\suse\sthe\slong-double\sfloating\spoint\sconversion\stechnique\nis\snow\sa\stest-control\ssetting.
-D 2023-07-03T14:56:49.741
+C Enhance\ssqlite3AtoF()\sso\sthat\sit\shonors\sthe\sUSELONGDOUBLE\stest-control.\nEnable\sthe\stest/atof1.test\smodule\son\snon-intel\splatforms.
+D 2023-07-03T18:18:35.350
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -705,7 +705,7 @@ F src/trigger.c ad6ab9452715fa9a8075442e15196022275b414b9141b566af8cdb7a1605f2b0
 F src/update.c 0aa36561167a7c40d01163238c297297962f31a15a8d742216b3c37cdf25f731
 F src/upsert.c 5303dc6c518fa7d4b280ec65170f465c7a70b7ac2b22491598f6d0b4875b3145
 F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0
-F src/util.c 452f1e5e4a85b7869daf15d9b6468ac754836467004fa04c3419f2bd628eb6ad
+F src/util.c 5c6a3c7a88af0cbabb17707314b07f6026410610be73c6b6fba163b1cbf8b5ea
 F src/vacuum.c 604fcdaebe76f3497c855afcbf91b8fa5046b32de3045bab89cc008d68e40104
 F src/vdbe.c 74282a947234513872a83b0bab1b8c644ece64b3e27b053ef17677c8ff9c81e0
 F src/vdbe.h 41485521f68e9437fdb7ec4a90f9d86ab294e9bb8281e33b235915e29122cfc0
@@ -775,7 +775,7 @@ F test/async2.test c0a9bd20816d7d6a2ceca7b8c03d3d69c28ffb8b
 F test/async3.test d73a062002376d7edc1fe3edff493edbec1fc2f7
 F test/async4.test 1787e3952128aa10238bf39945126de7ca23685a
 F test/async5.test 383ab533fdb9f7ad228cc99ee66e1acb34cc0dc0
-F test/atof1.test 191ce0d7b0d527aafeafe659c31e2433e430324b5ebce3fb066178b4d9035767
+F test/atof1.test f2765d7fdc1348ae58b279d096d301a208e46da623213877b2ba580dc2768975
 F test/atomic.test 065a453dde33c77ff586d91ccaa6ed419829d492dbb1a5694b8a09f3f9d7d061
 F test/atomic2.test b6863b4aa552543874f80b42fb3063f1c8c2e3d8e56b6562f00a3cc347b5c1da
 F test/atrc.c c388fac43dbba05c804432a7135ae688b32e8f25818e9994ffba4b64cf60c27c
@@ -2042,8 +2042,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 9435ed76cd9bb1be02768b3853a2323834f67bda75d3e3f76f6aa7bd0bade3d7
-R c19a4cd19e732c53bd925a8fc2b0f976
+P 02ae6caff1f7925c696ad263fe78b1036364d24b6373e1baec10d53aafb14a12
+R bad32f05b3c6a0ddbf09f09fc45b76f6
 U drh
-Z ccc178a785227b10fda86cb46a381790
+Z 7edb4dd9862f63ed43ef736b26696576
 # Remove this line to create a well-formed Fossil manifest.
index 64fd4d35398d7e6791ba8f58d030d99039a622a6..ecc3aca4fdf1276c5a7bbf06619654c130652ac8 100644 (file)
@@ -1 +1 @@
-02ae6caff1f7925c696ad263fe78b1036364d24b6373e1baec10d53aafb14a12
\ No newline at end of file
+b7850fd480535980d66f107c2746e7f7fc0a5379ec8244d84f7785533c83f276
\ No newline at end of file
index dbf31d30f372ed879249e5b7fc05667152bf53a9..f14cbf2594e604801d2af17a6f636744c34c108c 100644 (file)
@@ -386,43 +386,34 @@ u8 sqlite3StrIHash(const char *z){
   return h;
 }
 
-/*
-** Compute 10 to the E-th power.  Examples:  E==1 results in 10.
-** E==2 results in 100.  E==50 results in 1.0e50.
+/* Double-Double multiplication.  *(z,zz) = (x,xx) * (y,yy)
 **
-** This routine only works for values of E between 1 and 341.
+** Reference:
+**   T. J. Dekker, "A Floating-Point Technique for Extending the
+**   Available Precision".  1971-07-26.
 */
-static LONGDOUBLE_TYPE sqlite3Pow10(int E){
-#if defined(_MSC_VER)
-  static const LONGDOUBLE_TYPE x[] = {
-    1.0e+001L,
-    1.0e+002L,
-    1.0e+004L,
-    1.0e+008L,
-    1.0e+016L,
-    1.0e+032L,
-    1.0e+064L,
-    1.0e+128L,
-    1.0e+256L
-  };
-  LONGDOUBLE_TYPE r = 1.0;
-  int i;
-  assert( E>=0 && E<=307 );
-  for(i=0; E!=0; i++, E >>=1){
-    if( E & 1 ) r *= x[i];
-  }
-  return r;
-#else
-  LONGDOUBLE_TYPE x = 10.0;
-  LONGDOUBLE_TYPE r = 1.0;
-  while(1){
-    if( E & 1 ) r *= x;
-    E >>= 1;
-    if( E==0 ) break;
-    x *= x;
-  }
-  return r;
-#endif
+static void dekkerMul2(
+  double x,  double xx,
+  double y,  double yy,
+  double *z, double *zz
+){
+  double hx, tx, hy, ty, p, q, c, cc;
+  u64 m;
+  memcpy(&m, &x, 8);
+  m &= 0xfffffffffc000000L;
+  memcpy(&hx, &m, 8);
+  tx = x - hx;
+  memcpy(&m, &y, 8);
+  m &= 0xfffffffffc000000L;
+  memcpy(&hy, &m, 8);
+  ty = y - hy;
+  p = hx*hy;
+  q = hx*ty + tx*hy;
+  c = p+q;
+  cc = p - c + q + tx*ty;
+  cc = x*yy + xx*y + cc;
+  *z = c + cc;
+  *zz = c - *z + cc;
 }
 
 /*
@@ -463,12 +454,11 @@ int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){
   const char *zEnd;
   /* sign * significand * (10 ^ (esign * exponent)) */
   int sign = 1;    /* sign of significand */
-  i64 s = 0;       /* 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 */
-  LONGDOUBLE_TYPE result;
   int nDigit = 0;  /* Number of digits processed */
   int eType = 1;   /* 1: pure integer,  2+: fractional  -1 or less: bad UTF16 */
 
@@ -508,7 +498,7 @@ int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){
   while( z<zEnd && sqlite3Isdigit(*z) ){
     s = s*10 + (*z - '0');
     z+=incr; nDigit++;
-    if( s>=((LARGEST_INT64-9)/10) ){
+    if( s>=((LARGEST_UINT64-9)/10) ){
       /* skip non-significant significand digits
       ** (increase exponent by d to shift decimal left) */
       while( z<zEnd && sqlite3Isdigit(*z) ){ z+=incr; d++; }
@@ -523,7 +513,7 @@ int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){
     /* copy digits from after decimal to significand
     ** (decrease exponent by d to shift decimal right) */
     while( z<zEnd && sqlite3Isdigit(*z) ){
-      if( s<((LARGEST_INT64-9)/10) ){
+      if( s<((LARGEST_UINT64-9)/10) ){
         s = s*10 + (*z - '0');
         d--;
         nDigit++;
@@ -563,78 +553,79 @@ int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){
   while( z<zEnd && sqlite3Isspace(*z) ) z+=incr;
 
 do_atof_calc:
+  /* Zero is a special case */
+  if( s==0 ){
+    *pResult = sign<0 ? -0.0 : +0.0;
+    goto atof_return;
+  }
+
   /* adjust exponent by d, and update sign */
   e = (e*esign) + d;
-  if( e<0 ) {
-    esign = -1;
-    e *= -1;
-  } else {
-    esign = 1;
-  }
-
-  if( s==0 ) {
-    /* In the IEEE 754 standard, zero is signed. */
-    result = sign<0 ? -(double)0 : (double)0;
-  } else {
-    /* Attempt to reduce exponent.
-    **
-    ** Branches that are not required for the correct answer but which only
-    ** help to obtain the correct answer faster are marked with special
-    ** comments, as a hint to the mutation tester.
-    */
-    while( e>0 ){                                       /*OPTIMIZATION-IF-TRUE*/
-      if( esign>0 ){
-        if( s>=(LARGEST_INT64/10) ) break;             /*OPTIMIZATION-IF-FALSE*/
-        s *= 10;
-      }else{
-        if( s%10!=0 ) break;                           /*OPTIMIZATION-IF-FALSE*/
-        s /= 10;
-      }
-      e--;
-    }
 
-    /* adjust the sign of significand */
-    s = sign<0 ? -s : s;
+  /* Try to adjust the exponent to make it smaller */
+  while( e>0 && s<(LARGEST_UINT64/10) ){
+    s *= 10;
+    e--;
+  }
+  while( e<0 && (s%10)==0 ){
+    s /= 10;
+    e++;
+  }
 
-    if( e==0 ){                                         /*OPTIMIZATION-IF-TRUE*/
-      result = (LONGDOUBLE_TYPE)s;
+  if( e==0 ){
+    *pResult = s;
+  }else if( sqlite3Config.bUseLongDouble ){
+    LONGDOUBLE_TYPE r = (LONGDOUBLE_TYPE)s;
+    if( e>0 ){
+      while( e>=100  ){ e-=100; r *= 1.0e+100L; }
+      while( e>=10   ){ e-=10;  r *= 1.0e+10L;  }
+      while( e>=1    ){ e-=1;   r *= 1.0e+01L;  }
     }else{
-      /* attempt to handle extremely small/large numbers better */
-      if( e>307 ){                                      /*OPTIMIZATION-IF-TRUE*/
-        if( e<342 ){                                    /*OPTIMIZATION-IF-TRUE*/
-          LONGDOUBLE_TYPE scale = sqlite3Pow10(e-308);
-          if( esign<0 ){
-            result = s / scale;
-            result /= 1.0e+308L;
-          }else{
-            result = s * scale;
-            result *= 1.0e+308L;
-          }
-        }else{ assert( e>=342 );
-          if( esign<0 ){
-            result = 0.0*s;
-          }else{
-#ifdef INFINITY
-            result = INFINITY*s;
-#else
-            result = 1e308*1e308*s;  /* Infinity */
-#endif
-          }
-        }
-      }else{
-        LONGDOUBLE_TYPE scale = sqlite3Pow10(e);
-        if( esign<0 ){
-          result = s / scale;
-        }else{
-          result = s * scale;
-        }
+      while( e<=-100 ){ e+=100; r *= 1.0e-100L; }
+      while( e<=-10  ){ e+=10;  r *= 1.0e-10L;  }
+      while( e<=-1   ){ e+=1;   r *= 1.0e-01L;  }
+    }
+    *pResult = r;
+  }else{
+    double r, rr;
+    u64 s2;
+    r = (double)s;
+    s2 = (u64)r;
+    rr = s>=s2 ? (double)(s - s2) : -(double)(s2 - s);
+    if( e>0 ){
+      while( e>=100  ){
+        e -= 100;
+        dekkerMul2(r, rr, 1.0e+100, -1.5902891109759918046e+83, &r, &rr);
+      }
+      while( e>=10   ){
+        e -= 10;
+        dekkerMul2(r, rr, 1.0e+10, 0.0, &r, &rr);
+      }
+      while( e>=1    ){
+        e -= 1;
+        dekkerMul2(r, rr, 1.0e+01, 0.0, &r, &rr);
+      }
+    }else{
+      while( e<=-100 ){
+        e += 100;
+        dekkerMul2(r, rr, 1.0e-100, -1.99918998026028836196e-117, &r, &rr);
+      }
+      while( e<=-10  ){
+        e += 10;
+        dekkerMul2(r,rr, 1.0e-10, -3.6432197315497741579e-27, &r, &rr);
+      }
+      while( e<=-1   ){
+        e += 1;
+        dekkerMul2(r,rr, 1.0e-01, -5.5511151231257827021e-18, &r, &rr);
       }
     }
+    *pResult = r+rr;
+    if( sqlite3IsNaN(*pResult) ) *pResult = 1e300*1e300;
   }
+  if( sign<0 ) *pResult = -*pResult;
+  assert( !sqlite3IsNaN(*pResult) );
 
-  /* store the result */
-  *pResult = result;
-
+atof_return:
   /* return true if number and no extra non-whitespace characters after */
   if( z==zEnd && nDigit>0 && eValid && eType>0 ){
     return eType;
@@ -928,36 +919,6 @@ int sqlite3Atoi(const char *z){
   return x;
 }
 
-/* Double-Double multiplication.  *(z,zz) = (x,xx) * (y,yy)
-**
-** Reference:
-**   T. J. Dekker, "A Floating-Point Technique for Extending the
-**   Available Precision".  1971-07-26.
-*/
-static void dekkerMul2(
-  double x,  double xx,
-  double y,  double yy,
-  double *z, double *zz
-){
-  double hx, tx, hy, ty, p, q, c, cc;
-  u64 m;
-  memcpy(&m, &x, 8);
-  m &= 0xfffffffffc000000L;
-  memcpy(&hx, &m, 8);
-  tx = x - hx;
-  memcpy(&m, &y, 8);
-  m &= 0xfffffffffc000000L;
-  memcpy(&hy, &m, 8);
-  ty = y - hy;
-  p = hx*hy;
-  q = hx*ty + tx*hy;
-  c = p+q;
-  cc = p - c + q + tx*ty;
-  cc = x*yy + xx*y + cc;
-  *z = c + cc;
-  *zz = c - *z + cc;
-}
-
 /*
 ** Decode a floating-point value into an approximate decimal
 ** representation.
index 9386fb05893bcbb8124d40fc129bb68b3bb89a7c..95f443ce0d4171b6ff06aa2f0ecdd490e3585d75 100644 (file)
 set testdir [file dirname $argv0]
 source $testdir/tester.tcl
 
-if {$::longdouble_size<=8} {
-  finish_test
-  return
-}
-if {$::tcl_platform(machine)!="x86_64"} {
-  finish_test
-  return
-}
-
+set mxpow [expr {[use_long_double]?100:35}]
 expr srand(1)
 for {set i 1} {$i<20000} {incr i} {
-  set pow [expr {int((rand()-0.5)*100)}]
+  set pow [expr {int((rand()-0.5)*$mxpow)}]
   set x [expr {pow((rand()-0.5)*2*rand(),$pow)}]
   set xf [format %.32e $x]