summaryrefslogtreecommitdiff
path: root/sin_cos.c
diff options
context:
space:
mode:
authorvlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4>2009-12-07 13:23:25 +0000
committervlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4>2009-12-07 13:23:25 +0000
commite69c2fb020cd3d27b097904fd5cbe6ce949e7623 (patch)
treee686423d7378de392758183ae3b6b0bf67559765 /sin_cos.c
parent88520ac4482da223d3493f8c5de61bc0750afb72 (diff)
downloadmpfr-e69c2fb020cd3d27b097904fd5cbe6ce949e7623.tar.gz
sin_cos.c, tsin_cos.c: ported patch and tests from the trunk.
More precisely: * tsin_cos.c: more testing, in particular in the underflow case. * sin_cos.c: in case of tiny inputs, keep the flags. In practice, this fixes the following bug in mpfr_sin_cos (shown by the improved tsin_cos.c): if emin is the minimum exponent (MPFR_EMIN_MIN), the absolute value of the input is the minimum positive number and the rounding mode is toward 0 (or equivalent), then the underflow flag is dropped. The other exception cases (e.g., in case of reduced exponent range) are handled by mpfr_check_range(). git-svn-id: svn://scm.gforge.inria.fr/svn/mpfr/branches/2.4@6629 280ebfd0-de03-0410-8827-d642c229c3f4
Diffstat (limited to 'sin_cos.c')
-rw-r--r--sin_cos.c34
1 files changed, 18 insertions, 16 deletions
diff --git a/sin_cos.c b/sin_cos.c
index ab3ea41b7..d4ec34989 100644
--- a/sin_cos.c
+++ b/sin_cos.c
@@ -82,17 +82,19 @@ mpfr_sin_cos (mpfr_ptr y, mpfr_ptr z, mpfr_srcptr x, mp_rnd_t rnd_mode)
if (y != x)
/* y and x differ, thus we can safely try to compute y first */
{
- MPFR_FAST_COMPUTE_IF_SMALL_INPUT (y, x, -2 * expx, 2, 0, rnd_mode,
- { inexy = _inexact;
- goto small_input; });
+ MPFR_FAST_COMPUTE_IF_SMALL_INPUT (
+ y, x, -2 * expx, 2, 0, rnd_mode,
+ { inexy = _inexact;
+ goto small_input; });
if (0)
{
small_input:
/* we can go here only if we can round sin(x) */
- MPFR_FAST_COMPUTE_IF_SMALL_INPUT (z, __gmpfr_one, -2 * expx,
- 1, 0, rnd_mode,
- { inexz = _inexact;
- goto end; });
+ MPFR_FAST_COMPUTE_IF_SMALL_INPUT (
+ z, __gmpfr_one, -2 * expx, 1, 0, rnd_mode,
+ { inexz = _inexact;
+ MPFR_SAVE_EXPO_UPDATE_FLAGS (expo, __gmpfr_flags);
+ goto end; });
}
/* if we go here, one of the two MPFR_FAST_COMPUTE_IF_SMALL_INPUT
@@ -101,18 +103,19 @@ mpfr_sin_cos (mpfr_ptr y, mpfr_ptr z, mpfr_srcptr x, mp_rnd_t rnd_mode)
else /* y and x are the same variable: try to compute z first, which
necessarily differs */
{
- MPFR_FAST_COMPUTE_IF_SMALL_INPUT (z, __gmpfr_one, -2 * expx,
- 1, 0, rnd_mode,
- { inexz = _inexact;
- goto small_input2; });
+ MPFR_FAST_COMPUTE_IF_SMALL_INPUT (
+ z, __gmpfr_one, -2 * expx, 1, 0, rnd_mode,
+ { inexz = _inexact;
+ goto small_input2; });
if (0)
{
small_input2:
/* we can go here only if we can round cos(x) */
- MPFR_FAST_COMPUTE_IF_SMALL_INPUT (y, x, -2 * expx, 2, 0,
- rnd_mode,
- { inexy = _inexact;
- goto end; });
+ MPFR_FAST_COMPUTE_IF_SMALL_INPUT (
+ y, x, -2 * expx, 2, 0, rnd_mode,
+ { inexy = _inexact;
+ MPFR_SAVE_EXPO_UPDATE_FLAGS (expo, __gmpfr_flags);
+ goto end; });
}
}
m += 2 * (-expx);
@@ -207,7 +210,6 @@ mpfr_sin_cos (mpfr_ptr y, mpfr_ptr z, mpfr_srcptr x, mp_rnd_t rnd_mode)
mpfr_clear (xr);
end:
- /* FIXME: update the underflow flag if need be. */
MPFR_SAVE_EXPO_FREE (expo);
mpfr_check_range (y, inexy, rnd_mode);
mpfr_check_range (z, inexz, rnd_mode);