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

Annotation of OpenXM_contrib/gmp/mpfr/set_d.c, Revision 1.1

1.1     ! maekawa     1: /* mpfr_set_d, mpfr_get_d -- convert a multiple precision floating-point number
        !             2:                              from/to a machine double precision float
        !             3:
        !             4: Copyright (C) 1999 PolKA project, Inria Lorraine and Loria
        !             5:
        !             6: This file is part of the MPFR Library.
        !             7:
        !             8: The MPFR Library is free software; you can redistribute it and/or modify
        !             9: it under the terms of the GNU Library General Public License as published by
        !            10: the Free Software Foundation; either version 2 of the License, or (at your
        !            11: option) any later version.
        !            12:
        !            13: The MPFR Library is distributed in the hope that it will be useful, but
        !            14: WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
        !            15: or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
        !            16: License for more details.
        !            17:
        !            18: You should have received a copy of the GNU Library General Public License
        !            19: along with the MPFR Library; see the file COPYING.LIB.  If not, write to
        !            20: the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
        !            21: MA 02111-1307, USA. */
        !            22:
        !            23: #if __GNUC__ /* gcc "patched" headers seem to omit isnan... */
        !            24: extern int isnan(double);
        !            25: #endif
        !            26: #include <math.h> /* for isnan and NaN */
        !            27:
        !            28: #include "gmp.h"
        !            29: #include "gmp-impl.h"
        !            30: #include "longlong.h"
        !            31: #include "mpfr.h"
        !            32:
        !            33: #define NaN sqrt(-1) /* ensures a machine-independent NaN */
        !            34:
        !            35: /* Included from gmp-2.0.2, patched to support denorms */
        !            36:
        !            37: #ifdef XDEBUG
        !            38: #undef _GMP_IEEE_FLOATS
        !            39: #endif
        !            40:
        !            41: #ifndef _GMP_IEEE_FLOATS
        !            42: #define _GMP_IEEE_FLOATS 0
        !            43: #endif
        !            44:
        !            45: int
        !            46: #if __STDC__
        !            47: __mpfr_extract_double (mp_ptr rp, double d, int e)
        !            48: #else
        !            49: __mpfr_extract_double (rp, d, e)
        !            50:      mp_ptr rp;
        !            51:      double d;
        !            52:      int e;
        !            53: #endif
        !            54:      /* e=0 iff BITS_PER_MP_LIMB=32 and rp has only one limb */
        !            55: {
        !            56:   long exp;
        !            57:   mp_limb_t manl;
        !            58: #if BITS_PER_MP_LIMB == 32
        !            59:   mp_limb_t manh;
        !            60: #endif
        !            61:
        !            62:   /* BUGS
        !            63:
        !            64:      1. Should handle Inf and NaN in IEEE specific code.
        !            65:      2. Handle Inf and NaN also in default code, to avoid hangs.
        !            66:      3. Generalize to handle all BITS_PER_MP_LIMB >= 32.
        !            67:      4. This lits is incomplete and misspelled.
        !            68:    */
        !            69:
        !            70:   if (d == 0.0)
        !            71:     {
        !            72:       rp[0] = 0;
        !            73: #if BITS_PER_MP_LIMB == 32
        !            74:       if (e) rp[1] = 0;
        !            75: #endif
        !            76:       return 0;
        !            77:     }
        !            78:
        !            79: #if _GMP_IEEE_FLOATS
        !            80:   {
        !            81:     union ieee_double_extract x;
        !            82:     x.d = d;
        !            83:
        !            84:     exp = x.s.exp;
        !            85:     if (exp)
        !            86:       {
        !            87: #if BITS_PER_MP_LIMB == 64
        !            88:        manl = (((mp_limb_t) 1 << 63)
        !            89:                | ((mp_limb_t) x.s.manh << 43) | ((mp_limb_t) x.s.manl << 11));
        !            90: #else
        !            91:        manh = ((mp_limb_t) 1 << 31) | (x.s.manh << 11) | (x.s.manl >> 21);
        !            92:        manl = x.s.manl << 11;
        !            93: #endif
        !            94:       }
        !            95:     else
        !            96:       {
        !            97: #if BITS_PER_MP_LIMB == 64
        !            98:        manl = ((mp_limb_t) x.s.manh << 43) | ((mp_limb_t) x.s.manl << 11);
        !            99: #else
        !           100:     manh = (x.s.manh << 11) | (x.s.manl >> 21);
        !           101:        manl = x.s.manl << 11;
        !           102: #endif
        !           103:       }
        !           104:   }
        !           105: #else
        !           106:   {
        !           107:     /* Unknown (or known to be non-IEEE) double format.  */
        !           108:     exp = 0;
        !           109:     if (d >= 1.0)
        !           110:       {
        !           111:         if (d * 0.5 == d)
        !           112:           abort ();
        !           113:
        !           114:         while (d >= 32768.0)
        !           115:           {
        !           116:             d *= (1.0 / 65536.0);
        !           117:             exp += 16;
        !           118:           }
        !           119:         while (d >= 1.0)
        !           120:           {
        !           121:             d *= 0.5;
        !           122:             exp += 1;
        !           123:           }
        !           124:       }
        !           125:     else if (d < 0.5)
        !           126:       {
        !           127:         while (d < (1.0 / 65536.0))
        !           128:           {
        !           129:             d *=  65536.0;
        !           130:             exp -= 16;
        !           131:           }
        !           132:         while (d < 0.5)
        !           133:           {
        !           134:             d *= 2.0;
        !           135:             exp -= 1;
        !           136:           }
        !           137:       }
        !           138:
        !           139:     d *= MP_BASE_AS_DOUBLE;
        !           140: #if BITS_PER_MP_LIMB == 64
        !           141:     manl = d;
        !           142: #else
        !           143:     manh = d;
        !           144:     manl = (d - manh) * MP_BASE_AS_DOUBLE;
        !           145: #endif
        !           146:
        !           147:     exp += 1022;
        !           148:   }
        !           149: #endif
        !           150:
        !           151:   if (exp) exp = (unsigned) exp - 1022; else exp = -1021;
        !           152:
        !           153: #if BITS_PER_MP_LIMB == 64
        !           154:       rp[0] = manl;
        !           155: #else
        !           156:       if (e) {
        !           157:        rp[1] = manh;
        !           158:        rp[0] = manl;
        !           159:       }
        !           160:       else {
        !           161:        rp[0] = manh;
        !           162:       }
        !           163: #endif
        !           164:
        !           165:   return exp;
        !           166: }
        !           167:
        !           168: /* End of part included from gmp-2.0.2 */
        !           169: /* Part included from gmp temporary releases */
        !           170: double
        !           171: #if __STDC__
        !           172: __mpfr_scale2 (double d, int exp)
        !           173: #else
        !           174: __mpfr_scale2 (d, exp)
        !           175:      double d;
        !           176:      int exp;
        !           177: #endif
        !           178: {
        !           179: #if _GMP_IEEE_FLOATS
        !           180:   {
        !           181:     union ieee_double_extract x;
        !           182:     x.d = d;
        !           183:     exp += x.s.exp;
        !           184:     x.s.exp = exp;
        !           185:     if (exp >= 2047)
        !           186:       {
        !           187:         /* Return +-infinity */
        !           188:         x.s.exp = 2047;
        !           189:         x.s.manl = x.s.manh = 0;
        !           190:       }
        !           191:     else if (exp < 1)
        !           192:       {
        !           193:         x.s.exp = 1;            /* smallest exponent (biased) */
        !           194:         /* Divide result by 2 until we have scaled it to the right IEEE
        !           195:            denormalized number, but stop if it becomes zero.  */
        !           196:         while (exp < 1 && x.d != 0)
        !           197:           {
        !           198:             x.d *= 0.5;
        !           199:             exp++;
        !           200:           }
        !           201:       }
        !           202:     return x.d;
        !           203:   }
        !           204: #else
        !           205:   {
        !           206:     double factor, r;
        !           207:
        !           208:     factor = 2.0;
        !           209:     if (exp < 0)
        !           210:       {
        !           211:         factor = 0.5;
        !           212:         exp = -exp;
        !           213:       }
        !           214:     r = d;
        !           215:     if (exp != 0)
        !           216:       {
        !           217:         if ((exp & 1) != 0)
        !           218:           r *= factor;
        !           219:         exp >>= 1;
        !           220:         while (exp != 0)
        !           221:           {
        !           222:             factor *= factor;
        !           223:             if ((exp & 1) != 0)
        !           224:               r *= factor;
        !           225:             exp >>= 1;
        !           226:           }
        !           227:       }
        !           228:     return r;
        !           229:   }
        !           230: #endif
        !           231: }
        !           232:
        !           233:
        !           234: /* End of part included from gmp */
        !           235:
        !           236: void
        !           237: #if __STDC__
        !           238: mpfr_set_d(mpfr_t r, double d, unsigned char rnd_mode)
        !           239: #else
        !           240: mpfr_set_d(r, d, rnd_mode)
        !           241:      mpfr_t r;
        !           242:      double d;
        !           243:      unsigned char rnd_mode;
        !           244: #endif
        !           245: {
        !           246:   int signd, sizer; unsigned int cnt;
        !           247:
        !           248:   if (d == 0) { SET_ZERO(r); return; }
        !           249:   else if (isnan(d)) { SET_NAN(r); return; }
        !           250:
        !           251:   signd = (d < 0) ? -1 : 1;
        !           252:   d = ABS (d);
        !           253:   sizer = (PREC(r)-1)/BITS_PER_MP_LIMB + 1;
        !           254:
        !           255:   /* warning: __mpfr_extract_double requires at least two limbs */
        !           256:   if (sizer < MPFR_LIMBS_PER_DOUBLE)
        !           257:     EXP(r) = __mpfr_extract_double (MANT(r), d, 0);
        !           258:   else
        !           259:     EXP(r) = __mpfr_extract_double (MANT(r) + sizer - MPFR_LIMBS_PER_DOUBLE, d, 1);
        !           260:
        !           261:   if (sizer > MPFR_LIMBS_PER_DOUBLE)
        !           262:     MPN_ZERO(MANT(r), sizer - MPFR_LIMBS_PER_DOUBLE);
        !           263:
        !           264:   count_leading_zeros(cnt, MANT(r)[sizer-1]);
        !           265:   if (cnt) mpn_lshift(MANT(r), MANT(r), sizer, cnt);
        !           266:
        !           267:   EXP(r) -= cnt;
        !           268:   if (SIZE(r)*signd<0) CHANGE_SIGN(r);
        !           269:
        !           270:   mpfr_round(r, rnd_mode, PREC(r));
        !           271:   return;
        !           272: }
        !           273:
        !           274: double
        !           275: #if __STDC__
        !           276: mpfr_get_d2(mpfr_srcptr src, long e)
        !           277: #else
        !           278: mpfr_get_d2(src, e)
        !           279:      mpfr_srcptr(src);
        !           280:      long e;
        !           281: #endif
        !           282: {
        !           283:   double res;
        !           284:   mp_size_t size, i, n_limbs_to_use;
        !           285:   mp_ptr qp;
        !           286:   int negative;
        !           287:
        !           288:   if (FLAG_NAN(src)) {
        !           289: #ifdef DEBUG
        !           290:     printf("recognized NaN\n");
        !           291: #endif
        !           292:     return NaN; }
        !           293:   if (NOTZERO(src)==0) return 0.0;
        !           294:   size = 1+(PREC(src)-1)/BITS_PER_MP_LIMB;
        !           295:   qp = MANT(src);
        !           296:   negative = (SIGN(src)==-1);
        !           297:
        !           298:   /* Warning: don't compute the abs(res) and set the sign afterwards,
        !           299:      otherwise the current machine rounding mode will not be taken
        !           300:      correctly into account. */
        !           301:   /* res = (negative) ? -(double)qp[size - 1] : qp[size - 1]; */
        !           302:   res = 0.0;
        !           303:   /* Warning: an arbitrary number of limbs may be required for an exact
        !           304:      rounding. The following code is correct but not optimal since one
        !           305:      may be able to decide without considering all limbs. */
        !           306:   /* n_limbs_to_use = MIN (MPFR_LIMBS_PER_DOUBLE, size); */
        !           307:   n_limbs_to_use = size;
        !           308:   /* Accumulate the limbs from less significant to most significant
        !           309:      otherwise due to rounding we may accumulate several ulps,
        !           310:      especially in rounding towards -/+infinity. */
        !           311:   for (i = n_limbs_to_use; i>=1; i--)
        !           312:     res = res / MP_BASE_AS_DOUBLE +
        !           313:       ((negative) ? -(double)qp[size - i] : qp[size - i]);
        !           314:   res = __mpfr_scale2 (res, e - BITS_PER_MP_LIMB);
        !           315:
        !           316:   return res;
        !           317: }
        !           318:
        !           319: double
        !           320: #if __STDC__
        !           321: mpfr_get_d(mpfr_srcptr src)
        !           322: #else
        !           323: mpfr_get_d(src)
        !           324:      mpfr_srcptr src;
        !           325: #endif
        !           326: {
        !           327:   return mpfr_get_d2(src, EXP(src));
        !           328: }
        !           329:

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>