diff options
author | Kevin Ryde <user42@zip.com.au> | 2001-02-01 23:29:23 +0100 |
---|---|---|
committer | Kevin Ryde <user42@zip.com.au> | 2001-02-01 23:29:23 +0100 |
commit | 618be102b4c29f1e02e4a7d2244ae57b4bb544c9 (patch) | |
tree | 23f14ffeb18a23ed1c61258a65130fd2321bec75 /mpfr/mul_ui.c | |
parent | eca14f894e34ab2d288357712157d6f942ced7fa (diff) | |
download | gmp-618be102b4c29f1e02e4a7d2244ae57b4bb544c9.tar.gz |
* mpfr/*: Update to mpfr 2001.
Tweaks applied to mpfr-impl.h for __gmp_allocate_func renaming, and to trunc.c
for OPERATION_$* scheme.
Diffstat (limited to 'mpfr/mul_ui.c')
-rw-r--r-- | mpfr/mul_ui.c | 92 |
1 files changed, 71 insertions, 21 deletions
diff --git a/mpfr/mul_ui.c b/mpfr/mul_ui.c index 83981a83c..e92a79155 100644 --- a/mpfr/mul_ui.c +++ b/mpfr/mul_ui.c @@ -1,6 +1,6 @@ /* mpfr_mul_ui -- multiply a floating-point number by a machine integer -Copyright (C) 1999 PolKA project, Inria Lorraine and Loria +Copyright (C) 1999 Free Software Foundation. This file is part of the MPFR Library. @@ -24,46 +24,96 @@ MA 02111-1307, USA. */ #include "gmp-impl.h" #include "longlong.h" #include "mpfr.h" +#include "mpfr-impl.h" void #if __STDC__ -mpfr_mul_ui(mpfr_ptr y, mpfr_srcptr x, unsigned long u, unsigned char RND_MODE) +mpfr_mul_ui(mpfr_ptr y, mpfr_srcptr x, unsigned long int u, mp_rnd_t rnd_mode) #else -mpfr_mul_ui(y, x, u, RND_MODE) - mpfr_ptr y; - mpfr_srcptr x; - unsigned long u; - unsigned char RND_MODE; +mpfr_mul_ui(y, x, u, rnd_mode) + mpfr_ptr y; + mpfr_srcptr x; + unsigned long int u; + 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, sh; TMP_DECL(marker); + if (MPFR_IS_NAN(x)) + { + MPFR_CLEAR_FLAGS(y); + MPFR_SET_NAN(y); + return; + } + + if (MPFR_IS_INF(x)) + { + MPFR_CLEAR_FLAGS(y); + if (u) + { + MPFR_SET_INF(y); + if (MPFR_SIGN(y) != MPFR_SIGN(x)) { MPFR_CHANGE_SIGN(y); } + return; + } + else { MPFR_SET_NAN(y); return; } + } + + MPFR_CLEAR_FLAGS(y); + TMP_MARK(marker); - my = MANT(y); - ysize = (PREC(y)-1)/BITS_PER_MP_LIMB + 1; - xsize = (PREC(x)-1)/BITS_PER_MP_LIMB + 1; + my = MPFR_MANT(y); ex = MPFR_EXP(x); + ysize = (MPFR_PREC(y)-1)/BITS_PER_MP_LIMB + 1; + xsize = (MPFR_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; } else dif=ysize-xsize; - carry = mpn_mul_1(my+dif, MANT(x), xsize, u); + carry = mpn_mul_1(my+dif, MPFR_MANT(x), xsize, u); MPN_ZERO(my, dif); /* 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), (SIGN(x)<0), - PREC(y)-BITS_PER_MP_LIMB+cnt, RND_MODE); - + + /* Warning: the number of limbs used by x and the lower part + of y may differ */ + sh = (MPFR_PREC(x)+BITS_PER_MP_LIMB-1)/BITS_PER_MP_LIMB + - (MPFR_PREC(y)+cnt-1)/BITS_PER_MP_LIMB; + + /* Warning: if all significant bits are in the carry, one has to + be careful */ + if (cnt + MPFR_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 << (cnt ? BITS_PER_MP_LIMB - cnt : 0)); + } + else { + my2 = (mp_ptr) TMP_ALLOC ((ysize + 1) * BYTES_PER_MP_LIMB); + my2[ysize] = mpn_lshift(my2, my, ysize, cnt) + | (carry << (cnt ? BITS_PER_MP_LIMB - cnt : 0)); + } + + my = my2; ex += BITS_PER_MP_LIMB - cnt; + carry = 0; cnt = BITS_PER_MP_LIMB; + } + + c = mpfr_round_raw(my+sh, my, MPFR_PREC(x), (MPFR_SIGN(x)<0), + MPFR_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)) + if (c && (carry == (((mp_limb_t)1) << (cnt ? BITS_PER_MP_LIMB - cnt : 0)) + - 1)) { cnt--; mpn_rshift(my, my, ysize, BITS_PER_MP_LIMB - cnt); @@ -76,9 +126,9 @@ 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; + MPFR_EXP(y) = ex + BITS_PER_MP_LIMB - cnt; if (ysize < xsize) MPN_COPY(old_my, my, ysize); /* set sign */ - if (SIGN(y) != SIGN(x)) CHANGE_SIGN(y); + if (MPFR_SIGN(y) * MPFR_SIGN(x) < 0) MPFR_CHANGE_SIGN(y); TMP_FREE(marker); } |