Fix csin, csinh, ccos, ccosh missing underflows (bug 15405)
Andreas Jaeger
aj@suse.com
Fri Apr 26 19:15:00 GMT 2013
On 04/26/2013 05:48 PM, Joseph S. Myers wrote:
> Bug 15405 is missing underflow exceptions from csin, csinh, ccos and
> ccosh when one or both parts of the result underflow but this does not
> raise the underflow flag because the calculation that produced the
> tiny result was an exact multiplication (although the exact
> mathematical result is not exactly representable). This patch fixes
> the missing exceptions in the same way they were fixed for cexp (bug
> 14478). (ccos is implemented in terms of ccosh so doesn't need a
> separate fix.)
>
> Tested x86_64 and x86 (no ulps changes needed).
>
> 2013-04-26 Joseph Myers <joseph@codesourcery.com>
>
> [BZ #15405]
> * math/s_ccosh.c (__ccosh): Ensure underflow exception occurs for
> underflowed result.
> * math/s_ccoshf.c (__ccoshf): Likewise.
> * math/s_ccoshl.c (__ccoshl): Likewise.
> * math/s_csin.c (__csin): Likewise.
> * math/s_csinf.c (__csinf): Likewise.
> * math/s_csinh.c (__csinh): Likewise.
> * math/s_csinhf.c (__csinhf): Likewise.
> * math/s_csinhl.c (__csinhl): Likewise.
> * math/s_csinl.c (__csinl): Likewise.
> * math/libm-test.inc (ccos_test): Add more tests.
> (ccosh_test): Likewise.
> (csin_test): Likewise.
> (csinh_test): Likewise.
>
> diff --git a/math/libm-test.inc b/math/libm-test.inc
> index eb9fa71..a3d7731 100644
> --- a/math/libm-test.inc
> +++ b/math/libm-test.inc
> @@ -4570,6 +4570,9 @@ ccos_test (void)
> TEST_c_c (ccos, 0x1p-16434L, 22730, plus_infty, -1.217853148905605987081057582351152052687e4924L, OVERFLOW_EXCEPTION);
> #endif
>
> + TEST_c_c (ccos, min_subnorm_value * 0x1p120, 0x1p-120, 1.0, -min_subnorm_value, UNDERFLOW_EXCEPTION);
> + TEST_c_c (ccos, 0x1p-120, min_subnorm_value * 0x1p120, 1.0, -min_subnorm_value, UNDERFLOW_EXCEPTION);
> +
> END (ccos, complex);
> }
>
> @@ -4670,6 +4673,9 @@ ccosh_test (void)
> TEST_c_c (ccosh, 22730, 0x1p-16434L, plus_infty, 1.217853148905605987081057582351152052687e4924L, OVERFLOW_EXCEPTION);
> #endif
>
> + TEST_c_c (ccosh, min_subnorm_value * 0x1p120, 0x1p-120, 1.0, min_subnorm_value, UNDERFLOW_EXCEPTION);
> + TEST_c_c (ccosh, 0x1p-120, min_subnorm_value * 0x1p120, 1.0, min_subnorm_value, UNDERFLOW_EXCEPTION);
> +
> END (ccosh, complex);
> }
>
> @@ -5898,6 +5904,9 @@ csin_test (void)
> TEST_c_c (csin, 0x1p-16434L, 22730, 1.217853148905605987081057582351152052687e4924L, plus_infty, OVERFLOW_EXCEPTION);
> #endif
>
> + TEST_c_c (csin, min_subnorm_value, min_value, min_subnorm_value, min_value, UNDERFLOW_EXCEPTION);
> + TEST_c_c (csin, min_value, min_subnorm_value, min_value, min_subnorm_value, UNDERFLOW_EXCEPTION);
> +
> END (csin, complex);
> }
>
> @@ -5997,6 +6006,9 @@ csinh_test (void)
> TEST_c_c (csinh, 22730, 0x1p-16434L, plus_infty, 1.217853148905605987081057582351152052687e4924L, OVERFLOW_EXCEPTION);
> #endif
>
> + TEST_c_c (csinh, min_subnorm_value, min_value, min_subnorm_value, min_value, UNDERFLOW_EXCEPTION);
> + TEST_c_c (csinh, min_value, min_subnorm_value, min_value, min_subnorm_value, UNDERFLOW_EXCEPTION);
> +
> END (csinh, complex);
> }
>
> diff --git a/math/s_ccosh.c b/math/s_ccosh.c
> index 2c05b63..05b146e 100644
> --- a/math/s_ccosh.c
> +++ b/math/s_ccosh.c
> @@ -82,6 +82,19 @@ __ccosh (__complex__ double x)
> __real__ retval = __ieee754_cosh (__real__ x) * cosix;
> __imag__ retval = __ieee754_sinh (__real__ x) * sinix;
> }
> +
> + if (fabs (__real__ retval) < DBL_MIN)
> + {
> + volatile double force_underflow
> + = __real__ retval * __real__ retval;
> + (void) force_underflow;
> + }
> + if (fabs (__imag__ retval) < DBL_MIN)
> + {
> + volatile double force_underflow
> + = __imag__ retval * __imag__ retval;
> + (void) force_underflow;
> + }
Couldn't this be an else if? I expect we only need to raise underflow
once if both are underflowing, aren't we?
Otherwise fine,
Andreas
--
Andreas Jaeger aj@{suse.com,opensuse.org} Twitter/Identica: jaegerandi
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Jeff Hawn,Jennifer Guild,Felix Imendörffer,HRB16746 (AG Nürnberg)
GPG fingerprint = 93A3 365E CE47 B889 DF7F FED1 389A 563C C272 A126
More information about the Libc-alpha
mailing list