diff options
author | vlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4> | 2018-08-31 15:40:23 +0000 |
---|---|---|
committer | vlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4> | 2018-08-31 15:40:23 +0000 |
commit | abb0374b7f05425910d7e770a85e794c955dad35 (patch) | |
tree | cab06313ef73121f5d54bda870a35e2bc0d55405 | |
parent | 35cdd60fc3d4b87c803afa97ec5318d44d4bd460 (diff) | |
download | mpfr-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.c | 2 | ||||
-rw-r--r-- | src/mpfr-impl.h | 21 |
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 /****************************************************** |