summaryrefslogtreecommitdiff
path: root/set_q.c
diff options
context:
space:
mode:
authorpelissip <pelissip@280ebfd0-de03-0410-8827-d642c229c3f4>2004-12-13 10:23:33 +0000
committerpelissip <pelissip@280ebfd0-de03-0410-8827-d642c229c3f4>2004-12-13 10:23:33 +0000
commit8f9d3fe8c9bf84081592c6bbd1fd732803b3058e (patch)
treee86799213232d9b21e95b58a2fc0198350548566 /set_q.c
parentb1aa93e0bfa5c39cb4339c2c92e04c07543bc023 (diff)
downloadmpfr-8f9d3fe8c9bf84081592c6bbd1fd732803b3058e.tar.gz
Update mpfr_set_q overflow problem.
git-svn-id: svn://scm.gforge.inria.fr/svn/mpfr/trunk@3132 280ebfd0-de03-0410-8827-d642c229c3f4
Diffstat (limited to 'set_q.c')
-rw-r--r--set_q.c42
1 files changed, 26 insertions, 16 deletions
diff --git a/set_q.c b/set_q.c
index 477e1bf37..75945f5ea 100644
--- a/set_q.c
+++ b/set_q.c
@@ -29,35 +29,45 @@ mpfr_set_q (mpfr_ptr f, mpq_srcptr q, mp_rnd_t rnd)
mpz_srcptr num, den;
mpfr_t n, d;
int inexact;
- mp_prec_t prec;
+ mp_prec_t pnum, pden;
MPFR_SAVE_EXPO_DECL (expo);
- MPFR_CLEAR_FLAGS (f);
num = mpq_numref (q);
- if (mpz_cmp_ui (num, 0) == 0)
+ if (MPFR_UNLIKELY (mpz_sgn (num) == 0))
{
MPFR_SET_ZERO (f);
MPFR_SET_POS (f);
MPFR_RET (0);
}
-
den = mpq_denref (q);
+ pnum = mpz_sizeinbase (num, 2);
+ pden = mpz_sizeinbase (den, 2);
+
+ /* Check for underflow */
+ if (MPFR_UNLIKELY ((mp_exp_t) pnum - (mp_exp_t) pden+1 <= __gmpfr_emin - 1))
+ {
+ if (rnd == GMP_RNDN
+ && ((mp_exp_t) pnum-pden+1 <= __gmpfr_emin - 2
+ || mpq_cmp_si (q, 1, __gmpfr_emin - 2) <= 0))
+ rnd = GMP_RNDZ;
+ return mpfr_set_underflow (f, rnd, mpq_sgn (q));
+ }
+
+ if (MPFR_UNLIKELY (pnum < MPFR_PREC_MIN))
+ pnum = MPFR_PREC_MIN;
+ if (MPFR_UNLIKELY (pden < MPFR_PREC_MIN))
+ pden = MPFR_PREC_MIN;
+
MPFR_SAVE_EXPO_MARK (expo);
- prec = mpz_sizeinbase (num, 2);
- if (prec < MPFR_PREC_MIN)
- prec = MPFR_PREC_MIN;
- mpfr_init2 (n, prec);
+ mpfr_init2 (n, pnum);
inexact = mpfr_set_z (n, num, GMP_RNDZ);
- MPFR_ASSERTD (inexact == 0);
- /* result is exact: overflow cannot occur since emax = prec */
+ MPFR_ASSERTN (inexact == 0);
+ /* result is exact: overflow can occur but we can't handle it */
- prec = mpz_sizeinbase (den, 2);
- if (prec < MPFR_PREC_MIN)
- prec = MPFR_PREC_MIN;
- mpfr_init2 (d, prec);
+ mpfr_init2 (d, pden);
inexact = mpfr_set_z (d, den, GMP_RNDZ);
- MPFR_ASSERTD (inexact == 0);
- /* result is exact: overflow cannot occur, as above */
+ MPFR_ASSERTN (inexact == 0);
+ /* result is exact: overflow can occur but we can't handle it */
inexact = mpfr_div (f, n, d, rnd);
mpfr_clear (n);