summaryrefslogtreecommitdiff
path: root/tan.c
diff options
context:
space:
mode:
authorpelissip <pelissip@280ebfd0-de03-0410-8827-d642c229c3f4>2005-02-15 10:06:39 +0000
committerpelissip <pelissip@280ebfd0-de03-0410-8827-d642c229c3f4>2005-02-15 10:06:39 +0000
commitf33368472babca56d40bdc5378f10fe71c341259 (patch)
treed00fc1fcb7df587feac0a7963982667c1279b359 /tan.c
parent24503ac68ee4f62422256794efda10983e1c8962 (diff)
downloadmpfr-f33368472babca56d40bdc5378f10fe71c341259.tar.gz
Fix bug of overflow in tan.
git-svn-id: svn://scm.gforge.inria.fr/svn/mpfr/trunk@3314 280ebfd0-de03-0410-8827-d642c229c3f4
Diffstat (limited to 'tan.c')
-rw-r--r--tan.c14
1 files changed, 11 insertions, 3 deletions
diff --git a/tan.c b/tan.c
index 1287881f4..0e4486c16 100644
--- a/tan.c
+++ b/tan.c
@@ -29,6 +29,7 @@ mpfr_tan (mpfr_ptr y, mpfr_srcptr x, mp_rnd_t rnd_mode)
int precy, m, inexact;
mpfr_t s, c;
MPFR_ZIV_DECL (loop);
+ MPFR_SAVE_EXPO_DECL (expo);
MPFR_LOG_FUNC (("x[%#R]=%R rnd=%d", x, x, rnd_mode),
("y[%#R]=%R inexact=%d", y, y, inexact));
@@ -49,6 +50,9 @@ mpfr_tan (mpfr_ptr y, mpfr_srcptr x, mp_rnd_t rnd_mode)
}
}
+ MPFR_SAVE_EXPO_MARK (expo);
+
+ /* Compute initial precision */
precy = MPFR_PREC (y);
m = precy + MPFR_INT_CEIL_LOG2 (precy) + 13;
if (MPFR_GET_EXP (x) > 0)
@@ -62,10 +66,13 @@ mpfr_tan (mpfr_ptr y, mpfr_srcptr x, mp_rnd_t rnd_mode)
MPFR_ZIV_INIT (loop, m);
for (;;)
{
+ /* The only way to get an overflow is to get ~ Pi/2
+ But the result will be ~ 2^Prec(y). */
mpfr_sin_cos (s, c, x, GMP_RNDN); /* err <= 1/2 ulp on s and c */
mpfr_div (c, s, c, GMP_RNDN); /* err <= 2 ulps */
- if (MPFR_IS_INF(x) || mpfr_can_round (c, m - 1, GMP_RNDN, GMP_RNDZ,
- precy + (rnd_mode == GMP_RNDN)))
+ MPFR_ASSERTD (!MPFR_IS_SINGULAR (c));
+ if (MPFR_LIKELY (mpfr_can_round (c, m - 1, GMP_RNDN, GMP_RNDZ,
+ precy + (rnd_mode == GMP_RNDN))))
break;
MPFR_ZIV_NEXT (loop, m);
mpfr_set_prec (s, m);
@@ -78,5 +85,6 @@ mpfr_tan (mpfr_ptr y, mpfr_srcptr x, mp_rnd_t rnd_mode)
mpfr_clear (s);
mpfr_clear (c);
- return inexact;
+ MPFR_SAVE_EXPO_FREE (expo);
+ return mpfr_check_range (y, inexact, rnd_mode);
}