summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorzimmerma <zimmerma@280ebfd0-de03-0410-8827-d642c229c3f4>2017-12-18 08:51:06 +0000
committerzimmerma <zimmerma@280ebfd0-de03-0410-8827-d642c229c3f4>2017-12-18 08:51:06 +0000
commit974825f8f3023a6d9e5c75d6010000064dc2672e (patch)
tree9b9989f9c9df406eddcf41fd04fa3fffb6ab97ed /src
parentaf989821960f0e6d15d015480406301174b6dd03 (diff)
downloadmpfr-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.c19
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)))