diff options
author | zimmerma <zimmerma@280ebfd0-de03-0410-8827-d642c229c3f4> | 2009-09-15 11:37:40 +0000 |
---|---|---|
committer | zimmerma <zimmerma@280ebfd0-de03-0410-8827-d642c229c3f4> | 2009-09-15 11:37:40 +0000 |
commit | 40def89a5d2c97509a526582e0bdc747beceb386 (patch) | |
tree | 81a23b35a99508ba009d28b58a827920988970bb /get_d.c | |
parent | 8b83b107bde01e54a6f33841130e07181e2b53bf (diff) | |
download | mpfr-40def89a5d2c97509a526582e0bdc747beceb386.tar.gz |
added new functions mpfr_set_binary32 and mpfr_get_binary32
fixed bug in mpfr_get_d and mpfr_get_decimal64 for RNDA
git-svn-id: svn://scm.gforge.inria.fr/svn/mpfr/trunk@6424 280ebfd0-de03-0410-8827-d642c229c3f4
Diffstat (limited to 'get_d.c')
-rw-r--r-- | get_d.c | 127 |
1 files changed, 7 insertions, 120 deletions
@@ -26,125 +26,8 @@ http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc., #define MPFR_NEED_LONGLONG_H #include "mpfr-impl.h" -/* "double" NaN and infinities are written as explicit bytes to be sure of - getting what we want, and to be sure of not depending on libm. - - Could use 4-byte "float" values and let the code convert them, but it - seems more direct to give exactly what we want. Certainly for gcc 3.0.2 - on alphaev56-unknown-freebsd4.3 the NaN must be 8-bytes, since that - compiler+system was seen incorrectly converting from a "float" NaN. */ - -#if _GMP_IEEE_FLOATS - -/* The "d" field guarantees alignment to a suitable boundary for a double. - Could use a union instead, if we checked the compiler supports union - initializers. */ -struct dbl_bytes { - unsigned char b[8]; - double d; -}; - -#define MPFR_DBL_INFP (* (const double *) dbl_infp.b) -#define MPFR_DBL_INFM (* (const double *) dbl_infm.b) -#define MPFR_DBL_NAN (* (const double *) dbl_nan.b) - -#if HAVE_DOUBLE_IEEE_LITTLE_ENDIAN -static const struct dbl_bytes dbl_infp = - { { 0, 0, 0, 0, 0, 0, 0xF0, 0x7F }, 0.0 }; -static const struct dbl_bytes dbl_infm = - { { 0, 0, 0, 0, 0, 0, 0xF0, 0xFF }, 0.0 }; -static const struct dbl_bytes dbl_nan = - { { 0, 0, 0, 0, 0, 0, 0xF8, 0x7F }, 0.0 }; -#endif -#if HAVE_DOUBLE_IEEE_LITTLE_SWAPPED -static const struct dbl_bytes dbl_infp = - { { 0, 0, 0xF0, 0x7F, 0, 0, 0, 0 }, 0.0 }; -static const struct dbl_bytes dbl_infm = - { { 0, 0, 0xF0, 0xFF, 0, 0, 0, 0 }, 0.0 }; -static const struct dbl_bytes dbl_nan = - { { 0, 0, 0xF8, 0x7F, 0, 0, 0, 0 }, 0.0 }; -#endif -#if HAVE_DOUBLE_IEEE_BIG_ENDIAN -static const struct dbl_bytes dbl_infp = - { { 0x7F, 0xF0, 0, 0, 0, 0, 0, 0 }, 0.0 }; -static const struct dbl_bytes dbl_infm = - { { 0xFF, 0xF0, 0, 0, 0, 0, 0, 0 }, 0.0 }; -static const struct dbl_bytes dbl_nan = - { { 0x7F, 0xF8, 0, 0, 0, 0, 0, 0 }, 0.0 }; -#endif - -#else /* _GMP_IEEE_FLOATS */ - -#define MPFR_DBL_INFP DBL_POS_INF -#define MPFR_DBL_INFM DBL_NEG_INF -#define MPFR_DBL_NAN DBL_NAN - -#endif /* _GMP_IEEE_FLOATS */ - - -/* multiplies 1/2 <= d <= 1 by 2^exp */ -static double -mpfr_scale2 (double d, int exp) -{ -#if _GMP_IEEE_FLOATS - { - union ieee_double_extract x; - - if (MPFR_UNLIKELY (d == 1.0)) - { - d = 0.5; - exp ++; - } - - /* now 1/2 <= d < 1 */ - - /* infinities and zeroes have already been checked */ - MPFR_ASSERTD (-1073 <= exp && exp <= 1025); - - x.d = d; - if (MPFR_UNLIKELY (exp < -1021)) /* subnormal case */ - { - x.s.exp += exp + 52; - x.d *= DBL_EPSILON; - } - else /* normalized case */ - { - x.s.exp += exp; - } - return x.d; - } -#else /* _GMP_IEEE_FLOATS */ - { - double factor; - - /* An overflow may occurs (example: 0.5*2^1024) */ - if (d < 1.0) - { - d += d; - exp--; - } - /* Now 1.0 <= d < 2.0 */ - - if (exp < 0) - { - factor = 0.5; - exp = -exp; - } - else - { - factor = 2.0; - } - while (exp != 0) - { - if ((exp & 1) != 0) - d *= factor; - exp >>= 1; - factor *= factor; - } - return d; - } -#endif -} +#include "ieee_floats.h" +#include "scale2.c" /* Assumes IEEE-754 double precision; otherwise, only an approximated result will be returned, without any guaranty (and special cases @@ -174,6 +57,9 @@ mpfr_get_d (mpfr_srcptr src, mpfr_rnd_t rnd_mode) e = MPFR_GET_EXP (src); negative = MPFR_IS_NEG (src); + if (MPFR_UNLIKELY(rnd_mode == MPFR_RNDA)) + rnd_mode = negative ? MPFR_RNDD : MPFR_RNDU; + /* the smallest normalized number is 2^(-1022)=0.1e-1021, and the smallest subnormal is 2^(-1074)=0.1e-1073 */ if (MPFR_UNLIKELY (e < -1073)) @@ -188,7 +74,8 @@ mpfr_get_d (mpfr_srcptr src, mpfr_rnd_t rnd_mode) (rnd_mode == MPFR_RNDU || (rnd_mode == MPFR_RNDN && mpfr_cmp_si_2exp(src, 1, -1075) > 0) ? DBL_MIN : 0.0); - if (d != 0.0) + if (d != 0.0) /* we multiply DBL_MIN = 2^(-1022) by DBL_EPSILON = 2^(-52) + to get +-2^(-1074) */ d *= DBL_EPSILON; } /* the largest normalized number is 2^1024*(1-2^(-53))=0.111...111e1024 */ |