Annotation of OpenXM_contrib/gmp/mpfr/set_z.c, Revision 1.1
1.1 ! maekawa 1: /* mpfr_set_z -- set a floating-point number from a multiple-precision integer
! 2:
! 3: Copyright (C) 1999 PolKA project, Inria Lorraine and Loria
! 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
! 8: it under the terms of the GNU Library General Public License as published by
! 9: the Free Software Foundation; either version 2 of the License, or (at your
! 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
! 14: or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
! 15: License for more details.
! 16:
! 17: You should have received a copy of the GNU Library General Public License
! 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"
! 26:
! 27: /* set f to the integer z */
! 28: int
! 29: #if __STDC__
! 30: mpfr_set_z (mpfr_ptr f, mpz_srcptr z, unsigned char rnd)
! 31: #else
! 32: mpfr_set_z (f, z, rnd)
! 33: mpfr_ptr f;
! 34: mpz_srcptr z;
! 35: unsigned char rnd;
! 36: #endif
! 37: {
! 38: int fn, zn, k, dif, sign_z, sh; mp_limb_t *fp = MANT(f), *zp, cc, c2;
! 39:
! 40: sign_z = mpz_cmp_ui(z,0);
! 41: if (sign_z==0) return (SIZE(f)=0);
! 42: fn = 1 + (PREC(f)-1)/BITS_PER_MP_LIMB;
! 43: zn = ABS(SIZ(z));
! 44: dif = zn-fn;
! 45: zp = PTR(z);
! 46: count_leading_zeros(k, zp[zn-1]);
! 47: EXP(f) = zn*BITS_PER_MP_LIMB-k;
! 48: if (SIGN(f)*sign_z<0) CHANGE_SIGN(f);
! 49: if (dif>=0) { /* number has to be truncated */
! 50: if (k) {
! 51: mpn_lshift(fp, zp + dif, fn, k);
! 52: if (dif) *fp += zp[dif-1] >> (BITS_PER_MP_LIMB-k);
! 53: }
! 54: else MPN_COPY(fp, zp + dif, fn);
! 55: sh = fn*BITS_PER_MP_LIMB-PREC(f);
! 56: cc = *fp & (((mp_limb_t)1 << sh) - 1);
! 57: *fp = *fp & ~cc;
! 58: if (rnd==GMP_RNDN) {
! 59: if (sh) c2 = (mp_limb_t)1 << (sh-1);
! 60: else { /* sh=0 */
! 61: c2 = ((mp_limb_t)1) << (BITS_PER_MP_LIMB-1);
! 62: dif--;
! 63: cc = (dif>=0) ? ((zp[dif])<<k) : 0;
! 64: if (dif>0 && k) cc += zp[dif-1] >> (BITS_PER_MP_LIMB-k);
! 65: }
! 66: /* now compares cc to c2 */
! 67: if (cc>c2) { mpfr_add_one_ulp(f); return cc; }
! 68: else if (cc<c2) goto towards_zero;
! 69: else {
! 70: cc=0;
! 71: while (dif>0 && (cc=zp[dif-1])==0) dif--;
! 72: if (cc) { mpfr_add_one_ulp(f); return cc; }
! 73: else /* exactly in middle: inexact in both cases */
! 74: if (*fp & ((mp_limb_t)1<<sh)) { mpfr_add_one_ulp(f); return 1; }
! 75: else return 1;
! 76: }
! 77: }
! 78: else if ((sign_z>0 && rnd==GMP_RNDU) || (sign_z<0 && rnd==GMP_RNDD)) {
! 79: /* round towards infinity */
! 80: /* result is exact iff all remaining bits are zero */
! 81: if (dif>0 && cc==0) cc=zp[--dif]<<k;
! 82: while (cc==0 && dif>0) cc=zp[--dif];
! 83: if (cc) { mpfr_add_one_ulp(f); return 1; }
! 84: else return 0;
! 85: }
! 86: else { /* round towards zero */
! 87: /* result is exact iff all remaining bits are zero */
! 88: towards_zero:
! 89: if (cc==0 && dif>0) cc=zp[--dif]<<k;
! 90: while (cc==0 && dif>0) cc=zp[--dif];
! 91: return cc;
! 92: }
! 93: }
! 94: else {
! 95: if (k) mpn_lshift(fp-dif, zp, zn, k);
! 96: else MPN_COPY(fp-dif, zp, zn);
! 97: /* fill with zeroes */
! 98: MPN_ZERO(fp, -dif);
! 99: return 0; /* result is exact */
! 100: }
! 101: }
! 102:
! 103:
! 104:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>