Commit 6cbbe239 authored by Tor Didriksen's avatar Tor Didriksen

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.
parent fe4fe4e1
...@@ -1989,44 +1989,45 @@ int decimal_mul(const decimal_t *from1, const decimal_t *from2, decimal_t *to) ...@@ -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), int intg1=ROUND_UP(from1->intg), intg2=ROUND_UP(from2->intg),
frac1=ROUND_UP(from1->frac), frac2=ROUND_UP(from2->frac), frac1=ROUND_UP(from1->frac), frac2=ROUND_UP(from2->frac),
intg0=ROUND_UP(from1->intg+from2->intg), 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, dec1 *buf1=from1->buf+intg1, *buf2=from2->buf+intg2, *buf0,
*start2, *stop2, *stop1, *start0, carry; *start2, *stop2, *stop1, *start0, carry;
sanity(to); sanity(to);
i=intg0; /* save 'ideal' values */ iii= intg0; /* save 'ideal' values */
j=frac0; jjj= frac0;
FIX_INTG_FRAC_ERROR(to->len, intg0, frac0, error); /* bound size */ FIX_INTG_FRAC_ERROR(to->len, intg0, frac0, error); /* bound size */
to->sign=from1->sign != from2->sign; to->sign= from1->sign != from2->sign;
to->frac=from1->frac+from2->frac; /* store size in digits */ to->frac= from1->frac + from2->frac; /* store size in digits */
set_if_smaller(to->frac, NOT_FIXED_DEC);
to->intg=intg0*DIG_PER_DEC1; to->intg=intg0*DIG_PER_DEC1;
if (unlikely(error)) if (unlikely(error))
{ {
set_if_smaller(to->frac, frac0*DIG_PER_DEC1); set_if_smaller(to->frac, frac0*DIG_PER_DEC1);
set_if_smaller(to->intg, intg0*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; iii-=intg0;
j=i >> 1; jjj= iii >> 1;
intg1-= j; intg1-= jjj;
intg2-=i-j; intg2-=iii-jjj;
frac1=frac2=0; /* frac0 is already 0 here */ frac1=frac2=0; /* frac0 is already 0 here */
} }
else /* bounded fract part */ else /* bounded fract part */
{ {
j-=frac0; jjj-=frac0;
i=j >> 1; iii=jjj >> 1;
if (frac1 <= frac2) if (frac1 <= frac2)
{ {
frac1-= i; frac1-= iii;
frac2-=j-i; frac2-=jjj-iii;
} }
else else
{ {
frac2-= i; frac2-= iii;
frac1-=j-i; frac1-=jjj-iii;
} }
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment