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#36270 | Tatjana A Nuernberg | 13 May 2008 |