mirror of
https://github.com/MariaDB/server.git
synced 2025-01-31 02:51:44 +01:00
Bug#11754279 SIGNIFICANT INACCURACY IN DECIMAL MULTIPLICATION CALCULATIONS
frac is the number of decimal digits after the point For each multiplication in the expression, decimal_mul() does this: to->frac= from1->frac + from2->frac; /* store size in digits */ which will eventually overflow. The code for handling the overflow, will truncate the two digits in "1.75" to "1" Solution: Truncate to 31 significant fractional digits, when doing decimal multiplication.
This commit is contained in:
parent
d68cba3413
commit
b125abecb7
1 changed files with 17 additions and 16 deletions
|
@ -1989,44 +1989,45 @@ int decimal_mul(const decimal_t *from1, const decimal_t *from2, decimal_t *to)
|
|||
int intg1=ROUND_UP(from1->intg), intg2=ROUND_UP(from2->intg),
|
||||
frac1=ROUND_UP(from1->frac), frac2=ROUND_UP(from2->frac),
|
||||
intg0=ROUND_UP(from1->intg+from2->intg),
|
||||
frac0=frac1+frac2, error, i, j, d_to_move;
|
||||
frac0=frac1+frac2, error, iii, jjj, d_to_move;
|
||||
dec1 *buf1=from1->buf+intg1, *buf2=from2->buf+intg2, *buf0,
|
||||
*start2, *stop2, *stop1, *start0, carry;
|
||||
|
||||
sanity(to);
|
||||
|
||||
i=intg0; /* save 'ideal' values */
|
||||
j=frac0;
|
||||
iii= intg0; /* save 'ideal' values */
|
||||
jjj= frac0;
|
||||
FIX_INTG_FRAC_ERROR(to->len, intg0, frac0, error); /* bound size */
|
||||
to->sign= from1->sign != from2->sign;
|
||||
to->frac= from1->frac + from2->frac; /* store size in digits */
|
||||
set_if_smaller(to->frac, NOT_FIXED_DEC);
|
||||
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)) /* bounded integer-part */
|
||||
if (unlikely(iii > intg0)) /* bounded integer-part */
|
||||
{
|
||||
i-=intg0;
|
||||
j=i >> 1;
|
||||
intg1-= j;
|
||||
intg2-=i-j;
|
||||
iii-=intg0;
|
||||
jjj= iii >> 1;
|
||||
intg1-= jjj;
|
||||
intg2-=iii-jjj;
|
||||
frac1=frac2=0; /* frac0 is already 0 here */
|
||||
}
|
||||
else /* bounded fract part */
|
||||
{
|
||||
j-=frac0;
|
||||
i=j >> 1;
|
||||
jjj-=frac0;
|
||||
iii=jjj >> 1;
|
||||
if (frac1 <= frac2)
|
||||
{
|
||||
frac1-= i;
|
||||
frac2-=j-i;
|
||||
frac1-= iii;
|
||||
frac2-=jjj-iii;
|
||||
}
|
||||
else
|
||||
{
|
||||
frac2-= i;
|
||||
frac1-=j-i;
|
||||
frac2-= iii;
|
||||
frac1-=jjj-iii;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue