diff options
author | zimmerma <zimmerma@280ebfd0-de03-0410-8827-d642c229c3f4> | 2004-09-24 07:21:04 +0000 |
---|---|---|
committer | zimmerma <zimmerma@280ebfd0-de03-0410-8827-d642c229c3f4> | 2004-09-24 07:21:04 +0000 |
commit | 981cb1a2a30b2fb2844a14e1b39481cda22cce2c (patch) | |
tree | 2be64812cd8dd271df7489c1a87b3fb5521dd10e /get_ui.c | |
parent | 6db21a0ff4f08decd754aba972713ba0d96f2745 (diff) | |
download | mpfr-981cb1a2a30b2fb2844a14e1b39481cda22cce2c.tar.gz |
fixed double-rounding bug in get_ui
git-svn-id: svn://scm.gforge.inria.fr/svn/mpfr/trunk@2986 280ebfd0-de03-0410-8827-d642c229c3f4
Diffstat (limited to 'get_ui.c')
-rw-r--r-- | get_ui.c | 23 |
1 files changed, 23 insertions, 0 deletions
@@ -34,9 +34,32 @@ mpfr_get_ui (mpfr_srcptr f, mp_rnd_t rnd) if (!mpfr_fits_ulong_p (f, rnd) || MPFR_IS_ZERO(f)) return (unsigned long) 0; + /* now 0 <= f and either f <= ULONG_MAX or + round(f, prec(ULONG_MAX), rnd) <= ULONG_MAX */ + + exp = MPFR_EXP(f); + if (exp <= 0) /* 0 < f < 1 */ + { + /* return 0 for round to zero or -infinity, + 1 for round to +infinity, + and for round to nearest: + 0 if f <= 1/2 (even rule) + 1 otherwise */ + return (rnd == GMP_RNDZ || rnd == GMP_RNDD) ? 0 + : ((rnd == GMP_RNDU) ? 1 + : (mpfr_cmp_ui_2exp (f, 1, -1) <= 0 ? 0 : 1)); + } + + /* now exp > 0 */ + /* determine prec of unsigned long */ for (s = ULONG_MAX, prec = 0; s != 0; s /= 2, prec ++); + /* since f < 2^EXP(f), we need at most min(prec,EXP(f)) bits */ + prec = (exp < prec) ? exp : prec; + if (prec < MPFR_PREC_MIN) + prec = MPFR_PREC_MIN; + /* first round to prec bits */ mpfr_init2 (x, prec); mpfr_set (x, f, rnd); |