summaryrefslogtreecommitdiff
path: root/Build/source/libs/mpfr/mpfr-src/src/set_si_2exp.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/libs/mpfr/mpfr-src/src/set_si_2exp.c')
-rw-r--r--Build/source/libs/mpfr/mpfr-src/src/set_si_2exp.c24
1 files changed, 22 insertions, 2 deletions
diff --git a/Build/source/libs/mpfr/mpfr-src/src/set_si_2exp.c b/Build/source/libs/mpfr/mpfr-src/src/set_si_2exp.c
index 97743d7acbb..5e703a47aaa 100644
--- a/Build/source/libs/mpfr/mpfr-src/src/set_si_2exp.c
+++ b/Build/source/libs/mpfr/mpfr-src/src/set_si_2exp.c
@@ -1,7 +1,7 @@
/* mpfr_set_si_2exp -- set a MPFR number from a machine signed integer with
a shift
-Copyright 2004, 2006-2019 Free Software Foundation, Inc.
+Copyright 2004, 2006-2020 Free Software Foundation, Inc.
Contributed by the AriC and Caramba projects, INRIA.
This file is part of the GNU MPFR Library.
@@ -33,6 +33,7 @@ mpfr_set_si_2exp (mpfr_ptr x, long i, mpfr_exp_t e, mpfr_rnd_t rnd_mode)
MPFR_SET_POS (x);
MPFR_RET (0);
}
+#ifdef MPFR_LONG_WITHIN_LIMB
else
{
mp_size_t xn;
@@ -40,7 +41,15 @@ mpfr_set_si_2exp (mpfr_ptr x, long i, mpfr_exp_t e, mpfr_rnd_t rnd_mode)
mp_limb_t ai, *xp;
int inex = 0;
- /* FIXME: support int limbs (e.g. 16-bit limbs on 16-bit proc) */
+ /* Early underflow/overflow checking is necessary to avoid
+ integer overflow or errors due to special exponent values. */
+ if (MPFR_UNLIKELY (e < __gmpfr_emin - (mpfr_exp_t)
+ (sizeof (unsigned long) * CHAR_BIT + 1)))
+ return mpfr_underflow (x, rnd_mode == MPFR_RNDN ?
+ MPFR_RNDZ : rnd_mode, i < 0 ? -1 : 1);
+ if (MPFR_UNLIKELY (e >= __gmpfr_emax))
+ return mpfr_overflow (x, rnd_mode, i < 0 ? -1 : 1);
+
ai = SAFE_ABS (unsigned long, i);
MPFR_ASSERTN (SAFE_ABS (unsigned long, i) == ai);
@@ -70,4 +79,15 @@ mpfr_set_si_2exp (mpfr_ptr x, long i, mpfr_exp_t e, mpfr_rnd_t rnd_mode)
MPFR_EXP (x) = e;
return mpfr_check_range (x, inex, rnd_mode);
}
+#else
+ /* if a long does not fit into a limb, we use mpfr_set_z_2exp */
+ {
+ mpz_t z;
+ int inex;
+ mpz_init_set_si (z, i);
+ inex = mpfr_set_z_2exp (x, z, e, rnd_mode);
+ mpz_clear (z);
+ return inex;
+ }
+#endif
}