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 | |
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
-rw-r--r-- | get_ui.c | 23 | ||||
-rw-r--r-- | tests/tset_si.c | 19 |
2 files changed, 42 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); diff --git a/tests/tset_si.c b/tests/tset_si.c index 6e535470d..342b018d6 100644 --- a/tests/tset_si.c +++ b/tests/tset_si.c @@ -217,6 +217,25 @@ main (int argc, char *argv[]) mpfr_nextabove (x); mpfr_get_ui (x, GMP_RNDU); + /* another test for get_ui */ + mpfr_set_prec (x, 10); + mpfr_set_str_binary (x, "10.101"); + dl = mpfr_get_ui (x, GMP_RNDN); + MPFR_ASSERTN (dl == 3); + + mpfr_set_str_binary (x, "-1.0"); + mpfr_get_ui (x, GMP_RNDN); + + mpfr_set_str_binary (x, "0.1"); + dl = mpfr_get_ui (x, GMP_RNDN); + MPFR_ASSERTN (dl == 0); + dl = mpfr_get_ui (x, GMP_RNDZ); + MPFR_ASSERTN (dl == 0); + dl = mpfr_get_ui (x, GMP_RNDD); + MPFR_ASSERTN (dl == 0); + dl = mpfr_get_ui (x, GMP_RNDU); + MPFR_ASSERTN (dl == 1); + /* coverage tests */ mpfr_set_prec (x, 2); mpfr_set_si (x, -7, GMP_RNDD); |