From 95bb49821598e92e05ebbbd6acea6fb9ffaa5b44 Mon Sep 17 00:00:00 2001 From: "Andrew J. Schorr" Date: Mon, 1 Aug 2016 13:31:13 -0400 Subject: Fix MPFR bug where precision was reduced to that of the function argument. --- mpfr.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'mpfr.c') diff --git a/mpfr.c b/mpfr.c index 9b9e538e..0f602898 100644 --- a/mpfr.c +++ b/mpfr.c @@ -39,6 +39,8 @@ mpz_t MFNR; bool do_ieee_fmt; /* IEEE-754 floating-point emulation */ mpfr_rnd_t ROUND_MODE; +static mpfr_prec_t default_prec; + static mpfr_rnd_t get_rnd_mode(const char rmode); static NODE *mpg_force_number(NODE *n); static NODE *mpg_make_number(double); @@ -70,7 +72,7 @@ static inline mpfr_ptr mpg_tofloat(mpfr_ptr mf, mpz_ptr mz); void init_mpfr(mpfr_prec_t prec, const char *rmode) { - mpfr_set_default_prec(prec); + mpfr_set_default_prec(default_prec = prec); ROUND_MODE = get_rnd_mode(rmode[0]); mpfr_set_default_rounding_mode(ROUND_MODE); make_number = mpg_make_number; @@ -561,7 +563,7 @@ set_PREC() } if (prec > 0) - mpfr_set_default_prec(prec); + mpfr_set_default_prec(default_prec = prec); } @@ -705,6 +707,7 @@ do_mpfr_func(const char *name, NODE *t1, *res; mpfr_ptr p1; int tval; + mpfr_prec_t argprec; t1 = POP_SCALAR(); if (do_lint && (t1->flags & (NUMCUR|NUMBER)) == 0) @@ -713,7 +716,8 @@ do_mpfr_func(const char *name, force_number(t1); p1 = MP_FLOAT(t1); res = mpg_float(); - mpfr_set_prec(res->mpg_numbr, mpfr_get_prec(p1)); /* needed at least for sqrt() */ + if ((argprec = mpfr_get_prec(p1)) > default_prec) + mpfr_set_prec(res->mpg_numbr, argprec); /* needed at least for sqrt() */ tval = mpfr_func(res->mpg_numbr, p1, ROUND_MODE); IEEE_FMT(res->mpg_numbr, tval); DEREF(t1); -- cgit v1.2.3 From 8518cb47f8315ea04290278e47cd44036edeaf35 Mon Sep 17 00:00:00 2001 From: "Andrew J. Schorr" Date: Mon, 1 Aug 2016 15:15:41 -0400 Subject: Minor MPFR fix to avoid potential hysteresis effects resulting in higher-than-needed precision. --- mpfr.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'mpfr.c') diff --git a/mpfr.c b/mpfr.c index 0f602898..db2eb697 100644 --- a/mpfr.c +++ b/mpfr.c @@ -1218,9 +1218,17 @@ mpg_tofloat(mpfr_ptr mf, mpz_ptr mz) prec -= (size_t) mpz_scan1(mz, 0); /* least significant 1 bit index starting at 0 */ if (prec > MPFR_PREC_MAX) prec = MPFR_PREC_MAX; - if (prec > PRECISION_MIN) - mpfr_set_prec(mf, prec); + else if (prec < PRECISION_MIN) + prec = PRECISION_MIN; } + else + prec = PRECISION_MIN; + /* + * Always set the precision to avoid hysteresis, since do_mpfr_func + * may copy our precision. + */ + if (prec != mpfr_get_prec(mf)) + mpfr_set_prec(mf, prec); mpfr_set_z(mf, mz, ROUND_MODE); return mf; -- cgit v1.2.3