summaryrefslogtreecommitdiff
path: root/mpfr/mul_ui.c
diff options
context:
space:
mode:
authorKevin Ryde <user42@zip.com.au>2001-02-01 23:29:23 +0100
committerKevin Ryde <user42@zip.com.au>2001-02-01 23:29:23 +0100
commit618be102b4c29f1e02e4a7d2244ae57b4bb544c9 (patch)
tree23f14ffeb18a23ed1c61258a65130fd2321bec75 /mpfr/mul_ui.c
parenteca14f894e34ab2d288357712157d6f942ced7fa (diff)
downloadgmp-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.c92
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);
}