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

Annotation of OpenXM_contrib/gmp/mpfr/get_d.c, Revision 1.1.1.1

1.1       ohara       1: /* mpfr_get_d -- convert a multiple precision floating-point number
                      2:                  to a machine double precision float
                      3:
                      4: Copyright 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
                      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 Lesser General Public License as published by
                     10: the Free Software Foundation; either version 2.1 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 Lesser General Public
                     16: License for more details.
                     17:
                     18: You should have received a copy of the GNU Lesser 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: #include <float.h>
                     24: #ifndef NO_MATH_DEFS
                     25: #include <math.h>
                     26: #endif
                     27: #include "gmp.h"
                     28: #include "gmp-impl.h"
                     29: #include "longlong.h"
                     30: #include "mpfr.h"
                     31: #include "mpfr-impl.h"
                     32: #include "mpfr-math.h"
                     33:
                     34: static double mpfr_scale2 _PROTO ((double, int));
                     35:
                     36: #define IEEE_DBL_MANT_DIG 53
                     37:
                     38: /* multiplies 1/2 <= d <= 1 by 2^exp */
                     39: static double
                     40: mpfr_scale2 (double d, int exp)
                     41: {
                     42: #if _GMP_IEEE_FLOATS
                     43:   {
                     44:     union ieee_double_extract x;
                     45:
                     46:     if (d == 1.0)
                     47:       {
                     48:         d = 0.5;
                     49:         exp ++;
                     50:       }
                     51:
                     52:     /* now 1/2 <= d < 1 */
                     53:
                     54:     /* infinities and zeroes have already been checked */
                     55:     MPFR_ASSERTN(-1073 <= exp && exp <= 1025);
                     56:
                     57:     x.d = d;
                     58:     if (exp < -1021) /* subnormal case */
                     59:       {
                     60:         x.s.exp += exp + 52;
                     61:         x.d *= DBL_EPSILON;
                     62:       }
                     63:     else /* normalized case */
                     64:       {
                     65:         x.s.exp += exp;
                     66:       }
                     67:     return x.d;
                     68:   }
                     69: #else
                     70:   {
                     71:     double factor;
                     72:
                     73:     if (exp < 0)
                     74:       {
                     75:         factor = 0.5;
                     76:         exp = -exp;
                     77:       }
                     78:     else
                     79:       {
                     80:         factor = 2.0;
                     81:       }
                     82:     while (exp != 0)
                     83:       {
                     84:         if ((exp & 1) != 0)
                     85:           d *= factor;
                     86:         exp >>= 1;
                     87:         factor *= factor;
                     88:       }
                     89:     return d;
                     90:   }
                     91: #endif
                     92: }
                     93:
                     94: /* Assumes IEEE-754 double precision; otherwise, only an approximated
                     95:    result will be returned, without any guaranty (and special cases
                     96:    such as NaN must be avoided if not supported). */
                     97:
                     98: double
                     99: mpfr_get_d3 (mpfr_srcptr src, mp_exp_t e, mp_rnd_t rnd_mode)
                    100: {
                    101:   double d;
                    102:   int negative;
                    103:
                    104:   if (MPFR_IS_NAN(src))
                    105:     return MPFR_DBL_NAN;
                    106:
                    107:   negative = MPFR_SIGN(src) < 0;
                    108:
                    109:   if (MPFR_IS_INF(src))
                    110:     return negative ? MPFR_DBL_INFM : MPFR_DBL_INFP;
                    111:
                    112:   if (MPFR_IS_ZERO(src))
                    113:     return negative ? -0.0 : 0.0;
                    114:
                    115:   /* the smallest normalized number is 2^(-1022)=0.1e-1021, and the smallest
                    116:      subnormal is 2^(-1074)=0.1e-1073 */
                    117:   if (e < -1073)
                    118:     {
                    119:       d = negative ?
                    120:         (rnd_mode == GMP_RNDD ||
                    121:          (rnd_mode == GMP_RNDN && mpfr_cmp_si_2exp(src, -1, -1075) < 0)
                    122:          ? -DBL_MIN : -0.0) :
                    123:         (rnd_mode == GMP_RNDU ||
                    124:          (rnd_mode == GMP_RNDN && mpfr_cmp_si_2exp(src, 1, -1075) > 0)
                    125:          ? DBL_MIN : 0.0);
                    126:       if (d != 0.0)
                    127:         d *= DBL_EPSILON;
                    128:     }
                    129:   /* the largest normalized number is 2^1024*(1-2^(-53))=0.111...111e1024 */
                    130:   else if (e > 1024)
                    131:     {
                    132:       d = negative ?
                    133:         (rnd_mode == GMP_RNDZ || rnd_mode == GMP_RNDU ?
                    134:          -DBL_MAX : MPFR_DBL_INFM) :
                    135:         (rnd_mode == GMP_RNDZ || rnd_mode == GMP_RNDD ?
                    136:          DBL_MAX : MPFR_DBL_INFP);
                    137:     }
                    138:   else
                    139:     {
                    140:       int nbits;
                    141:       mp_size_t np, i;
                    142:       mp_ptr tp;
                    143:       int carry;
                    144:
                    145:       nbits = IEEE_DBL_MANT_DIG; /* 53 */
                    146:       if (e < -1021) /* in the subnormal case, compute the exact number of
                    147:                         significant bits */
                    148:         {
                    149:           nbits += (1021 + e);
                    150:           MPFR_ASSERTN(nbits >= 1);
                    151:         }
                    152:       np = (nbits - 1) / BITS_PER_MP_LIMB;
                    153:       tp = (mp_ptr) (*__gmp_allocate_func) ((np + 1) * BYTES_PER_MP_LIMB);
                    154:       carry = mpfr_round_raw (tp, MPFR_MANT(src), MPFR_PREC(src), negative,
                    155:                              nbits, rnd_mode, (int *) 0);
                    156:       if (carry)
                    157:         d = 1.0;
                    158:       else
                    159:         {
                    160:           /* Warning: the rounding may still be incorrect in the rounding
                    161:              to the nearest mode when the result is a subnormal because of
                    162:              a double rounding (-> 53 bits -> final precision). */
                    163:           d = (double) tp[0] / MP_BASE_AS_DOUBLE;
                    164:           for (i = 1; i <= np; i++)
                    165:             d = (d + tp[i]) / MP_BASE_AS_DOUBLE;
                    166:           /* d is the mantissa (between 1/2 and 1) of the argument rounded
                    167:              to 53 bits */
                    168:         }
                    169:       d = mpfr_scale2 (d, e);
                    170:       if (negative)
                    171:         d = -d;
                    172:
                    173:       (*__gmp_free_func) (tp, (np + 1) * BYTES_PER_MP_LIMB);
                    174:     }
                    175:
                    176:   return d;
                    177: }
                    178:
                    179: /* Note: do not read the exponent if it has no meaning (avoid possible
                    180:    traps on some implementations). */
                    181:
                    182: double
                    183: mpfr_get_d (mpfr_srcptr src, mp_rnd_t rnd_mode)
                    184: {
                    185:   return mpfr_get_d3 (src, MPFR_IS_FP(src) && MPFR_NOTZERO(src) ?
                    186:                       MPFR_EXP(src) : 0, rnd_mode);
                    187: }
                    188:
                    189: double
                    190: mpfr_get_d1 (mpfr_srcptr src)
                    191: {
                    192:   return mpfr_get_d3 (src, MPFR_IS_FP(src) && MPFR_NOTZERO(src) ?
                    193:                       MPFR_EXP(src) : 0, __gmp_default_rounding_mode);
                    194: }

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