summaryrefslogtreecommitdiff
path: root/set_f.c
diff options
context:
space:
mode:
authorzimmerma <zimmerma@280ebfd0-de03-0410-8827-d642c229c3f4>2004-02-17 10:02:29 +0000
committerzimmerma <zimmerma@280ebfd0-de03-0410-8827-d642c229c3f4>2004-02-17 10:02:29 +0000
commita7604a09377bba7969c7dc861aee4d3008d77207 (patch)
tree9f98eb1967bbe910eb30f0552b468e64349571ab /set_f.c
parenta670e9bc4c691d692b4c967758d1caa130d043ff (diff)
downloadmpfr-a7604a09377bba7969c7dc861aee4d3008d77207.tar.gz
fixed 2 bugs and added test
git-svn-id: svn://scm.gforge.inria.fr/svn/mpfr/trunk@2743 280ebfd0-de03-0410-8827-d642c229c3f4
Diffstat (limited to 'set_f.c')
-rw-r--r--set_f.c26
1 files changed, 15 insertions, 11 deletions
diff --git a/set_f.c b/set_f.c
index 2525758e5..a08f89072 100644
--- a/set_f.c
+++ b/set_f.c
@@ -28,10 +28,10 @@ mpfr_set_f (mpfr_ptr y, mpf_srcptr x, mp_rnd_t rnd_mode)
{
mp_limb_t *my, *mx, *tmp;
unsigned long cnt, sx, sy;
- int inexact;
+ int inexact, carry = 0;
TMP_DECL(marker);
- if (SIZ(x) * MPFR_SIGN(y) < 0)
+ if (SIZ(x) * MPFR_FROM_SIGN_TO_INT(MPFR_SIGN(y)) < 0)
MPFR_CHANGE_SIGN (y);
MPFR_CLEAR_FLAGS (y);
@@ -46,7 +46,7 @@ mpfr_set_f (mpfr_ptr y, mpf_srcptr x, mp_rnd_t rnd_mode)
MPFR_SET_ZERO(y);
return 0; /* 0 is exact */
}
-
+
count_leading_zeros(cnt, mx[sx - 1]);
if (sy <= sx) /* we may have to round even when sy = sx */
@@ -54,27 +54,31 @@ mpfr_set_f (mpfr_ptr y, mpf_srcptr x, mp_rnd_t rnd_mode)
unsigned long xprec = sx * BITS_PER_MP_LIMB;
TMP_MARK(marker);
- tmp = (mp_limb_t*) TMP_ALLOC(xprec);
+ tmp = (mp_limb_t*) TMP_ALLOC(sx * BYTES_PER_MP_LIMB);
if (cnt)
- mpn_lshift(tmp, mx, sx, cnt);
+ mpn_lshift (tmp, mx, sx, cnt);
else
- MPN_COPY(tmp, mx, sx);
- mpfr_round_raw (my, tmp, xprec, (SIZ(x)<0), MPFR_PREC(y), rnd_mode,
- &inexact);
+ /* FIXME: we may avoid the copy here, and directly call mpfr_round_raw
+ on mx instead of tmp */
+ MPN_COPY (tmp, mx, sx);
+ carry = mpfr_round_raw (my, tmp, xprec, (SIZ(x) < 0), MPFR_PREC(y),
+ rnd_mode, &inexact);
+ if (MPFR_UNLIKELY(carry)) /* result is a power of two */
+ my[sy - 1] = MPFR_LIMB_HIGHBIT;
TMP_FREE(marker);
}
else
{
if (cnt)
- mpn_lshift(my + sy - sx, mx, sx, cnt);
+ mpn_lshift (my + sy - sx, mx, sx, cnt);
else
- MPN_COPY(my + sy - sx, mx, sy);
+ MPN_COPY (my + sy - sx, mx, sx);
MPN_ZERO(my, sy - sx);
/* no rounding necessary, since y has a larger mantissa */
inexact = 0;
}
- MPFR_SET_EXP(y, EXP(x) * BITS_PER_MP_LIMB - cnt);
+ MPFR_SET_EXP(y, EXP(x) * BITS_PER_MP_LIMB - cnt + carry);
return inexact;
}