summaryrefslogtreecommitdiff
path: root/strings/decimal.c
diff options
context:
space:
mode:
authorChad MILLER <chad@mysql.com>2008-08-15 15:46:21 -0400
committerChad MILLER <chad@mysql.com>2008-08-15 15:46:21 -0400
commitd0cf2fa6e73fd9987546dc7fca80e2c661b05876 (patch)
tree53f9a18c71b7efec31283b2940d94cf6373801c3 /strings/decimal.c
parent18e93e8fd9ab23f0bac9d68b7af1840f8122e74e (diff)
downloadmariadb-git-d0cf2fa6e73fd9987546dc7fca80e2c661b05876.tar.gz
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. (Queuing at demand of Trudy/Davi.)
Diffstat (limited to 'strings/decimal.c')
-rw-r--r--strings/decimal.c22
1 files changed, 15 insertions, 7 deletions
diff --git a/strings/decimal.c b/strings/decimal.c
index 3176cf6afa7..8b431ad9bab 100644
--- a/strings/decimal.c
+++ b/strings/decimal.c
@@ -1999,18 +1999,18 @@ int decimal_mul(decimal_t *from1, decimal_t *from2, decimal_t *to)
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, decimal_t *from2, decimal_t *to)
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;