summaryrefslogtreecommitdiff
path: root/src/get_si.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/get_si.c')
-rw-r--r--src/get_si.c15
1 files changed, 13 insertions, 2 deletions
diff --git a/src/get_si.c b/src/get_si.c
index 134874c30..3afad5839 100644
--- a/src/get_si.c
+++ b/src/get_si.c
@@ -28,6 +28,7 @@ mpfr_get_si (mpfr_srcptr f, mpfr_rnd_t rnd)
mpfr_prec_t prec;
long s;
mpfr_t x;
+ MPFR_SAVE_EXPO_DECL (expo);
if (MPFR_UNLIKELY (!mpfr_fits_slong_p (f, rnd)))
{
@@ -39,14 +40,22 @@ mpfr_get_si (mpfr_srcptr f, mpfr_rnd_t rnd)
if (MPFR_IS_ZERO (f))
return (long) 0;
- /* determine prec of long */
- for (s = LONG_MIN, prec = 0; s != 0; s /= 2, prec++)
+ /* Determine the precision of long. |LONG_MIN| may have one more bit
+ as an integer, but in this case, this is a power of 2, thus fits
+ in a precision-prec floating-point number. */
+ for (s = LONG_MAX, prec = 0; s != 0; s /= 2, prec++)
{ }
+ MPFR_SAVE_EXPO_MARK (expo);
+
/* first round to prec bits */
mpfr_init2 (x, prec);
mpfr_rint (x, f, rnd);
+ /* The flags from mpfr_rint are the wanted ones. In particular,
+ it sets the inexact flag when necessary. */
+ MPFR_SAVE_EXPO_UPDATE_FLAGS (expo, __gmpfr_flags);
+
/* warning: if x=0, taking its exponent is illegal */
if (MPFR_UNLIKELY (MPFR_IS_ZERO(x)))
s = 0;
@@ -65,5 +74,7 @@ mpfr_get_si (mpfr_srcptr f, mpfr_rnd_t rnd)
mpfr_clear (x);
+ MPFR_SAVE_EXPO_FREE (expo);
+
return s;
}