summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorvlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4>2014-02-11 13:18:00 +0000
committervlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4>2014-02-11 13:18:00 +0000
commitc673d2d6e040cd23cff109af8de8119b13c5ff4a (patch)
tree1a2899eb32019e4924482d9ff6573b7313cf2b7b
parent4a6c79009b04a646bb4e0e7e85991a3cace85c40 (diff)
downloadmpfr-c673d2d6e040cd23cff109af8de8119b13c5ff4a.tar.gz
Start of mpfr_set_exp behavior clean-up.
* src/mpfr-impl.h: updated the MPFR_SET_EXP(x, exp) definition for the MPFR_EXP_CHECK case. There are 2 consequences: 1. The exp expression is evaluated several times (this should be OK with the MPFR code and optimizations). 2. The real value of exp is tested for the assertion, instead of the value converted to mpfr_exp_t. Thus new bugs can be found (e.g. when an unsigned type is used instead of signed). * src/set_exp.c: set the exponent only if x is a non-zero ordinary number, i.e. already has a valid significand and a valid exponent (thus it is no longer a low-level function, and it can no longer generate an invalid value from a valid one). * doc/mpfr.texi: updated mpfr_set_exp description and added an item in the "API Compatibility / Changed Functions" section. Currently 73 tests pass and 96 fail on Linux/x86_64, either due to bugs or due to code not yet updated for this change. git-svn-id: svn://scm.gforge.inria.fr/svn/mpfr/branches/set_exp@8924 280ebfd0-de03-0410-8827-d642c229c3f4
-rw-r--r--doc/mpfr.texi17
-rw-r--r--src/mpfr-impl.h4
-rw-r--r--src/set_exp.c4
3 files changed, 19 insertions, 6 deletions
diff --git a/doc/mpfr.texi b/doc/mpfr.texi
index 771f16989..dc1b5efc6 100644
--- a/doc/mpfr.texi
+++ b/doc/mpfr.texi
@@ -2835,10 +2835,9 @@ infinity or zero is undefined.
@end deftypefun
@deftypefun int mpfr_set_exp (mpfr_t @var{x}, mpfr_exp_t @var{e})
-Set the exponent of @var{x} if @var{e} is in the current exponent range,
-and return 0 (even if @var{x} is not a non-zero ordinary number);
-otherwise, return a non-zero value.
-The significand is assumed to be in [1/2,1).
+Set the exponent of @var{x} to @var{e} if @var{x} is a non-zero ordinary
+number and @var{e} is in the current exponent range, and return 0;
+otherwise, return a non-zero value (@var{x} is not changed).
@end deftypefun
@deftypefun int mpfr_signbit (mpfr_t @var{op})
@@ -3646,6 +3645,16 @@ Note: this function has been renamed to @code{mpfr_get_z_2exp}
in MPFR 3.0, but @code{mpfr_get_z_exp} is still available for
compatibility reasons.
+@item @code{mpfr_set_exp} changed in MPFR 3.2.
+Before MPFR 3.2, the exponent was set whatever the contents of the MPFR
+object in argument. In practice, this could be useful as a low-level
+function when the MPFR number was being constructed by setting the fields
+of its internal structure, but the API does not provide a way to do this
+except by using internals. Thus, for the API, this behavior was useless
+and could quickly lead to undefined behavior due to the fact that the
+generated value could have an invalid format if the MPFR object contained
+a special value (NaN, infinity or zero).
+
@item @code{mpfr_strtofr} changed in MPFR 2.3.1 and MPFR 2.4.
This was actually a bug fix since the code and the documentation did
not match. But both were changed in order to have a more consistent
diff --git a/src/mpfr-impl.h b/src/mpfr-impl.h
index 569bb8336..eee6afae2 100644
--- a/src/mpfr-impl.h
+++ b/src/mpfr-impl.h
@@ -784,7 +784,9 @@ typedef intmax_t mpfr_eexp_t;
#ifdef MPFR_EXP_CHECK
# define MPFR_GET_EXP(x) (mpfr_get_exp) (x)
-# define MPFR_SET_EXP(x, exp) MPFR_ASSERTN (!mpfr_set_exp ((x), (exp)))
+# define MPFR_SET_EXP(x, exp) (MPFR_ASSERTN ((exp) >= __gmpfr_emin && \
+ (exp) <= __gmpfr_emax), \
+ (void) (MPFR_EXP (x) = (exp)))
# define MPFR_SET_INVALID_EXP(x) ((void) (MPFR_EXP (x) = MPFR_EXP_INVALID))
#else
# define MPFR_GET_EXP(x) MPFR_EXP (x)
diff --git a/src/set_exp.c b/src/set_exp.c
index 22322ea32..42defe268 100644
--- a/src/set_exp.c
+++ b/src/set_exp.c
@@ -25,7 +25,9 @@ http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
int
mpfr_set_exp (mpfr_ptr x, mpfr_exp_t exponent)
{
- if (MPFR_LIKELY (exponent >= __gmpfr_emin && exponent <= __gmpfr_emax))
+ if (MPFR_LIKELY (MPFR_IS_PURE_FP (x) &&
+ exponent >= __gmpfr_emin &&
+ exponent <= __gmpfr_emax))
{
MPFR_EXP(x) = exponent; /* do not use MPFR_SET_EXP of course... */
return 0;