List:Commits« Previous MessageNext Message »
From:Tatjana A Nuernberg Date:May 13 2008 12:45pm
Subject:bk commit into 5.0 tree (tnurnberg:1.2610) BUG#36270
View as plain text  
Below is the list of changes that have just been committed into a local
5.0 repository of tnurnberg.  When tnurnberg 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, 2008-05-13 14:45:50+02:00, tnurnberg@stripped +3 -0
  Bug#36270: incorrect calculation result - works in 4.1 but not in 5.0 or 5.1
  
  When the fractional part in a multiplication of DECIMALs
  overflowed, we truncated the first operand rather than the
  longest. Now truncating least significant places instead
  for more precise multiplications.

  mysql-test/r/type_newdecimal.result@stripped, 2008-05-13 14:45:48+02:00, tnurnberg@stripped +5 -0
    show that if we need to truncate the scale of an operand, we pick the
    right one (that is, we discard the least significant decimal places)

  mysql-test/t/type_newdecimal.test@stripped, 2008-05-13 14:45:48+02:00, tnurnberg@stripped +9 -0
    show that if we need to truncate the scale of an operand, we pick the
    right one (that is, we discard the least significant decimal places)

  strings/decimal.c@stripped, 2008-05-13 14:45:48+02:00, tnurnberg@stripped +15 -7
    when needing to disregard fractional parts, pick the least
    significant ones

diff -Nrup a/mysql-test/r/type_newdecimal.result b/mysql-test/r/type_newdecimal.result
--- a/mysql-test/r/type_newdecimal.result	2007-11-17 19:05:29 +01:00
+++ b/mysql-test/r/type_newdecimal.result	2008-05-13 14:45:48 +02:00
@@ -1519,4 +1519,9 @@ SELECT f1 FROM t1;
 f1
 99999999999999999999999999999.999999999999999999999999999999
 DROP TABLE t1;
+select (1.20396873 * 0.89550000 * 0.68000000 * 1.08721696 * 0.99500000 *
+1.01500000 * 1.01500000 * 0.99500000);
+(1.20396873 * 0.89550000 * 0.68000000 * 1.08721696 * 0.99500000 *
+1.01500000 * 1.01500000 * 0.99500000)
+0.812988073953673124592306939480
 End of 5.0 tests
diff -Nrup a/mysql-test/t/type_newdecimal.test b/mysql-test/t/type_newdecimal.test
--- a/mysql-test/t/type_newdecimal.test	2007-11-17 19:05:29 +01:00
+++ b/mysql-test/t/type_newdecimal.test	2008-05-13 14:45:48 +02:00
@@ -1216,4 +1216,13 @@ DESC t1;
 SELECT f1 FROM t1;
 DROP TABLE t1;
 
+#
+# Bug #36270: incorrect calculation result - works in 4.1 but not in 5.0 or 5.1
+#
+
+# show that if we need to truncate the scale of an operand, we pick the
+# right one (that is, we discard the least significant decimal places)
+select (1.20396873 * 0.89550000 * 0.68000000 * 1.08721696 * 0.99500000 *
+        1.01500000 * 1.01500000 * 0.99500000);
+
 --echo End of 5.0 tests
diff -Nrup a/strings/decimal.c b/strings/decimal.c
--- a/strings/decimal.c	2008-01-14 16:16:32 +01:00
+++ b/strings/decimal.c	2008-05-13 14:45:48 +02:00
@@ -1999,18 +1999,18 @@ int decimal_mul(decimal_t *from1, decima
 
   sanity(to);
 
-  i=intg0;
+  i=intg0;                                       /* save 'ideal' values */
   j=frac0;
-  FIX_INTG_FRAC_ERROR(to->len, intg0, frac0, error);
+  FIX_INTG_FRAC_ERROR(to->len, intg0, frac0, error);  /* bound size */
   to->sign=from1->sign != from2->sign;
-  to->frac=from1->frac+from2->frac;
+  to->frac=from1->frac+from2->frac;              /* store size in digits */
   to->intg=intg0*DIG_PER_DEC1;
 
   if (unlikely(error))
   {
     set_if_smaller(to->frac, frac0*DIG_PER_DEC1);
     set_if_smaller(to->intg, intg0*DIG_PER_DEC1);
-    if (unlikely(i > intg0))
+    if (unlikely(i > intg0))                     /* bounded integer-part */
     {
       i-=intg0;
       j=i >> 1;
@@ -2018,12 +2018,20 @@ int decimal_mul(decimal_t *from1, decima
       intg2-=i-j;
       frac1=frac2=0; /* frac0 is already 0 here */
     }
-    else
+    else                                         /* bounded fract part */
     {
       j-=frac0;
       i=j >> 1;
-      frac1-= i;
-      frac2-=j-i;
+      if (frac1 <= frac2)
+      {
+        frac1-= i;
+        frac2-=j-i;
+      }
+      else
+      {
+        frac2-= i;
+        frac1-=j-i;
+      }
     }
   }
   start0=to->buf+intg0+frac0-1;
Thread
bk commit into 5.0 tree (tnurnberg:1.2610) BUG#36270Tatjana A Nuernberg13 May