diff options
author | vlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4> | 2009-12-07 13:23:25 +0000 |
---|---|---|
committer | vlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4> | 2009-12-07 13:23:25 +0000 |
commit | e69c2fb020cd3d27b097904fd5cbe6ce949e7623 (patch) | |
tree | e686423d7378de392758183ae3b6b0bf67559765 /sin_cos.c | |
parent | 88520ac4482da223d3493f8c5de61bc0750afb72 (diff) | |
download | mpfr-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.c | 34 |
1 files changed, 18 insertions, 16 deletions
@@ -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); |