summaryrefslogtreecommitdiff
path: root/Build/source/libs/mpfr/mpfr-src/src/set_ld.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/libs/mpfr/mpfr-src/src/set_ld.c')
-rw-r--r--Build/source/libs/mpfr/mpfr-src/src/set_ld.c114
1 files changed, 66 insertions, 48 deletions
diff --git a/Build/source/libs/mpfr/mpfr-src/src/set_ld.c b/Build/source/libs/mpfr/mpfr-src/src/set_ld.c
index 3d92d70affa..3ff57b99472 100644
--- a/Build/source/libs/mpfr/mpfr-src/src/set_ld.c
+++ b/Build/source/libs/mpfr/mpfr-src/src/set_ld.c
@@ -1,7 +1,7 @@
/* mpfr_set_ld -- convert a machine long double to
a multiple precision floating-point number
-Copyright 2002-2019 Free Software Foundation, Inc.
+Copyright 2002-2020 Free Software Foundation, Inc.
Contributed by the AriC and Caramba projects, INRIA.
This file is part of the GNU MPFR Library.
@@ -26,27 +26,8 @@ https://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
#define MPFR_NEED_LONGLONG_H
#include "mpfr-impl.h"
-/* Various i386 systems have been seen with <float.h> LDBL constants equal
- to the DBL ones, whereas they ought to be bigger, reflecting the 10-byte
- IEEE extended format on that processor. gcc 3.2.1 on FreeBSD and Solaris
- has been seen with the problem, and gcc 2.95.4 on FreeBSD 4.7. */
-
-#if HAVE_LDOUBLE_IEEE_EXT_LITTLE
-static const union {
- char bytes[10];
- long double d;
-} ldbl_max_struct = {
- { '\377','\377','\377','\377',
- '\377','\377','\377','\377',
- '\376','\177' }
-};
-#define MPFR_LDBL_MAX (ldbl_max_struct.d)
-#else
-#define MPFR_LDBL_MAX LDBL_MAX
-#endif
-
-/* To check for +inf, one can use the test x > MPFR_LDBL_MAX, as LDBL_MAX
- is the maximum finite number representable in a long double, according
+/* To check for +inf, one can use the test x > LDBL_MAX, as LDBL_MAX is
+ the maximum finite number representable in a long double, according
to DR 467; see
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2092.htm
If this fails on some platform, a test x - x != 0 might be used. */
@@ -62,11 +43,25 @@ mpfr_set_ld (mpfr_ptr r, long double d, mpfr_rnd_t rnd_mode)
#elif defined(HAVE_LDOUBLE_IEEE_EXT_LITTLE)
+#if GMP_NUMB_BITS >= 64
+# define MPFR_LIMBS_PER_LONG_DOUBLE 1
+#elif GMP_NUMB_BITS == 32
+# define MPFR_LIMBS_PER_LONG_DOUBLE 2
+#elif GMP_NUMB_BITS == 16
+# define MPFR_LIMBS_PER_LONG_DOUBLE 4
+#elif GMP_NUMB_BITS == 8
+# define MPFR_LIMBS_PER_LONG_DOUBLE 8
+#else
+#error "GMP_NUMB_BITS is assumed to be 8, 16, 32 or >= 64"
+#endif
+/* The hypothetical GMP_NUMB_BITS == 16 is not supported. It will trigger
+ an error below. */
+
/* IEEE Extended Little Endian Code */
int
mpfr_set_ld (mpfr_ptr r, long double d, mpfr_rnd_t rnd_mode)
{
- int inexact, i, k, cnt;
+ int inexact, k, cnt;
mpfr_t tmp;
mp_limb_t tmpmant[MPFR_LIMBS_PER_LONG_DOUBLE];
mpfr_long_double_t x;
@@ -81,13 +76,13 @@ mpfr_set_ld (mpfr_ptr r, long double d, mpfr_rnd_t rnd_mode)
MPFR_RET_NAN;
}
/* Check for INF */
- else if (MPFR_UNLIKELY (d > MPFR_LDBL_MAX))
+ else if (MPFR_UNLIKELY (d > LDBL_MAX))
{
MPFR_SET_INF (r);
MPFR_SET_POS (r);
return 0;
}
- else if (MPFR_UNLIKELY (d < -MPFR_LDBL_MAX))
+ else if (MPFR_UNLIKELY (d < -LDBL_MAX))
{
MPFR_SET_INF (r);
MPFR_SET_NEG (r);
@@ -120,25 +115,48 @@ mpfr_set_ld (mpfr_ptr r, long double d, mpfr_rnd_t rnd_mode)
x.ld = -x.ld;
}
- /* Extract mantissa */
-#if GMP_NUMB_BITS >= 64
+ /* Extract and normalize the significand */
+#if MPFR_LIMBS_PER_LONG_DOUBLE == 1
tmpmant[0] = ((mp_limb_t) x.s.manh << 32) | ((mp_limb_t) x.s.manl);
-#else
+ count_leading_zeros (cnt, tmpmant[0]);
+ tmpmant[0] <<= cnt;
+ k = 0; /* number of limbs shifted */
+#else /* MPFR_LIMBS_PER_LONG_DOUBLE >= 2 */
+#if MPFR_LIMBS_PER_LONG_DOUBLE == 2
tmpmant[0] = (mp_limb_t) x.s.manl;
tmpmant[1] = (mp_limb_t) x.s.manh;
-#endif
-
- /* Normalize mantissa */
- i = MPFR_LIMBS_PER_LONG_DOUBLE;
- MPN_NORMALIZE_NOT_ZERO (tmpmant, i);
- k = MPFR_LIMBS_PER_LONG_DOUBLE - i;
- count_leading_zeros (cnt, tmpmant[i - 1]);
- if (MPFR_UNLIKELY (cnt != 0))
- mpn_lshift (tmpmant + k, tmpmant, i, cnt);
- else if (MPFR_UNLIKELY (k != 0))
- MPN_COPY (tmpmant + k, tmpmant, i);
- if (MPFR_UNLIKELY (k != 0))
- MPN_ZERO (tmpmant, k);
+#elif MPFR_LIMBS_PER_LONG_DOUBLE == 4
+ tmpmant[0] = (mp_limb_t) x.s.manl;
+ tmpmant[1] = (mp_limb_t) (x.s.manl >> 16);
+ tmpmant[2] = (mp_limb_t) x.s.manh;
+ tmpmant[3] = (mp_limb_t) (x.s.manh >> 16);
+#elif MPFR_LIMBS_PER_LONG_DOUBLE == 8
+ tmpmant[0] = (mp_limb_t) x.s.manl;
+ tmpmant[1] = (mp_limb_t) (x.s.manl >> 8);
+ tmpmant[2] = (mp_limb_t) (x.s.manl >> 16);
+ tmpmant[3] = (mp_limb_t) (x.s.manl >> 24);
+ tmpmant[4] = (mp_limb_t) x.s.manh;
+ tmpmant[5] = (mp_limb_t) (x.s.manh >> 8);
+ tmpmant[6] = (mp_limb_t) (x.s.manh >> 16);
+ tmpmant[7] = (mp_limb_t) (x.s.manh >> 24);
+#else
+#error "MPFR_LIMBS_PER_LONG_DOUBLE should be 1, 2, 4 or 8"
+#endif /* MPFR_LIMBS_PER_LONG_DOUBLE >= 2 */
+ {
+ int i = MPFR_LIMBS_PER_LONG_DOUBLE;
+ MPN_NORMALIZE_NOT_ZERO (tmpmant, i);
+ k = MPFR_LIMBS_PER_LONG_DOUBLE - i;
+ count_leading_zeros (cnt, tmpmant[i - 1]);
+ if (cnt != 0)
+ mpn_lshift (tmpmant + k, tmpmant, i, cnt);
+ else if (k != 0)
+ /* since we copy {tmpmant, i} into {tmpmant + k, i}, we should work
+ decreasingly, thus call mpn_copyd */
+ mpn_copyd (tmpmant + k, tmpmant, i);
+ if (k != 0)
+ MPN_ZERO (tmpmant, k);
+ }
+#endif /* MPFR_LIMBS_PER_LONG_DOUBLE == 1 */
/* Set exponent */
exp = (mpfr_exp_t) ((x.s.exph << 8) + x.s.expl); /* 15-bit unsigned int */
@@ -163,7 +181,7 @@ int
mpfr_set_ld (mpfr_ptr r, long double d, mpfr_rnd_t rnd_mode)
{
mpfr_t t, u;
- int inexact, shift_exp;
+ int inexact;
double h, l;
MPFR_SAVE_EXPO_DECL (expo);
@@ -171,12 +189,12 @@ mpfr_set_ld (mpfr_ptr r, long double d, mpfr_rnd_t rnd_mode)
LONGDOUBLE_NAN_ACTION (d, goto nan);
/* Check for INF */
- if (d > MPFR_LDBL_MAX)
+ if (d > LDBL_MAX)
{
mpfr_set_inf (r, 1);
return 0;
}
- else if (d < -MPFR_LDBL_MAX)
+ else if (d < -LDBL_MAX)
{
mpfr_set_inf (r, -1);
return 0;
@@ -185,8 +203,8 @@ mpfr_set_ld (mpfr_ptr r, long double d, mpfr_rnd_t rnd_mode)
else if (d == 0.0)
return mpfr_set_d (r, (double) d, rnd_mode);
- if (d >= (long double) MPFR_LDBL_MAX || d <= (long double) -MPFR_LDBL_MAX)
- h = (d >= (long double) MPFR_LDBL_MAX) ? MPFR_LDBL_MAX : -MPFR_LDBL_MAX;
+ if (d >= LDBL_MAX || d <= -LDBL_MAX)
+ h = (d >= LDBL_MAX) ? LDBL_MAX : -LDBL_MAX;
else
h = (double) d; /* should not overflow */
l = (double) (d - (long double) h);
@@ -229,12 +247,12 @@ mpfr_set_ld (mpfr_ptr r, long double d, mpfr_rnd_t rnd_mode)
LONGDOUBLE_NAN_ACTION (d, goto nan);
/* Check for INF */
- if (d > MPFR_LDBL_MAX)
+ if (d > LDBL_MAX)
{
mpfr_set_inf (r, 1);
return 0;
}
- else if (d < -MPFR_LDBL_MAX)
+ else if (d < -LDBL_MAX)
{
mpfr_set_inf (r, -1);
return 0;