summaryrefslogtreecommitdiff
path: root/src/rint.c
diff options
context:
space:
mode:
authorvlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4>2015-06-03 00:32:23 +0000
committervlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4>2015-06-03 00:32:23 +0000
commitbcb29ed8bcf0d0375668e43245a902af7cf49014 (patch)
treece48cb857e75f18bbf004b9b0bb871a095fe4878 /src/rint.c
parentf5f1420095191e6e82448cd1ac86666cc77b3421 (diff)
downloadmpfr-bcb29ed8bcf0d0375668e43245a902af7cf49014.tar.gz
[src/rint.c] Simplified and fixed the mpfr_rint_* functions: in some
corner cases, an intermediate overflow would not be propagated. No testcases added for this particular problem since huge precision numbers would be involved. git-svn-id: svn://scm.gforge.inria.fr/svn/mpfr/trunk@9484 280ebfd0-de03-0410-8827-d642c229c3f4
Diffstat (limited to 'src/rint.c')
-rw-r--r--src/rint.c35
1 files changed, 19 insertions, 16 deletions
diff --git a/src/rint.c b/src/rint.c
index 22ee1dc51..d17817a43 100644
--- a/src/rint.c
+++ b/src/rint.c
@@ -333,6 +333,13 @@ mpfr_floor (mpfr_ptr r, mpfr_srcptr u)
return mpfr_rint (r, u, MPFR_RNDD);
}
+/* For the round-to-integer functions below, we don't need to extend the
+ * exponent range. And it is better not to do so, so that we can test
+ * the flag setting for intermediate overflow in the test suite without
+ * involving huge non-integer numbers (thus in huge precision). This
+ * should also be faster.
+ */
+
#undef mpfr_rint_round
int
@@ -344,19 +351,18 @@ mpfr_rint_round (mpfr_ptr r, mpfr_srcptr u, mpfr_rnd_t rnd_mode)
{
mpfr_t tmp;
int inex;
- MPFR_SAVE_EXPO_DECL (expo);
+ mpfr_flags_t saved_flags = __gmpfr_flags;
MPFR_BLOCK_DECL (flags);
- MPFR_SAVE_EXPO_MARK (expo);
mpfr_init2 (tmp, MPFR_PREC (u));
/* round(u) is representable in tmp unless an overflow occurs */
MPFR_BLOCK (flags, mpfr_round (tmp, u));
+ __gmpfr_flags = saved_flags;
inex = (MPFR_OVERFLOW (flags)
? mpfr_overflow (r, rnd_mode, MPFR_SIGN (u))
: mpfr_set (r, tmp, rnd_mode));
mpfr_clear (tmp);
- MPFR_SAVE_EXPO_FREE (expo);
- return mpfr_check_range (r, inex, rnd_mode);
+ return inex;
}
}
@@ -371,16 +377,15 @@ mpfr_rint_trunc (mpfr_ptr r, mpfr_srcptr u, mpfr_rnd_t rnd_mode)
{
mpfr_t tmp;
int inex;
- MPFR_SAVE_EXPO_DECL (expo);
+ mpfr_flags_t saved_flags = __gmpfr_flags;
- MPFR_SAVE_EXPO_MARK (expo);
mpfr_init2 (tmp, MPFR_PREC (u));
/* trunc(u) is always representable in tmp */
mpfr_trunc (tmp, u);
+ __gmpfr_flags = saved_flags;
inex = mpfr_set (r, tmp, rnd_mode);
mpfr_clear (tmp);
- MPFR_SAVE_EXPO_FREE (expo);
- return mpfr_check_range (r, inex, rnd_mode);
+ return inex;
}
}
@@ -395,19 +400,18 @@ mpfr_rint_ceil (mpfr_ptr r, mpfr_srcptr u, mpfr_rnd_t rnd_mode)
{
mpfr_t tmp;
int inex;
- MPFR_SAVE_EXPO_DECL (expo);
+ mpfr_flags_t saved_flags = __gmpfr_flags;
MPFR_BLOCK_DECL (flags);
- MPFR_SAVE_EXPO_MARK (expo);
mpfr_init2 (tmp, MPFR_PREC (u));
/* ceil(u) is representable in tmp unless an overflow occurs */
MPFR_BLOCK (flags, mpfr_ceil (tmp, u));
+ __gmpfr_flags = saved_flags;
inex = (MPFR_OVERFLOW (flags)
? mpfr_overflow (r, rnd_mode, MPFR_SIGN_POS)
: mpfr_set (r, tmp, rnd_mode));
mpfr_clear (tmp);
- MPFR_SAVE_EXPO_FREE (expo);
- return mpfr_check_range (r, inex, rnd_mode);
+ return inex;
}
}
@@ -422,18 +426,17 @@ mpfr_rint_floor (mpfr_ptr r, mpfr_srcptr u, mpfr_rnd_t rnd_mode)
{
mpfr_t tmp;
int inex;
- MPFR_SAVE_EXPO_DECL (expo);
+ mpfr_flags_t saved_flags = __gmpfr_flags;
MPFR_BLOCK_DECL (flags);
- MPFR_SAVE_EXPO_MARK (expo);
mpfr_init2 (tmp, MPFR_PREC (u));
/* floor(u) is representable in tmp unless an overflow occurs */
MPFR_BLOCK (flags, mpfr_floor (tmp, u));
+ __gmpfr_flags = saved_flags;
inex = (MPFR_OVERFLOW (flags)
? mpfr_overflow (r, rnd_mode, MPFR_SIGN_NEG)
: mpfr_set (r, tmp, rnd_mode));
mpfr_clear (tmp);
- MPFR_SAVE_EXPO_FREE (expo);
- return mpfr_check_range (r, inex, rnd_mode);
+ return inex;
}
}