summaryrefslogtreecommitdiff
path: root/get_ui.c
diff options
context:
space:
mode:
authorzimmerma <zimmerma@280ebfd0-de03-0410-8827-d642c229c3f4>2004-09-24 07:21:04 +0000
committerzimmerma <zimmerma@280ebfd0-de03-0410-8827-d642c229c3f4>2004-09-24 07:21:04 +0000
commit981cb1a2a30b2fb2844a14e1b39481cda22cce2c (patch)
tree2be64812cd8dd271df7489c1a87b3fb5521dd10e /get_ui.c
parent6db21a0ff4f08decd754aba972713ba0d96f2745 (diff)
downloadmpfr-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.c23
1 files changed, 23 insertions, 0 deletions
diff --git a/get_ui.c b/get_ui.c
index 4ed644dae..b926c03d0 100644
--- a/get_ui.c
+++ b/get_ui.c
@@ -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);