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