From: Date: May 13 2008 2:45pm Subject: bk commit into 5.0 tree (tnurnberg:1.2610) BUG#36270 List-Archive: http://lists.mysql.com/commits/46651 X-Bug: 36270 Message-Id: <20080513124553.6E76C427BEEA@noir.koehntopp.de> 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;