This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Fix csin, csinh, ccos, ccosh missing underflows (bug 15405)


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]