[BACK]Return to set_z.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib / gmp / mpfr

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>