summaryrefslogtreecommitdiff
path: root/Build/source/libs/mpfr/mpfr-src/src/mul_ui.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/libs/mpfr/mpfr-src/src/mul_ui.c')
-rw-r--r--Build/source/libs/mpfr/mpfr-src/src/mul_ui.c112
1 files changed, 66 insertions, 46 deletions
diff --git a/Build/source/libs/mpfr/mpfr-src/src/mul_ui.c b/Build/source/libs/mpfr/mpfr-src/src/mul_ui.c
index c745e029983..408133a4c91 100644
--- a/Build/source/libs/mpfr/mpfr-src/src/mul_ui.c
+++ b/Build/source/libs/mpfr/mpfr-src/src/mul_ui.c
@@ -1,6 +1,6 @@
/* mpfr_mul_ui -- multiply a floating-point number by a machine integer
-Copyright 1999-2019 Free Software Foundation, Inc.
+Copyright 1999-2020 Free Software Foundation, Inc.
Contributed by the AriC and Caramba projects, INRIA.
This file is part of the GNU MPFR Library.
@@ -27,10 +27,7 @@ https://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
MPFR_HOT_FUNCTION_ATTR int
mpfr_mul_ui (mpfr_ptr y, mpfr_srcptr x, unsigned long int u, mpfr_rnd_t rnd_mode)
{
- mp_limb_t *yp;
- mp_size_t xn;
- int cnt, inexact;
- MPFR_TMP_DECL (marker);
+ int inexact;
if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (x)))
{
@@ -75,45 +72,68 @@ mpfr_mul_ui (mpfr_ptr y, mpfr_srcptr x, unsigned long int u, mpfr_rnd_t rnd_mode
else if (MPFR_UNLIKELY (IS_POW2 (u)))
return mpfr_mul_2si (y, x, MPFR_INT_CEIL_LOG2 (u), rnd_mode);
- yp = MPFR_MANT (y);
- xn = MPFR_LIMB_SIZE (x);
-
- MPFR_ASSERTD (xn < MP_SIZE_T_MAX);
- MPFR_TMP_MARK(marker);
- yp = MPFR_TMP_LIMBS_ALLOC (xn + 1);
-
- MPFR_ASSERTN (u == (mp_limb_t) u);
- yp[xn] = mpn_mul_1 (yp, MPFR_MANT (x), xn, u);
-
- /* x * u is stored in yp[xn], ..., yp[0] */
-
- /* since the case u=1 was treated above, we have u >= 2, thus
- yp[xn] >= 1 since x was msb-normalized */
- MPFR_ASSERTD (yp[xn] != 0);
- if (MPFR_LIKELY (MPFR_LIMB_MSB (yp[xn]) == 0))
- {
- count_leading_zeros (cnt, yp[xn]);
- mpn_lshift (yp, yp, xn + 1, cnt);
- }
- else
- {
- cnt = 0;
- }
-
- /* now yp[xn], ..., yp[0] is msb-normalized too, and has at most
- PREC(x) + (GMP_NUMB_BITS - cnt) non-zero bits */
- MPFR_RNDRAW (inexact, y, yp, (mpfr_prec_t) (xn + 1) * GMP_NUMB_BITS,
- rnd_mode, MPFR_SIGN (x), cnt -- );
-
- MPFR_TMP_FREE (marker);
-
- cnt = GMP_NUMB_BITS - cnt;
- if (MPFR_UNLIKELY (__gmpfr_emax < MPFR_EMAX_MIN + cnt
- || MPFR_GET_EXP (x) > __gmpfr_emax - cnt))
- return mpfr_overflow (y, rnd_mode, MPFR_SIGN(x));
-
- MPFR_SET_EXP (y, MPFR_GET_EXP (x) + cnt);
- MPFR_SET_SAME_SIGN (y, x);
-
- MPFR_RET (inexact);
+#ifdef MPFR_LONG_WITHIN_LIMB
+ {
+ mp_limb_t *yp;
+ mp_size_t xn;
+ int cnt;
+ MPFR_TMP_DECL (marker);
+
+ yp = MPFR_MANT (y);
+ xn = MPFR_LIMB_SIZE (x);
+
+ MPFR_ASSERTD (xn < MP_SIZE_T_MAX);
+ MPFR_TMP_MARK(marker);
+ yp = MPFR_TMP_LIMBS_ALLOC (xn + 1);
+
+ MPFR_ASSERTN (u == (mp_limb_t) u);
+ yp[xn] = mpn_mul_1 (yp, MPFR_MANT (x), xn, u);
+
+ /* x * u is stored in yp[xn], ..., yp[0] */
+
+ /* since the case u=1 was treated above, we have u >= 2, thus
+ yp[xn] >= 1 since x was msb-normalized */
+ MPFR_ASSERTD (yp[xn] != 0);
+ if (MPFR_LIKELY (MPFR_LIMB_MSB (yp[xn]) == 0))
+ {
+ count_leading_zeros (cnt, yp[xn]);
+ mpn_lshift (yp, yp, xn + 1, cnt);
+ }
+ else
+ {
+ cnt = 0;
+ }
+
+ /* now yp[xn], ..., yp[0] is msb-normalized too, and has at most
+ PREC(x) + (GMP_NUMB_BITS - cnt) non-zero bits */
+ MPFR_RNDRAW (inexact, y, yp, (mpfr_prec_t) (xn + 1) * GMP_NUMB_BITS,
+ rnd_mode, MPFR_SIGN (x), cnt -- );
+
+ MPFR_TMP_FREE (marker);
+
+ cnt = GMP_NUMB_BITS - cnt;
+ if (MPFR_UNLIKELY (__gmpfr_emax < MPFR_EMAX_MIN + cnt
+ || MPFR_GET_EXP (x) > __gmpfr_emax - cnt))
+ return mpfr_overflow (y, rnd_mode, MPFR_SIGN(x));
+
+ MPFR_SET_EXP (y, MPFR_GET_EXP (x) + cnt);
+ MPFR_SET_SAME_SIGN (y, x);
+ MPFR_RET (inexact);
+ }
+#else
+ {
+ mpfr_t uu;
+ MPFR_SAVE_EXPO_DECL (expo);
+
+ mpfr_init2 (uu, sizeof (unsigned long) * CHAR_BIT);
+ /* Warning: u might be outside the current exponent range! */
+ MPFR_SAVE_EXPO_MARK (expo);
+ mpfr_set_ui (uu, u, MPFR_RNDZ);
+ inexact = mpfr_mul (y, x, uu, rnd_mode);
+ mpfr_clear (uu);
+ MPFR_SAVE_EXPO_UPDATE_FLAGS (expo, __gmpfr_flags);
+ MPFR_SAVE_EXPO_FREE (expo);
+ return mpfr_check_range (y, inexact, rnd_mode);
+ }
+#endif /* MPFR_LONG_WITHIN_LIMB */
}