Annotation of OpenXM_contrib/gmp/mpfr/set_z.c, Revision 1.1.1.2
1.1 maekawa 1: /* mpfr_set_z -- set a floating-point number from a multiple-precision integer
2:
1.1.1.2 ! ohara 3: Copyright 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
1.1 maekawa 4:
5: This file is part of the MPFR Library.
6:
7: The MPFR Library is free software; you can redistribute it and/or modify
1.1.1.2 ! ohara 8: it under the terms of the GNU Lesser General Public License as published by
! 9: the Free Software Foundation; either version 2.1 of the License, or (at your
1.1 maekawa 10: option) any later version.
11:
12: The MPFR Library is distributed in the hope that it will be useful, but
13: WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
1.1.1.2 ! ohara 14: or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
1.1 maekawa 15: License for more details.
16:
1.1.1.2 ! ohara 17: You should have received a copy of the GNU Lesser General Public License
1.1 maekawa 18: along with the MPFR Library; see the file COPYING.LIB. If not, write to
19: the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
20: MA 02111-1307, USA. */
21:
22: #include "gmp.h"
23: #include "gmp-impl.h"
24: #include "longlong.h"
25: #include "mpfr.h"
1.1.1.2 ! ohara 26: #include "mpfr-impl.h"
1.1 maekawa 27:
28: /* set f to the integer z */
29: int
1.1.1.2 ! ohara 30: mpfr_set_z (mpfr_ptr f, mpz_srcptr z, mp_rnd_t rnd_mode)
1.1 maekawa 31: {
1.1.1.2 ! ohara 32: mp_size_t fn, zn, dif;
! 33: int k, sign_z, inex;
! 34: mp_limb_t *fp, *zp;
! 35: mp_exp_t exp;
! 36:
! 37: MPFR_CLEAR_FLAGS (f); /* z cannot be NaN nor Inf */
! 38:
! 39: sign_z = mpz_cmp_ui (z, 0);
! 40:
! 41: if (sign_z == 0)
! 42: {
! 43: MPFR_SET_ZERO(f);
! 44: MPFR_SET_POS(f);
! 45: MPFR_RET(0);
! 46: }
1.1 maekawa 47:
1.1.1.2 ! ohara 48: fp = MPFR_MANT(f);
! 49: fn = 1 + (MPFR_PREC(f) - 1) / BITS_PER_MP_LIMB;
1.1 maekawa 50: zn = ABS(SIZ(z));
1.1.1.2 ! ohara 51: dif = zn - fn;
1.1 maekawa 52: zp = PTR(z);
53: count_leading_zeros(k, zp[zn-1]);
54:
1.1.1.2 ! ohara 55: exp = (mp_prec_t) zn * BITS_PER_MP_LIMB - k;
! 56: /* The exponent will be exp or exp + 1 (due to rounding) */
! 57: if (exp > __mpfr_emax)
! 58: return mpfr_set_overflow(f, rnd_mode, sign_z);
! 59: if (exp + 1 < __mpfr_emin)
! 60: return mpfr_set_underflow(f, rnd_mode, sign_z);
! 61:
! 62: if (MPFR_SIGN(f) * sign_z < 0)
! 63: MPFR_CHANGE_SIGN(f);
! 64:
! 65: if (dif >= 0)
! 66: {
! 67: mp_limb_t cc;
! 68: int sh;
! 69:
! 70: /* number has to be truncated */
! 71: if (k != 0)
! 72: {
! 73: mpn_lshift(fp, zp + dif, fn, k);
! 74: if (dif != 0)
! 75: fp[0] += zp[dif - 1] >> (BITS_PER_MP_LIMB - k);
! 76: }
! 77: else
! 78: MPN_COPY(fp, zp + dif, fn);
! 79:
! 80: sh = (mp_prec_t) fn * BITS_PER_MP_LIMB - MPFR_PREC(f);
! 81: cc = fp[0] & ((MP_LIMB_T_ONE << sh) - 1);
! 82: fp[0] &= ~cc;
! 83:
! 84: if ((rnd_mode == GMP_RNDU && sign_z < 0) ||
! 85: (rnd_mode == GMP_RNDD && sign_z > 0))
! 86: rnd_mode = GMP_RNDZ;
! 87:
! 88: /* remaining bits... */
! 89: if (rnd_mode == GMP_RNDN)
! 90: {
! 91: /* 1) If rounding bit is 0, behave like rounding to 0.
! 92: 2) Determine the sticky bit (cc != 0). */
! 93: if (sh != 0)
! 94: {
! 95: mp_limb_t rb;
! 96:
! 97: rb = MP_LIMB_T_ONE << (sh - 1);
! 98: if ((cc & rb) == 0)
! 99: rnd_mode = GMP_RNDZ; /* rounding bit is 0 */
! 100: else
! 101: cc &= ~rb;
! 102: if (cc == 0 && dif > 0)
! 103: cc = zp[--dif] << k;
! 104: }
! 105: else /* sh == 0 */
! 106: {
! 107: MPFR_ASSERTN(cc == 0);
! 108: if (dif > 0)
! 109: cc = zp[--dif] << k;
! 110: if ((cc & GMP_LIMB_HIGHBIT) == 0)
! 111: rnd_mode = GMP_RNDZ; /* rounding bit is 0 */
! 112: else
! 113: cc <<= 1;
! 114: }
! 115:
! 116: while (cc == 0 && dif > 0)
! 117: cc = zp[--dif];
! 118:
! 119: if (rnd_mode == GMP_RNDN && cc == 0) /* even rounding */
! 120: {
! 121: cc = 1;
! 122: if ((fp[0] & (MP_LIMB_T_ONE << sh)) == 0)
! 123: rnd_mode = GMP_RNDZ;
! 124: }
! 125: } /* rnd_mode == GMP_RNDN */
! 126: else if (cc == 0 && dif > 0)
! 127: {
! 128: cc = zp[--dif] << k;
! 129: while (cc == 0 && dif > 0)
! 130: cc = zp[--dif];
! 131: }
! 132:
! 133: if (cc == 0)
! 134: inex = 0;
! 135: else if (rnd_mode == GMP_RNDZ)
! 136: inex = -sign_z;
! 137: else
! 138: {
! 139: if (mpn_add_1(fp, fp, fn, MP_LIMB_T_ONE << sh))
! 140: {
! 141: if (exp == __mpfr_emax)
! 142: return mpfr_set_overflow(f, rnd_mode, sign_z);
! 143: else
! 144: {
! 145: exp++;
! 146: fp[fn-1] = GMP_LIMB_HIGHBIT;
! 147: }
! 148: }
! 149: inex = sign_z;
! 150: }
! 151: } /* dif >= 0 */
! 152: else /* dif < 0 */
! 153: {
! 154: if (k != 0)
! 155: mpn_lshift(fp - dif, zp, zn, k);
! 156: else
! 157: MPN_COPY(fp - dif, zp, zn);
! 158: /* fill with zeroes */
! 159: MPN_ZERO(fp, -dif);
! 160: inex = 0; /* result is exact */
! 161: }
1.1 maekawa 162:
1.1.1.2 ! ohara 163: if (exp < __mpfr_emin)
! 164: return mpfr_set_underflow(f, rnd_mode, sign_z);
! 165: MPFR_EXP(f) = exp;
! 166: MPFR_RET(inex);
! 167: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>