diff options
author | zimmerma <zimmerma@280ebfd0-de03-0410-8827-d642c229c3f4> | 2017-12-18 08:51:06 +0000 |
---|---|---|
committer | zimmerma <zimmerma@280ebfd0-de03-0410-8827-d642c229c3f4> | 2017-12-18 08:51:06 +0000 |
commit | 974825f8f3023a6d9e5c75d6010000064dc2672e (patch) | |
tree | 9b9989f9c9df406eddcf41fd04fa3fffb6ab97ed /src | |
parent | af989821960f0e6d15d015480406301174b6dd03 (diff) | |
download | mpfr-974825f8f3023a6d9e5c75d6010000064dc2672e.tar.gz |
[tests/ttanh.c] added test for bug in mpfr_tanh
[doc/algorithms.tex] fixed error analysis for mpfr_tanh
[src/tanh.c] fixed error analysis
Note after r12016: Even though mpfr_tanh was incorrect, the failure
of the test added in ttanh.c was actually *only* due to a bug in the
mpfr_div code specific to the trunk (fixed in r12002), i.e. this was
not a non-regression test for the mpfr_tanh bug itself (in particular,
this test does not introduce a failure in the 3.1 branch, which still
has the same incorrect mpfr_tanh code but a correct mpfr_div).
git-svn-id: svn://scm.gforge.inria.fr/svn/mpfr/trunk@11993 280ebfd0-de03-0410-8827-d642c229c3f4
Diffstat (limited to 'src')
-rw-r--r-- | src/tanh.c | 19 |
1 files changed, 13 insertions, 6 deletions
diff --git a/src/tanh.c b/src/tanh.c index 06adf7874..e731f2623 100644 --- a/src/tanh.c +++ b/src/tanh.c @@ -98,13 +98,20 @@ mpfr_tanh (mpfr_ptr y, mpfr_srcptr xt , mpfr_rnd_t rnd_mode) if (MPFR_GET_EXP (x) < 0) Nt += -MPFR_GET_EXP (x); + /* The error analysis in algorithms.tex assumes that x is exactly + representable with working precision Nt. + FIXME: adapt the error analysis for the case Nt < PREC(x). */ + if (Nt < MPFR_PREC(x)) + Nt = MPFR_PREC(x); + /* initialize of intermediary variable */ MPFR_GROUP_INIT_2 (group, Nt, t, te); MPFR_ZIV_INIT (loop, Nt); for (;;) { /* tanh = (exp(2x)-1)/(exp(2x)+1) */ - mpfr_mul_2ui (te, x, 1, MPFR_RNDN); /* 2x */ + inexact = mpfr_mul_2ui (te, x, 1, MPFR_RNDN); /* 2x */ + MPFR_ASSERTD(inexact == 0); /* see FIXME above */ /* since x > 0, we can only have an overflow */ mpfr_exp (te, te, MPFR_RNDN); /* exp(2x) */ if (MPFR_UNLIKELY (MPFR_IS_INF (te))) { @@ -119,13 +126,13 @@ mpfr_tanh (mpfr_ptr y, mpfr_srcptr xt , mpfr_rnd_t rnd_mode) break; } d = MPFR_GET_EXP (te); /* For Error calculation */ - mpfr_add_ui (t, te, 1, MPFR_RNDD); /* exp(2x) + 1*/ - mpfr_sub_ui (te, te, 1, MPFR_RNDU); /* exp(2x) - 1*/ + mpfr_add_ui (t, te, 1, MPFR_RNDD); /* exp(2x) + 1 */ + mpfr_sub_ui (te, te, 1, MPFR_RNDU); /* exp(2x) - 1 */ d = d - MPFR_GET_EXP (te); - mpfr_div (t, te, t, MPFR_RNDN); /* (exp(2x)-1)/(exp(2x)+1)*/ + mpfr_div (t, te, t, MPFR_RNDN); /* (exp(2x)-1)/(exp(2x)+1) */ - /* Calculation of the error */ - d = MAX(3, d + 1); + /* Calculation of the error, see algorithms.tex */ + d = MAX(4, d + 2); err = Nt - (d + 1); if (MPFR_LIKELY ((d <= Nt / 2) && MPFR_CAN_ROUND (t, err, Ny, rnd_mode))) |