diff options
author | hanrot <hanrot@280ebfd0-de03-0410-8827-d642c229c3f4> | 2000-04-13 16:49:33 +0000 |
---|---|---|
committer | hanrot <hanrot@280ebfd0-de03-0410-8827-d642c229c3f4> | 2000-04-13 16:49:33 +0000 |
commit | 44920050b3ac4293695dc97f8bd97431a78c9c10 (patch) | |
tree | 0b7e80429885cee8fdc9a626fcd428dd3d73be66 /mul_ui.c | |
parent | c364a1bc349d3c83c54260f96bdfc1713c17326d (diff) | |
download | mpfr-44920050b3ac4293695dc97f8bd97431a78c9c10.tar.gz |
Correction d'un bug quand le carry contient tous les bits significatifs.
git-svn-id: svn://scm.gforge.inria.fr/svn/mpfr/trunk@481 280ebfd0-de03-0410-8827-d642c229c3f4
Diffstat (limited to 'mul_ui.c')
-rw-r--r-- | mul_ui.c | 41 |
1 files changed, 32 insertions, 9 deletions
@@ -36,17 +36,18 @@ mpfr_mul_ui(y, x, u, rnd_mode) mp_rnd_t rnd_mode; #endif { - mp_limb_t carry, *my, *old_my; unsigned long c; - unsigned long xsize, ysize, cnt, dif; + mp_limb_t carry, *my, *old_my, *my2; unsigned long c; + unsigned long xsize, ysize, cnt, dif, ex; TMP_DECL(marker); TMP_MARK(marker); - my = MANT(y); + my = MANT(y); ex = EXP(x); ysize = (PREC(y)-1)/BITS_PER_MP_LIMB + 1; xsize = (PREC(x)-1)/BITS_PER_MP_LIMB + 1; + old_my = my; + if (ysize < xsize) { - old_my = my; my = (mp_ptr) TMP_ALLOC (xsize * BYTES_PER_MP_LIMB); dif=0; } @@ -58,10 +59,32 @@ mpfr_mul_ui(y, x, u, rnd_mode) /* WARNING: count_leading_zeros is undefined for carry=0 */ if (carry) count_leading_zeros(cnt, carry); else cnt=BITS_PER_MP_LIMB; - - c = mpfr_round_raw(my, my, PREC(x), (MPFR_SIGN(x)<0), - PREC(y)-BITS_PER_MP_LIMB+cnt, rnd_mode); - + + /* Warning: if all significant bits are in the carry, one has to + be careful */ + + if (cnt + PREC(y) < BITS_PER_MP_LIMB) + { + /* Quick 'n dirty */ + + if (xsize > ysize) { + my2 = (mp_ptr) TMP_ALLOC ((xsize + 1) * BYTES_PER_MP_LIMB); + my2[xsize] = mpn_lshift(my2, my, xsize, cnt) + | (carry << (BITS_PER_MP_LIMB - cnt)); + } + else { + my2 = (mp_ptr) TMP_ALLOC ((ysize + 1) * BYTES_PER_MP_LIMB); + my2[ysize] = mpn_lshift(my2, my, ysize, cnt) + | (carry << (BITS_PER_MP_LIMB - cnt)); + } + + my = my2; ex += BITS_PER_MP_LIMB - cnt; + carry = 0; cnt = BITS_PER_MP_LIMB; + } + + c = mpfr_round_raw(my, my, PREC(x), (MPFR_SIGN(x)<0), + PREC(y)-BITS_PER_MP_LIMB+cnt, rnd_mode); + /* If cnt = 1111111111111 and c = 1 we shall get depressed */ if (c && (carry == (((mp_limb_t)1) << (BITS_PER_MP_LIMB - cnt)) - 1)) { @@ -76,7 +99,7 @@ mpfr_mul_ui(y, x, u, rnd_mode) mpn_rshift(my, my, ysize, BITS_PER_MP_LIMB - cnt); my[ysize - 1] |= (carry << cnt); } - EXP(y) = EXP(x) + BITS_PER_MP_LIMB - cnt; + EXP(y) = ex + BITS_PER_MP_LIMB - cnt; if (ysize < xsize) MPN_COPY(old_my, my, ysize); /* set sign */ if (MPFR_SIGN(y) * MPFR_SIGN(x) < 0) CHANGE_SIGN(y); |