diff options
author | pelissip <pelissip@280ebfd0-de03-0410-8827-d642c229c3f4> | 2004-12-13 10:23:33 +0000 |
---|---|---|
committer | pelissip <pelissip@280ebfd0-de03-0410-8827-d642c229c3f4> | 2004-12-13 10:23:33 +0000 |
commit | 8f9d3fe8c9bf84081592c6bbd1fd732803b3058e (patch) | |
tree | e86799213232d9b21e95b58a2fc0198350548566 /set_q.c | |
parent | b1aa93e0bfa5c39cb4339c2c92e04c07543bc023 (diff) | |
download | mpfr-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.c | 42 |
1 files changed, 26 insertions, 16 deletions
@@ -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); |