14a238c70SJohn Marino /* mpfr_set_ld -- convert a machine long double to
24a238c70SJohn Marino a multiple precision floating-point number
34a238c70SJohn Marino
4*ab6d115fSJohn Marino Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc.
5*ab6d115fSJohn Marino Contributed by the AriC and Caramel projects, INRIA.
64a238c70SJohn Marino
74a238c70SJohn Marino This file is part of the GNU MPFR Library.
84a238c70SJohn Marino
94a238c70SJohn Marino The GNU MPFR Library is free software; you can redistribute it and/or modify
104a238c70SJohn Marino it under the terms of the GNU Lesser General Public License as published by
114a238c70SJohn Marino the Free Software Foundation; either version 3 of the License, or (at your
124a238c70SJohn Marino option) any later version.
134a238c70SJohn Marino
144a238c70SJohn Marino The GNU MPFR Library is distributed in the hope that it will be useful, but
154a238c70SJohn Marino WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
164a238c70SJohn Marino or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
174a238c70SJohn Marino License for more details.
184a238c70SJohn Marino
194a238c70SJohn Marino You should have received a copy of the GNU Lesser General Public License
204a238c70SJohn Marino along with the GNU MPFR Library; see the file COPYING.LESSER. If not, see
214a238c70SJohn Marino http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
224a238c70SJohn Marino 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
234a238c70SJohn Marino
244a238c70SJohn Marino #include <float.h>
254a238c70SJohn Marino
264a238c70SJohn Marino #define MPFR_NEED_LONGLONG_H
274a238c70SJohn Marino #include "mpfr-impl.h"
284a238c70SJohn Marino
294a238c70SJohn Marino /* Various i386 systems have been seen with <float.h> LDBL constants equal
304a238c70SJohn Marino to the DBL ones, whereas they ought to be bigger, reflecting the 10-byte
314a238c70SJohn Marino IEEE extended format on that processor. gcc 3.2.1 on FreeBSD and Solaris
324a238c70SJohn Marino has been seen with the problem, and gcc 2.95.4 on FreeBSD 4.7. */
334a238c70SJohn Marino
344a238c70SJohn Marino #if HAVE_LDOUBLE_IEEE_EXT_LITTLE
354a238c70SJohn Marino static const union {
364a238c70SJohn Marino char bytes[10];
374a238c70SJohn Marino long double d;
384a238c70SJohn Marino } ldbl_max_struct = {
394a238c70SJohn Marino { '\377','\377','\377','\377',
404a238c70SJohn Marino '\377','\377','\377','\377',
414a238c70SJohn Marino '\376','\177' }
424a238c70SJohn Marino };
434a238c70SJohn Marino #define MPFR_LDBL_MAX (ldbl_max_struct.d)
444a238c70SJohn Marino #else
454a238c70SJohn Marino #define MPFR_LDBL_MAX LDBL_MAX
464a238c70SJohn Marino #endif
474a238c70SJohn Marino
484a238c70SJohn Marino #ifndef HAVE_LDOUBLE_IEEE_EXT_LITTLE
494a238c70SJohn Marino
504a238c70SJohn Marino /* Generic code */
514a238c70SJohn Marino int
mpfr_set_ld(mpfr_ptr r,long double d,mpfr_rnd_t rnd_mode)524a238c70SJohn Marino mpfr_set_ld (mpfr_ptr r, long double d, mpfr_rnd_t rnd_mode)
534a238c70SJohn Marino {
544a238c70SJohn Marino mpfr_t t, u;
554a238c70SJohn Marino int inexact, shift_exp;
564a238c70SJohn Marino long double x;
574a238c70SJohn Marino MPFR_SAVE_EXPO_DECL (expo);
584a238c70SJohn Marino
594a238c70SJohn Marino /* Check for NAN */
604a238c70SJohn Marino LONGDOUBLE_NAN_ACTION (d, goto nan);
614a238c70SJohn Marino
624a238c70SJohn Marino /* Check for INF */
634a238c70SJohn Marino if (d > MPFR_LDBL_MAX)
644a238c70SJohn Marino {
654a238c70SJohn Marino mpfr_set_inf (r, 1);
664a238c70SJohn Marino return 0;
674a238c70SJohn Marino }
684a238c70SJohn Marino else if (d < -MPFR_LDBL_MAX)
694a238c70SJohn Marino {
704a238c70SJohn Marino mpfr_set_inf (r, -1);
714a238c70SJohn Marino return 0;
724a238c70SJohn Marino }
734a238c70SJohn Marino /* Check for ZERO */
744a238c70SJohn Marino else if (d == 0.0)
754a238c70SJohn Marino return mpfr_set_d (r, (double) d, rnd_mode);
764a238c70SJohn Marino
774a238c70SJohn Marino mpfr_init2 (t, MPFR_LDBL_MANT_DIG);
784a238c70SJohn Marino mpfr_init2 (u, IEEE_DBL_MANT_DIG);
794a238c70SJohn Marino
804a238c70SJohn Marino MPFR_SAVE_EXPO_MARK (expo);
814a238c70SJohn Marino
824a238c70SJohn Marino convert:
834a238c70SJohn Marino x = d;
844a238c70SJohn Marino MPFR_SET_ZERO (t); /* The sign doesn't matter. */
854a238c70SJohn Marino shift_exp = 0; /* invariant: remainder to deal with is d*2^shift_exp */
864a238c70SJohn Marino while (x != (long double) 0.0)
874a238c70SJohn Marino {
884a238c70SJohn Marino /* Check overflow of double */
894a238c70SJohn Marino if (x > (long double) DBL_MAX || (-x) > (long double) DBL_MAX)
904a238c70SJohn Marino {
914a238c70SJohn Marino long double div9, div10, div11, div12, div13;
924a238c70SJohn Marino
934a238c70SJohn Marino #define TWO_64 18446744073709551616.0 /* 2^64 */
944a238c70SJohn Marino #define TWO_128 (TWO_64 * TWO_64)
954a238c70SJohn Marino #define TWO_256 (TWO_128 * TWO_128)
964a238c70SJohn Marino div9 = (long double) (double) (TWO_256 * TWO_256); /* 2^(2^9) */
974a238c70SJohn Marino div10 = div9 * div9;
984a238c70SJohn Marino div11 = div10 * div10; /* 2^(2^11) */
994a238c70SJohn Marino div12 = div11 * div11; /* 2^(2^12) */
1004a238c70SJohn Marino div13 = div12 * div12; /* 2^(2^13) */
1014a238c70SJohn Marino if (ABS (x) >= div13)
1024a238c70SJohn Marino {
1034a238c70SJohn Marino x /= div13; /* exact */
1044a238c70SJohn Marino shift_exp += 8192;
1054a238c70SJohn Marino mpfr_div_2si (t, t, 8192, MPFR_RNDZ);
1064a238c70SJohn Marino }
1074a238c70SJohn Marino if (ABS (x) >= div12)
1084a238c70SJohn Marino {
1094a238c70SJohn Marino x /= div12; /* exact */
1104a238c70SJohn Marino shift_exp += 4096;
1114a238c70SJohn Marino mpfr_div_2si (t, t, 4096, MPFR_RNDZ);
1124a238c70SJohn Marino }
1134a238c70SJohn Marino if (ABS (x) >= div11)
1144a238c70SJohn Marino {
1154a238c70SJohn Marino x /= div11; /* exact */
1164a238c70SJohn Marino shift_exp += 2048;
1174a238c70SJohn Marino mpfr_div_2si (t, t, 2048, MPFR_RNDZ);
1184a238c70SJohn Marino }
1194a238c70SJohn Marino if (ABS (x) >= div10)
1204a238c70SJohn Marino {
1214a238c70SJohn Marino x /= div10; /* exact */
1224a238c70SJohn Marino shift_exp += 1024;
1234a238c70SJohn Marino mpfr_div_2si (t, t, 1024, MPFR_RNDZ);
1244a238c70SJohn Marino }
1254a238c70SJohn Marino /* warning: we may have DBL_MAX=2^1024*(1-2^(-53)) < x < 2^1024,
1264a238c70SJohn Marino therefore we have one extra exponent reduction step */
1274a238c70SJohn Marino if (ABS (x) >= div9)
1284a238c70SJohn Marino {
1294a238c70SJohn Marino x /= div9; /* exact */
1304a238c70SJohn Marino shift_exp += 512;
1314a238c70SJohn Marino mpfr_div_2si (t, t, 512, MPFR_RNDZ);
1324a238c70SJohn Marino }
1334a238c70SJohn Marino } /* Check overflow of double */
1344a238c70SJohn Marino else /* no overflow on double */
1354a238c70SJohn Marino {
1364a238c70SJohn Marino long double div9, div10, div11;
1374a238c70SJohn Marino
1384a238c70SJohn Marino div9 = (long double) (double) 7.4583407312002067432909653e-155;
1394a238c70SJohn Marino /* div9 = 2^(-2^9) */
1404a238c70SJohn Marino div10 = div9 * div9; /* 2^(-2^10) */
1414a238c70SJohn Marino div11 = div10 * div10; /* 2^(-2^11) if extended precision */
1424a238c70SJohn Marino /* since -DBL_MAX <= x <= DBL_MAX, the cast to double should not
1434a238c70SJohn Marino overflow here */
1444a238c70SJohn Marino if (ABS(x) < div10 &&
1454a238c70SJohn Marino div11 != (long double) 0.0 &&
1464a238c70SJohn Marino div11 / div10 == div10) /* possible underflow */
1474a238c70SJohn Marino {
1484a238c70SJohn Marino long double div12, div13;
1494a238c70SJohn Marino /* After the divisions, any bit of x must be >= div10,
1504a238c70SJohn Marino hence the possible division by div9. */
1514a238c70SJohn Marino div12 = div11 * div11; /* 2^(-2^12) */
1524a238c70SJohn Marino div13 = div12 * div12; /* 2^(-2^13) */
1534a238c70SJohn Marino if (ABS (x) <= div13)
1544a238c70SJohn Marino {
1554a238c70SJohn Marino x /= div13; /* exact */
1564a238c70SJohn Marino shift_exp -= 8192;
1574a238c70SJohn Marino mpfr_mul_2si (t, t, 8192, MPFR_RNDZ);
1584a238c70SJohn Marino }
1594a238c70SJohn Marino if (ABS (x) <= div12)
1604a238c70SJohn Marino {
1614a238c70SJohn Marino x /= div12; /* exact */
1624a238c70SJohn Marino shift_exp -= 4096;
1634a238c70SJohn Marino mpfr_mul_2si (t, t, 4096, MPFR_RNDZ);
1644a238c70SJohn Marino }
1654a238c70SJohn Marino if (ABS (x) <= div11)
1664a238c70SJohn Marino {
1674a238c70SJohn Marino x /= div11; /* exact */
1684a238c70SJohn Marino shift_exp -= 2048;
1694a238c70SJohn Marino mpfr_mul_2si (t, t, 2048, MPFR_RNDZ);
1704a238c70SJohn Marino }
1714a238c70SJohn Marino if (ABS (x) <= div10)
1724a238c70SJohn Marino {
1734a238c70SJohn Marino x /= div10; /* exact */
1744a238c70SJohn Marino shift_exp -= 1024;
1754a238c70SJohn Marino mpfr_mul_2si (t, t, 1024, MPFR_RNDZ);
1764a238c70SJohn Marino }
1774a238c70SJohn Marino if (ABS(x) <= div9)
1784a238c70SJohn Marino {
1794a238c70SJohn Marino x /= div9; /* exact */
1804a238c70SJohn Marino shift_exp -= 512;
1814a238c70SJohn Marino mpfr_mul_2si (t, t, 512, MPFR_RNDZ);
1824a238c70SJohn Marino }
1834a238c70SJohn Marino }
1844a238c70SJohn Marino else /* no underflow */
1854a238c70SJohn Marino {
1864a238c70SJohn Marino inexact = mpfr_set_d (u, (double) x, MPFR_RNDZ);
1874a238c70SJohn Marino MPFR_ASSERTD (inexact == 0);
1884a238c70SJohn Marino if (mpfr_add (t, t, u, MPFR_RNDZ) != 0)
1894a238c70SJohn Marino {
1904a238c70SJohn Marino if (!mpfr_number_p (t))
1914a238c70SJohn Marino break;
1924a238c70SJohn Marino /* Inexact. This cannot happen unless the C implementation
1934a238c70SJohn Marino "lies" on the precision or when long doubles are
1944a238c70SJohn Marino implemented with FP expansions like under Mac OS X. */
1954a238c70SJohn Marino if (MPFR_PREC (t) != MPFR_PREC (r) + 1)
1964a238c70SJohn Marino {
1974a238c70SJohn Marino /* We assume that MPFR_PREC (r) < MPFR_PREC_MAX.
1984a238c70SJohn Marino The precision MPFR_PREC (r) + 1 allows us to
1994a238c70SJohn Marino deduce the rounding bit and the sticky bit. */
2004a238c70SJohn Marino mpfr_set_prec (t, MPFR_PREC (r) + 1);
2014a238c70SJohn Marino goto convert;
2024a238c70SJohn Marino }
2034a238c70SJohn Marino else
2044a238c70SJohn Marino {
2054a238c70SJohn Marino mp_limb_t *tp;
2064a238c70SJohn Marino int rb_mask;
2074a238c70SJohn Marino
2084a238c70SJohn Marino /* Since mpfr_add was inexact, the sticky bit is 1. */
2094a238c70SJohn Marino tp = MPFR_MANT (t);
2104a238c70SJohn Marino rb_mask = MPFR_LIMB_ONE <<
2114a238c70SJohn Marino (GMP_NUMB_BITS - 1 -
2124a238c70SJohn Marino (MPFR_PREC (r) & (GMP_NUMB_BITS - 1)));
2134a238c70SJohn Marino if (rnd_mode == MPFR_RNDN)
2144a238c70SJohn Marino rnd_mode = (*tp & rb_mask) ^ MPFR_IS_NEG (t) ?
2154a238c70SJohn Marino MPFR_RNDU : MPFR_RNDD;
2164a238c70SJohn Marino *tp |= rb_mask;
2174a238c70SJohn Marino break;
2184a238c70SJohn Marino }
2194a238c70SJohn Marino }
2204a238c70SJohn Marino x -= (long double) mpfr_get_d1 (u); /* exact */
2214a238c70SJohn Marino }
2224a238c70SJohn Marino }
2234a238c70SJohn Marino }
2244a238c70SJohn Marino inexact = mpfr_mul_2si (r, t, shift_exp, rnd_mode);
2254a238c70SJohn Marino mpfr_clear (t);
2264a238c70SJohn Marino mpfr_clear (u);
2274a238c70SJohn Marino
2284a238c70SJohn Marino MPFR_SAVE_EXPO_FREE (expo);
2294a238c70SJohn Marino return mpfr_check_range (r, inexact, rnd_mode);
2304a238c70SJohn Marino
2314a238c70SJohn Marino nan:
2324a238c70SJohn Marino MPFR_SET_NAN(r);
2334a238c70SJohn Marino MPFR_RET_NAN;
2344a238c70SJohn Marino }
2354a238c70SJohn Marino
2364a238c70SJohn Marino #else /* IEEE Extended Little Endian Code */
2374a238c70SJohn Marino
2384a238c70SJohn Marino int
mpfr_set_ld(mpfr_ptr r,long double d,mpfr_rnd_t rnd_mode)2394a238c70SJohn Marino mpfr_set_ld (mpfr_ptr r, long double d, mpfr_rnd_t rnd_mode)
2404a238c70SJohn Marino {
2414a238c70SJohn Marino int inexact, i, k, cnt;
2424a238c70SJohn Marino mpfr_t tmp;
2434a238c70SJohn Marino mp_limb_t tmpmant[MPFR_LIMBS_PER_LONG_DOUBLE];
2444a238c70SJohn Marino mpfr_long_double_t x;
2454a238c70SJohn Marino mpfr_exp_t exp;
2464a238c70SJohn Marino int signd;
2474a238c70SJohn Marino MPFR_SAVE_EXPO_DECL (expo);
2484a238c70SJohn Marino
2494a238c70SJohn Marino /* Check for NAN */
2504a238c70SJohn Marino if (MPFR_UNLIKELY (d != d))
2514a238c70SJohn Marino {
2524a238c70SJohn Marino MPFR_SET_NAN (r);
2534a238c70SJohn Marino MPFR_RET_NAN;
2544a238c70SJohn Marino }
2554a238c70SJohn Marino /* Check for INF */
2564a238c70SJohn Marino else if (MPFR_UNLIKELY (d > MPFR_LDBL_MAX))
2574a238c70SJohn Marino {
2584a238c70SJohn Marino MPFR_SET_INF (r);
2594a238c70SJohn Marino MPFR_SET_POS (r);
2604a238c70SJohn Marino return 0;
2614a238c70SJohn Marino }
2624a238c70SJohn Marino else if (MPFR_UNLIKELY (d < -MPFR_LDBL_MAX))
2634a238c70SJohn Marino {
2644a238c70SJohn Marino MPFR_SET_INF (r);
2654a238c70SJohn Marino MPFR_SET_NEG (r);
2664a238c70SJohn Marino return 0;
2674a238c70SJohn Marino }
2684a238c70SJohn Marino /* Check for ZERO */
2694a238c70SJohn Marino else if (MPFR_UNLIKELY (d == 0.0))
2704a238c70SJohn Marino {
2714a238c70SJohn Marino x.ld = d;
2724a238c70SJohn Marino MPFR_SET_ZERO (r);
2734a238c70SJohn Marino if (x.s.sign == 1)
2744a238c70SJohn Marino MPFR_SET_NEG(r);
2754a238c70SJohn Marino else
2764a238c70SJohn Marino MPFR_SET_POS(r);
2774a238c70SJohn Marino return 0;
2784a238c70SJohn Marino }
2794a238c70SJohn Marino
2804a238c70SJohn Marino /* now d is neither 0, nor NaN nor Inf */
2814a238c70SJohn Marino MPFR_SAVE_EXPO_MARK (expo);
2824a238c70SJohn Marino
2834a238c70SJohn Marino MPFR_MANT (tmp) = tmpmant;
2844a238c70SJohn Marino MPFR_PREC (tmp) = 64;
2854a238c70SJohn Marino
2864a238c70SJohn Marino /* Extract sign */
2874a238c70SJohn Marino x.ld = d;
2884a238c70SJohn Marino signd = MPFR_SIGN_POS;
2894a238c70SJohn Marino if (x.ld < 0.0)
2904a238c70SJohn Marino {
2914a238c70SJohn Marino signd = MPFR_SIGN_NEG;
2924a238c70SJohn Marino x.ld = -x.ld;
2934a238c70SJohn Marino }
2944a238c70SJohn Marino
2954a238c70SJohn Marino /* Extract mantissa */
2964a238c70SJohn Marino #if GMP_NUMB_BITS >= 64
2974a238c70SJohn Marino tmpmant[0] = ((mp_limb_t) x.s.manh << 32) | ((mp_limb_t) x.s.manl);
2984a238c70SJohn Marino #else
2994a238c70SJohn Marino tmpmant[0] = (mp_limb_t) x.s.manl;
3004a238c70SJohn Marino tmpmant[1] = (mp_limb_t) x.s.manh;
3014a238c70SJohn Marino #endif
3024a238c70SJohn Marino
3034a238c70SJohn Marino /* Normalize mantissa */
3044a238c70SJohn Marino i = MPFR_LIMBS_PER_LONG_DOUBLE;
3054a238c70SJohn Marino MPN_NORMALIZE_NOT_ZERO (tmpmant, i);
3064a238c70SJohn Marino k = MPFR_LIMBS_PER_LONG_DOUBLE - i;
3074a238c70SJohn Marino count_leading_zeros (cnt, tmpmant[i - 1]);
3084a238c70SJohn Marino if (MPFR_LIKELY (cnt != 0))
3094a238c70SJohn Marino mpn_lshift (tmpmant + k, tmpmant, i, cnt);
3104a238c70SJohn Marino else if (k != 0)
3114a238c70SJohn Marino MPN_COPY (tmpmant + k, tmpmant, i);
3124a238c70SJohn Marino if (MPFR_UNLIKELY (k != 0))
3134a238c70SJohn Marino MPN_ZERO (tmpmant, k);
3144a238c70SJohn Marino
3154a238c70SJohn Marino /* Set exponent */
3164a238c70SJohn Marino exp = (mpfr_exp_t) ((x.s.exph << 8) + x.s.expl); /* 15-bit unsigned int */
3174a238c70SJohn Marino if (MPFR_UNLIKELY (exp == 0))
3184a238c70SJohn Marino exp -= 0x3FFD;
3194a238c70SJohn Marino else
3204a238c70SJohn Marino exp -= 0x3FFE;
3214a238c70SJohn Marino
3224a238c70SJohn Marino MPFR_SET_EXP (tmp, exp - cnt - k * GMP_NUMB_BITS);
3234a238c70SJohn Marino
3244a238c70SJohn Marino /* tmp is exact */
3254a238c70SJohn Marino inexact = mpfr_set4 (r, tmp, rnd_mode, signd);
3264a238c70SJohn Marino
3274a238c70SJohn Marino MPFR_SAVE_EXPO_FREE (expo);
3284a238c70SJohn Marino return mpfr_check_range (r, inexact, rnd_mode);
3294a238c70SJohn Marino }
3304a238c70SJohn Marino
3314a238c70SJohn Marino #endif
332