summaryrefslogtreecommitdiff
path: root/Build/source/libs/mpfr/mpfr-src/src/div_2ui.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/libs/mpfr/mpfr-src/src/div_2ui.c')
-rw-r--r--Build/source/libs/mpfr/mpfr-src/src/div_2ui.c22
1 files changed, 14 insertions, 8 deletions
diff --git a/Build/source/libs/mpfr/mpfr-src/src/div_2ui.c b/Build/source/libs/mpfr/mpfr-src/src/div_2ui.c
index 60fd9b4eb01..349d8367af3 100644
--- a/Build/source/libs/mpfr/mpfr-src/src/div_2ui.c
+++ b/Build/source/libs/mpfr/mpfr-src/src/div_2ui.c
@@ -1,6 +1,6 @@
/* mpfr_div_2ui -- divide a floating-point number by a power of two
-Copyright 1999, 2001-2019 Free Software Foundation, Inc.
+Copyright 1999, 2001-2020 Free Software Foundation, Inc.
Contributed by the AriC and Caramba projects, INRIA.
This file is part of the GNU MPFR Library.
@@ -40,6 +40,10 @@ mpfr_div_2ui (mpfr_ptr y, mpfr_srcptr x, unsigned long n, mpfr_rnd_t rnd_mode)
mpfr_uexp_t diffexp;
MPFR_SETRAW (inexact, y, x, exp, rnd_mode);
+ /* Warning! exp may have increased by 1 due to rounding. Thus the
+ difference below may overflow in a mpfr_exp_t; but mpfr_uexp_t
+ is OK to hold the value, with the difference done in unsigned
+ integer arithmetic in this type. */
diffexp = (mpfr_uexp_t) exp - (mpfr_uexp_t) (__gmpfr_emin - 1);
if (MPFR_UNLIKELY (n >= diffexp)) /* exp - n <= emin - 1 */
{
@@ -50,13 +54,15 @@ mpfr_div_2ui (mpfr_ptr y, mpfr_srcptr x, unsigned long n, mpfr_rnd_t rnd_mode)
rnd_mode = MPFR_RNDZ;
return mpfr_underflow (y, rnd_mode, MPFR_SIGN (y));
}
- /* exp - n >= emin (no underflow, no integer overflow) */
- while (n > LONG_MAX)
- {
- n -= LONG_MAX;
- exp -= LONG_MAX; /* note: signed values */
- }
- MPFR_SET_EXP (y, exp - (long) n);
+ /* Now, n < diffexp, i.e. n <= exp - emin, which a difference of
+ * two valid exponents + 0 or 1, thus fits in a mpfr_exp_t (from
+ * the constraints on valid exponents). Moreover, there cannot be
+ * an overflow (if exp had been increased by 1 due to rounding)
+ * since the case n = 0 has been filtered out.
+ */
+ MPFR_ASSERTD (n <= MPFR_EXP_MAX);
+ MPFR_ASSERTD (n >= 1);
+ MPFR_SET_EXP (y, exp - (mpfr_exp_t) n);
}
MPFR_RET (inexact);