summaryrefslogtreecommitdiff
path: root/src/fits_u.h
diff options
context:
space:
mode:
authorvlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4>2013-09-26 10:47:05 +0000
committervlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4>2013-09-26 10:47:05 +0000
commitd4aa7f855bd5ddc690797b5c8067dfbe4bded673 (patch)
treef15fe1dc2f5ee61c31f458fd22e1d3101676b657 /src/fits_u.h
parent2856faa64801ec5c1a32f828ee2fa8652e60dcc2 (diff)
downloadmpfr-d4aa7f855bd5ddc690797b5c8067dfbe4bded673.tar.gz
[src/{fits_u.h,fits_uintmax.c}] Fixed the mpfr_fits_u*_p functions,
which incorrectly returned 0 ("doesn't fit") on negative arguments when the rounding to an integer was 0. The fits_uintmax.c file now uses fits_u.h for consistency. [tests/tfits.c] Added tests, in particular for small negative op (triggering the above bug) and in non-RNDN rounding modes. (merged changesets r8494,8501-8503 from the trunk) git-svn-id: svn://scm.gforge.inria.fr/svn/mpfr/branches/3.1@8684 280ebfd0-de03-0410-8827-d642c229c3f4
Diffstat (limited to 'src/fits_u.h')
-rw-r--r--src/fits_u.h19
1 files changed, 11 insertions, 8 deletions
diff --git a/src/fits_u.h b/src/fits_u.h
index e4bd6a024..fe4de05c1 100644
--- a/src/fits_u.h
+++ b/src/fits_u.h
@@ -32,17 +32,20 @@ FUNCTION (mpfr_srcptr f, mpfr_rnd_t rnd)
int res;
if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (f)))
- /* Zero always fit */
- return MPFR_IS_ZERO (f) ? 1 : 0;
- else if (MPFR_IS_NEG (f))
- /* Negative numbers don't fit */
- return 0;
- /* now it fits if
- (a) f <= MAXIMUM
- (b) round(f, prec(slong), rnd) <= MAXIMUM */
+ return MPFR_IS_ZERO (f) ? 1 : 0; /* Zero always fits */
e = MPFR_GET_EXP (f);
+ if (MPFR_IS_NEG (f))
+ return e >= 1 ? 0 /* f <= -1 does not fit */
+ : rnd != MPFR_RNDN ? MPFR_IS_LIKE_RNDU (rnd, -1) /* directed mode */
+ : e < 0 ? 1 /* f > -1/2 fits in MPFR_RNDN */
+ : mpfr_powerof2_raw(f); /* -1/2 fits, -1 < f < -1/2 don't */
+
+ /* Now it fits if
+ (a) f <= MAXIMUM
+ (b) round(f, prec(slong), rnd) <= MAXIMUM */
+
/* first compute prec(MAXIMUM); fits in an int */
for (s = MAXIMUM, prec = 0; s != 0; s /= 2, prec ++);