summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorvlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4>2018-08-31 15:40:23 +0000
committervlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4>2018-08-31 15:40:23 +0000
commitabb0374b7f05425910d7e770a85e794c955dad35 (patch)
treecab06313ef73121f5d54bda870a35e2bc0d55405
parent35cdd60fc3d4b87c803afa97ec5318d44d4bd460 (diff)
downloadmpfr-abb0374b7f05425910d7e770a85e794c955dad35.tar.gz
[src/mpfr-impl.h] Define MPFR_LIMB_LSHIFT(x,c) macro to do a left shift,
making sure that the shifted argument is unsigned (needed due to the integer promotion rules when mp_limb_t is defined as an unsigned short). [src/add1.c] Fixed potential undefined behavior with MPFR_LIMB_LSHIFT. git-svn-id: svn://scm.gforge.inria.fr/svn/mpfr/trunk@13101 280ebfd0-de03-0410-8827-d642c229c3f4
-rw-r--r--src/add1.c2
-rw-r--r--src/mpfr-impl.h21
2 files changed, 16 insertions, 7 deletions
diff --git a/src/add1.c b/src/add1.c
index 880c49ccf..f1419f7f1 100644
--- a/src/add1.c
+++ b/src/add1.c
@@ -404,7 +404,7 @@ mpfr_add1 (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode)
if (fb || ck < 0)
goto rounding;
- if (difs && MPFR_LIMB(cprev << (GMP_NUMB_BITS - difs)) != 0)
+ if (difs && MPFR_LIMB_LSHIFT(cprev, GMP_NUMB_BITS - difs) != 0)
{
fb = 1;
goto rounding;
diff --git a/src/mpfr-impl.h b/src/mpfr-impl.h
index 5ea624af1..b24975491 100644
--- a/src/mpfr-impl.h
+++ b/src/mpfr-impl.h
@@ -1173,18 +1173,27 @@ typedef uintmax_t mpfr_ueexp_t;
/* Mask for the low 's' bits of a limb */
#define MPFR_LIMB_MASK(s) ((MPFR_LIMB_ONE << (s)) - MPFR_LIMB_ONE)
-/* Cast to mp_limb_t, assuming that x is based on mp_limb_t variables
- (needed when mp_limb_t is defined as an integer type shorter than
- int, due to the integer promotion rules, which is possible only
+/* MPFR_LIMB: Cast to mp_limb_t, assuming that x is based on mp_limb_t
+ variables (needed when mp_limb_t is defined as an integer type shorter
+ than int, due to the integer promotion rules, which is possible only
if MPFR_LONG_WITHIN_LIMB is not defined). Warning! This will work
only when the computed value x is congruent to the expected value
- modulo MPFR_LIMB_MAX + 1. Be aware that this macro may not solve
- all the problems related to the integer promotion rules, because
- it won't have an influence on the evaluation of x itself. */
+ modulo MPFR_LIMB_MAX + 1. Be aware that this macro may not solve all
+ the problems related to the integer promotion rules, because it won't
+ have an influence on the evaluation of x itself. Hence the need for...
+
+ MPFR_LIMB_LSHIFT: Left shift by making sure that the shifted argument
+ is unsigned (use unsigned long due to the MPFR_LONG_WITHIN_LIMB test).
+ For instance, due to the integer promotion rules, if mp_limb_t is
+ defined as a 16-bit unsigned short and an int has 32 bits, then a
+ mp_limb_t will be converted to an int, which is signed.
+*/
#ifdef MPFR_LONG_WITHIN_LIMB
#define MPFR_LIMB(x) (x)
+#define MPFR_LIMB_LSHIFT(x,c) ((x) << (c))
#else
#define MPFR_LIMB(x) ((mp_limb_t) (x))
+#define MPFR_LIMB_LSHIFT(x,c) MPFR_LIMB((unsigned long) (x) << (c))
#endif
/******************************************************