List:Commits« Previous MessageNext Message »
From:Alexey Kopytov Date:September 22 2006 3:40pm
Subject:bk commit into 5.0 tree (kaa:1.2235)
View as plain text  
Below is the list of changes that have just been committed into a local
5.0 repository of kaa. When kaa does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet@stripped, 2006-09-22 19:40:07+04:00, kaa@stripped +3 -0
  Merge polly.local:/tmp/22129/bug22129/my41-bug22129
  into  polly.local:/tmp/22129/bug22129/my50-bug22129
  MERGE: 1.1616.2658.18

  mysql-test/r/type_float.result@stripped, 2006-09-22 19:40:05+04:00, kaa@stripped +0 -0
    SCCS merged
    MERGE: 1.25.1.11

  mysql-test/t/type_float.test@stripped, 2006-09-22 19:40:05+04:00, kaa@stripped +0 -0
    SCCS merged
    MERGE: 1.15.1.7

  strings/strtod.c@stripped, 2006-09-22 19:37:55+04:00, kaa@stripped +0 -0
    Auto merged
    MERGE: 1.15.2.1

# This is a BitKeeper patch.  What follows are the unified diffs for the
# set of deltas contained in the patch.  The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User:	kaa
# Host:	polly.local
# Root:	/tmp/22129/bug22129/my50-bug22129/RESYNC

--- 1.21/strings/strtod.c	2006-09-22 19:40:12 +04:00
+++ 1.22/strings/strtod.c	2006-09-22 19:40:12 +04:00
@@ -30,7 +30,8 @@
 #include "m_ctype.h"
 
 #define MAX_DBL_EXP	308
-#define MAX_RESULT_FOR_MAX_EXP 1.79769313486232
+#define MAX_RESULT_FOR_MAX_EXP 1.7976931348623157
+#define MIN_RESULT_FOR_MIN_EXP 2.225073858507202
 static double scaler10[] = {
   1.0, 1e10, 1e20, 1e30, 1e40, 1e50, 1e60, 1e70, 1e80, 1e90
 };
@@ -57,10 +58,11 @@ double my_strtod(const char *str, char *
 {
   double result= 0.0;
   uint negative= 0, ndigits, dec_digits= 0, neg_exp= 0;
-  int exp= 0, digits_after_dec_point= 0;
+  int exp= 0, digits_after_dec_point= 0, tmp_exp;
   const char *old_str, *end= *end_ptr, *start_of_number;
   char next_char;
   my_bool overflow=0;
+  double scaler= 1.0;
 
   *error= 0;
   if (str >= end)
@@ -91,6 +93,7 @@ double my_strtod(const char *str, char *
   while ((next_char= *str) >= '0' && next_char <= '9')
   {
     result= result*10.0 + (next_char - '0');
+    scaler= scaler*10.0;
     if (++str == end)
     {
       next_char= 0;                             /* Found end of string */
@@ -114,6 +117,7 @@ double my_strtod(const char *str, char *
     {
       result= result*10.0 + (next_char - '0');
       digits_after_dec_point++;
+      scaler= scaler*10.0;
       if (++str == end)
       {
         next_char= 0;
@@ -144,39 +148,54 @@ double my_strtod(const char *str, char *
       } while (str < end && my_isdigit(&my_charset_latin1, *str));
     }
   }
-  if ((exp= (neg_exp ? exp + digits_after_dec_point :
-             exp - digits_after_dec_point)))
+  tmp_exp= neg_exp ? exp + digits_after_dec_point : exp - digits_after_dec_point;
+  if (tmp_exp)
   {
-    double scaler;
-    if (exp < 0)
-    {
-      exp= -exp;
-      neg_exp= 1;                               /* neg_exp was 0 before */
-    }
-    if (exp + ndigits >= MAX_DBL_EXP + 1 && result)
-    {
-      /*
-        This is not 100 % as we actually will give an owerflow for
-        17E307 but not for 1.7E308 but lets cut some corners to make life
-        simpler
-      */
-      if (exp + ndigits > MAX_DBL_EXP + 1 ||
-          result >= MAX_RESULT_FOR_MAX_EXP)
+    int order;
+    /*
+      Check for underflow/overflow.
+      order is such an integer number that f = C * 10 ^ order,
+      where f is the resulting floating point number and 1 <= C < 10.
+      Here we compute the modulus
+    */
+    order= exp + (neg_exp ? -1 : 1) * (ndigits - 1);
+    if (order < 0)
+      order= -order;
+    if (order >= MAX_DBL_EXP && result)
+    {
+      double c;
+      /* Compute modulus of C (see comment above) */
+      c= result / scaler * 10.0;
+      if (neg_exp)
       {
-        if (neg_exp)
+        if (order > MAX_DBL_EXP || c < MIN_RESULT_FOR_MIN_EXP)
+        {
           result= 0.0;
-        else
+          goto done;
+        }
+      }
+      else
+      {
+        if (order > MAX_DBL_EXP || c > MAX_RESULT_FOR_MAX_EXP)
+        {
           overflow= 1;
-        goto done;
+          goto done;
+        }
       }
     }
-    scaler= 1.0;
+
+    exp= tmp_exp;
+    if (exp < 0)
+    {
+      exp= -exp;
+      neg_exp= 1;                               /* neg_exp was 0 before */
+    }
     while (exp >= 100)
     {
-      scaler*= 1.0e100;
+      result= neg_exp ? result/1.0e100 : result*1.0e100;
       exp-= 100;
     }
-    scaler*= scaler10[exp/10]*scaler1[exp%10];
+    scaler= scaler10[exp/10]*scaler1[exp%10];
     if (neg_exp)
       result/= scaler;
     else

--- 1.46/mysql-test/r/type_float.result	2006-09-22 19:40:12 +04:00
+++ 1.47/mysql-test/r/type_float.result	2006-09-22 19:40:12 +04:00
@@ -262,6 +262,13 @@ desc t3;
 Field	Type	Null	Key	Default	Extra
 a	decimal(21,2)	NO		0.00	
 drop table t1,t2,t3;
+select 1e-308, 1.00000001e-300, 100000000e-300;
+1e-308	1.00000001e-300	100000000e-300
+0	1.00000001e-300	1e-292
+select 10e307;
+10e307
+1e+308
+End of 4.1 tests
 create table t1 (s1 float(0,2));
 ERROR 42000: For float(M,D), double(M,D) or decimal(M,D), M must be >= D (column 's1').
 create table t1 (s1 float(1,2));

--- 1.30/mysql-test/t/type_float.test	2006-09-22 19:40:12 +04:00
+++ 1.31/mysql-test/t/type_float.test	2006-09-22 19:40:12 +04:00
@@ -178,7 +178,16 @@ show warnings;
 desc t3;
 drop table t1,t2,t3;
 
-# End of 4.1 tests
+#
+# Bug #22129: A small double precision number becomes zero
+#
+# check if underflows are detected correctly
+select 1e-308, 1.00000001e-300, 100000000e-300;
+
+# check if overflows are detected correctly
+select 10e307;
+
+--echo End of 4.1 tests
 
 #
 # bug #12694 (float(m,d) specifications)
Thread
bk commit into 5.0 tree (kaa:1.2235)Alexey Kopytov22 Sep