Fix sign of zero part from ctan / ctanh when argument infinite (bug 17118).

C99/C11 Annex G specifies the sign of the zero part of the result of
ctan (x +/- i * Inf) and ctanh (+/-Inf + i * y).  This patch fixes glibc
to follow that specification, along the lines I described in my review
of Andreas's previous patch for this issue
<https://sourceware.org/ml/libc-alpha/2014-08/msg00142.html>.

Tested for x86_64.

2015-09-17  Joseph Myers  <joseph@codesourcery.com>
	    Andreas Schwab  <schwab@suse.de>

	[BZ #17118]
	* math/s_ctan.c (__ctan): Determine sign of zero real part of
	result when imaginary part of argument is infinite using sine and
	cosine.
	* math/s_ctanf.c (__ctanf): Likewise.
	* math/s_ctanl.c (__ctanl): Likewise.
	* math/s_ctanh.c (__ctanh): Determine sign of zero imaginary part
	of result when real part of argument is infinite using sine and
	cosine.
	* math/s_ctanhf.c (__ctanhf): Likewise.
	* math/s_ctanhl.c (__ctanhl): Likewise.
	* math/libm-test.inc (ctan_test_data): Add more tests of ctan.
	(ctanh_test_data): Add more tests of ctanh.
This commit is contained in:
Joseph Myers 2015-09-17 21:21:39 +00:00
parent b8682397ab
commit 61f8937898
9 changed files with 198 additions and 11 deletions

View File

@ -1,3 +1,20 @@
2015-09-17 Joseph Myers <joseph@codesourcery.com>
Andreas Schwab <schwab@suse.de>
[BZ #17118]
* math/s_ctan.c (__ctan): Determine sign of zero real part of
result when imaginary part of argument is infinite using sine and
cosine.
* math/s_ctanf.c (__ctanf): Likewise.
* math/s_ctanl.c (__ctanl): Likewise.
* math/s_ctanh.c (__ctanh): Determine sign of zero imaginary part
of result when real part of argument is infinite using sine and
cosine.
* math/s_ctanhf.c (__ctanhf): Likewise.
* math/s_ctanhl.c (__ctanhl): Likewise.
* math/libm-test.inc (ctan_test_data): Add more tests of ctan.
(ctanh_test_data): Add more tests of ctanh.
2015-09-17 Joseph Myers <joseph@codesourcery.com>
[BZ #15384]

10
NEWS
View File

@ -11,11 +11,11 @@ Version 2.23
2542, 2543, 2558, 2898, 4404, 6803, 14341, 14912, 15384, 15786, 15918,
16141, 16296, 16415, 16517, 16519, 16520, 16521, 16734, 16973, 16985,
17243, 17244, 17787, 17905, 18084, 18086, 18240, 18265, 18370, 18421,
18480, 18525, 18595, 18610, 18618, 18647, 18661, 18674, 18675, 18681,
18757, 18778, 18781, 18787, 18789, 18790, 18795, 18796, 18820, 18823,
18824, 18857, 18863, 18870, 18872, 18873, 18875, 18887, 18921, 18951,
18952, 18961, 18966, 18967, 18977.
17118, 17243, 17244, 17787, 17905, 18084, 18086, 18240, 18265, 18370,
18421, 18480, 18525, 18595, 18610, 18618, 18647, 18661, 18674, 18675,
18681, 18757, 18778, 18781, 18787, 18789, 18790, 18795, 18796, 18820,
18823, 18824, 18857, 18863, 18870, 18872, 18873, 18875, 18887, 18921,
18951, 18952, 18961, 18966, 18967, 18977.
* The obsolete header <regexp.h> has been removed. Programs that require
this header must be updated to use <regex.h> instead.

View File

@ -6551,13 +6551,73 @@ static const struct test_c_c_data ctan_test_data[] =
{
TEST_c_c (ctan, 0, plus_infty, 0.0, 1.0),
TEST_c_c (ctan, 1, plus_infty, 0.0, 1.0),
TEST_c_c (ctan, 2, plus_infty, minus_zero, 1.0),
TEST_c_c (ctan, 3, plus_infty, minus_zero, 1.0),
TEST_c_c (ctan, 4, plus_infty, 0.0, 1.0),
TEST_c_c (ctan, min_value, plus_infty, 0.0, 1.0),
TEST_c_c (ctan, min_subnorm_value, plus_infty, 0.0, 1.0),
TEST_c_c (ctan, 0x1p127, plus_infty, 0.0, 1.0),
TEST_c_c (ctan, 0x1.11p127, plus_infty, minus_zero, 1.0),
#ifndef TEST_FLOAT
TEST_c_c (ctan, 0x1p1023, plus_infty, minus_zero, 1.0),
TEST_c_c (ctan, 0x1.5p1023, plus_infty, 0.0, 1.0),
#endif
#if defined TEST_LDOUBLE && LDBL_MAX_EXP >= 16384
TEST_c_c (ctan, 0x1p16383L, plus_infty, 0.0, 1.0),
TEST_c_c (ctan, 0x1.2p16383L, plus_infty, minus_zero, 1.0),
#endif
TEST_c_c (ctan, minus_zero, plus_infty, minus_zero, 1.0),
TEST_c_c (ctan, -1, plus_infty, minus_zero, 1.0),
TEST_c_c (ctan, -2, plus_infty, 0.0, 1.0),
TEST_c_c (ctan, -3, plus_infty, 0.0, 1.0),
TEST_c_c (ctan, -4, plus_infty, minus_zero, 1.0),
TEST_c_c (ctan, -min_value, plus_infty, minus_zero, 1.0),
TEST_c_c (ctan, -min_subnorm_value, plus_infty, minus_zero, 1.0),
TEST_c_c (ctan, -0x1p127, plus_infty, minus_zero, 1.0),
TEST_c_c (ctan, -0x1.11p127, plus_infty, 0.0, 1.0),
#ifndef TEST_FLOAT
TEST_c_c (ctan, -0x1p1023, plus_infty, 0.0, 1.0),
TEST_c_c (ctan, -0x1.5p1023, plus_infty, minus_zero, 1.0),
#endif
#if defined TEST_LDOUBLE && LDBL_MAX_EXP >= 16384
TEST_c_c (ctan, -0x1p16383L, plus_infty, minus_zero, 1.0),
TEST_c_c (ctan, -0x1.2p16383L, plus_infty, 0.0, 1.0),
#endif
TEST_c_c (ctan, 0, minus_infty, 0.0, -1.0),
TEST_c_c (ctan, 1, minus_infty, 0.0, -1.0),
TEST_c_c (ctan, 2, minus_infty, minus_zero, -1.0),
TEST_c_c (ctan, 3, minus_infty, minus_zero, -1.0),
TEST_c_c (ctan, 4, minus_infty, 0.0, -1.0),
TEST_c_c (ctan, min_value, minus_infty, 0.0, -1.0),
TEST_c_c (ctan, min_subnorm_value, minus_infty, 0.0, -1.0),
TEST_c_c (ctan, 0x1p127, minus_infty, 0.0, -1.0),
TEST_c_c (ctan, 0x1.11p127, minus_infty, minus_zero, -1.0),
#ifndef TEST_FLOAT
TEST_c_c (ctan, 0x1p1023, minus_infty, minus_zero, -1.0),
TEST_c_c (ctan, 0x1.5p1023, minus_infty, 0.0, -1.0),
#endif
#if defined TEST_LDOUBLE && LDBL_MAX_EXP >= 16384
TEST_c_c (ctan, 0x1p16383L, minus_infty, 0.0, -1.0),
TEST_c_c (ctan, 0x1.2p16383L, minus_infty, minus_zero, -1.0),
#endif
TEST_c_c (ctan, minus_zero, minus_infty, minus_zero, -1.0),
TEST_c_c (ctan, -1, minus_infty, minus_zero, -1.0),
TEST_c_c (ctan, -2, minus_infty, 0.0, -1.0),
TEST_c_c (ctan, -3, minus_infty, 0.0, -1.0),
TEST_c_c (ctan, -4, minus_infty, minus_zero, -1.0),
TEST_c_c (ctan, -min_value, minus_infty, minus_zero, -1.0),
TEST_c_c (ctan, -min_subnorm_value, minus_infty, minus_zero, -1.0),
TEST_c_c (ctan, -0x1p127, minus_infty, minus_zero, -1.0),
TEST_c_c (ctan, -0x1.11p127, minus_infty, 0.0, -1.0),
#ifndef TEST_FLOAT
TEST_c_c (ctan, -0x1p1023, minus_infty, 0.0, -1.0),
TEST_c_c (ctan, -0x1.5p1023, minus_infty, minus_zero, -1.0),
#endif
#if defined TEST_LDOUBLE && LDBL_MAX_EXP >= 16384
TEST_c_c (ctan, -0x1p16383L, minus_infty, minus_zero, -1.0),
TEST_c_c (ctan, -0x1.2p16383L, minus_infty, 0.0, -1.0),
#endif
TEST_c_c (ctan, plus_infty, 0, qnan_value, qnan_value, INVALID_EXCEPTION),
TEST_c_c (ctan, plus_infty, 2, qnan_value, qnan_value, INVALID_EXCEPTION),
@ -6569,7 +6629,11 @@ static const struct test_c_c_data ctan_test_data[] =
TEST_c_c (ctan, minus_infty, -2, qnan_value, qnan_value, INVALID_EXCEPTION),
TEST_c_c (ctan, qnan_value, plus_infty, 0.0, 1.0, IGNORE_ZERO_INF_SIGN),
TEST_c_c (ctan, plus_infty, plus_infty, 0.0, 1.0, IGNORE_ZERO_INF_SIGN),
TEST_c_c (ctan, minus_infty, plus_infty, 0.0, 1.0, IGNORE_ZERO_INF_SIGN),
TEST_c_c (ctan, qnan_value, minus_infty, 0.0, -1.0, IGNORE_ZERO_INF_SIGN),
TEST_c_c (ctan, plus_infty, minus_infty, 0.0, -1.0, IGNORE_ZERO_INF_SIGN),
TEST_c_c (ctan, minus_infty, minus_infty, 0.0, -1.0, IGNORE_ZERO_INF_SIGN),
TEST_c_c (ctan, 0, qnan_value, 0.0, qnan_value),
TEST_c_c (ctan, minus_zero, qnan_value, minus_zero, qnan_value),
@ -6598,12 +6662,72 @@ static const struct test_c_c_data ctanh_test_data[] =
{
TEST_c_c (ctanh, plus_infty, 0, 1.0, 0.0),
TEST_c_c (ctanh, plus_infty, 1, 1.0, 0.0),
TEST_c_c (ctanh, plus_infty, 2, 1.0, minus_zero),
TEST_c_c (ctanh, plus_infty, 3, 1.0, minus_zero),
TEST_c_c (ctanh, plus_infty, 4, 1.0, 0.0),
TEST_c_c (ctanh, plus_infty, min_value, 1.0, 0.0),
TEST_c_c (ctanh, plus_infty, min_subnorm_value, 1.0, 0.0),
TEST_c_c (ctanh, plus_infty, 0x1p127, 1.0, 0.0),
TEST_c_c (ctanh, plus_infty, 0x1.11p127, 1.0, minus_zero),
#ifndef TEST_FLOAT
TEST_c_c (ctanh, plus_infty, 0x1p1023, 1.0, minus_zero),
TEST_c_c (ctanh, plus_infty, 0x1.5p1023, 1.0, 0.0),
#endif
#if defined TEST_LDOUBLE && LDBL_MAX_EXP >= 16384
TEST_c_c (ctanh, plus_infty, 0x1p16383L, 1.0, 0.0),
TEST_c_c (ctanh, plus_infty, 0x1.2p16383L, 1.0, minus_zero),
#endif
TEST_c_c (ctanh, plus_infty, minus_zero, 1.0, minus_zero),
TEST_c_c (ctanh, plus_infty, -1, 1.0, minus_zero),
TEST_c_c (ctanh, plus_infty, -2, 1.0, 0.0),
TEST_c_c (ctanh, plus_infty, -3, 1.0, 0.0),
TEST_c_c (ctanh, plus_infty, -4, 1.0, minus_zero),
TEST_c_c (ctanh, plus_infty, -min_value, 1.0, minus_zero),
TEST_c_c (ctanh, plus_infty, -min_subnorm_value, 1.0, minus_zero),
TEST_c_c (ctanh, plus_infty, -0x1p127, 1.0, minus_zero),
TEST_c_c (ctanh, plus_infty, -0x1.11p127, 1.0, 0.0),
#ifndef TEST_FLOAT
TEST_c_c (ctanh, plus_infty, -0x1p1023, 1.0, 0.0),
TEST_c_c (ctanh, plus_infty, -0x1.5p1023, 1.0, minus_zero),
#endif
#if defined TEST_LDOUBLE && LDBL_MAX_EXP >= 16384
TEST_c_c (ctanh, plus_infty, -0x1p16383L, 1.0, minus_zero),
TEST_c_c (ctanh, plus_infty, -0x1.2p16383L, 1.0, 0.0),
#endif
TEST_c_c (ctanh, minus_infty, 0, -1.0, 0.0),
TEST_c_c (ctanh, minus_infty, 1, -1.0, 0.0),
TEST_c_c (ctanh, minus_infty, 2, -1.0, minus_zero),
TEST_c_c (ctanh, minus_infty, 3, -1.0, minus_zero),
TEST_c_c (ctanh, minus_infty, 4, -1.0, 0.0),
TEST_c_c (ctanh, minus_infty, min_value, -1.0, 0.0),
TEST_c_c (ctanh, minus_infty, min_subnorm_value, -1.0, 0.0),
TEST_c_c (ctanh, minus_infty, 0x1p127, -1.0, 0.0),
TEST_c_c (ctanh, minus_infty, 0x1.11p127, -1.0, minus_zero),
#ifndef TEST_FLOAT
TEST_c_c (ctanh, minus_infty, 0x1p1023, -1.0, minus_zero),
TEST_c_c (ctanh, minus_infty, 0x1.5p1023, -1.0, 0.0),
#endif
#if defined TEST_LDOUBLE && LDBL_MAX_EXP >= 16384
TEST_c_c (ctanh, minus_infty, 0x1p16383L, -1.0, 0.0),
TEST_c_c (ctanh, minus_infty, 0x1.2p16383L, -1.0, minus_zero),
#endif
TEST_c_c (ctanh, minus_infty, minus_zero, -1.0, minus_zero),
TEST_c_c (ctanh, minus_infty, -1, -1.0, minus_zero),
TEST_c_c (ctanh, minus_infty, -2, -1.0, 0.0),
TEST_c_c (ctanh, minus_infty, -3, -1.0, 0.0),
TEST_c_c (ctanh, minus_infty, -4, -1.0, minus_zero),
TEST_c_c (ctanh, minus_infty, -min_value, -1.0, minus_zero),
TEST_c_c (ctanh, minus_infty, -min_subnorm_value, -1.0, minus_zero),
TEST_c_c (ctanh, minus_infty, -0x1p127, -1.0, minus_zero),
TEST_c_c (ctanh, minus_infty, -0x1.11p127, -1.0, 0.0),
#ifndef TEST_FLOAT
TEST_c_c (ctanh, minus_infty, -0x1p1023, -1.0, 0.0),
TEST_c_c (ctanh, minus_infty, -0x1.5p1023, -1.0, minus_zero),
#endif
#if defined TEST_LDOUBLE && LDBL_MAX_EXP >= 16384
TEST_c_c (ctanh, minus_infty, -0x1p16383L, -1.0, minus_zero),
TEST_c_c (ctanh, minus_infty, -0x1.2p16383L, -1.0, 0.0),
#endif
TEST_c_c (ctanh, 0, plus_infty, qnan_value, qnan_value, INVALID_EXCEPTION),
TEST_c_c (ctanh, 2, plus_infty, qnan_value, qnan_value, INVALID_EXCEPTION),
@ -6615,7 +6739,11 @@ static const struct test_c_c_data ctanh_test_data[] =
TEST_c_c (ctanh, -2, minus_infty, qnan_value, qnan_value, INVALID_EXCEPTION),
TEST_c_c (ctanh, plus_infty, qnan_value, 1.0, 0.0, IGNORE_ZERO_INF_SIGN),
TEST_c_c (ctanh, plus_infty, plus_infty, 1.0, 0.0, IGNORE_ZERO_INF_SIGN),
TEST_c_c (ctanh, plus_infty, minus_infty, 1.0, 0.0, IGNORE_ZERO_INF_SIGN),
TEST_c_c (ctanh, minus_infty, qnan_value, -1.0, 0.0, IGNORE_ZERO_INF_SIGN),
TEST_c_c (ctanh, minus_infty, plus_infty, -1.0, 0.0, IGNORE_ZERO_INF_SIGN),
TEST_c_c (ctanh, minus_infty, minus_infty, -1.0, 0.0, IGNORE_ZERO_INF_SIGN),
TEST_c_c (ctanh, qnan_value, 0, qnan_value, 0.0),
TEST_c_c (ctanh, qnan_value, minus_zero, qnan_value, minus_zero),

View File

@ -32,7 +32,14 @@ __ctan (__complex__ double x)
{
if (__isinf_ns (__imag__ x))
{
__real__ res = __copysign (0.0, __real__ x);
if (isfinite (__real__ x) && fabs (__real__ x) > 1.0)
{
double sinrx, cosrx;
__sincos (__real__ x, &sinrx, &cosrx);
__real__ res = __copysign (0.0, sinrx * cosrx);
}
else
__real__ res = __copysign (0.0, __real__ x);
__imag__ res = __copysign (1.0, __imag__ x);
}
else if (__real__ x == 0.0)

View File

@ -32,7 +32,14 @@ __ctanf (__complex__ float x)
{
if (__isinf_nsf (__imag__ x))
{
__real__ res = __copysignf (0.0, __real__ x);
if (isfinite (__real__ x) && fabsf (__real__ x) > 1.0f)
{
float sinrx, cosrx;
__sincosf (__real__ x, &sinrx, &cosrx);
__real__ res = __copysignf (0.0f, sinrx * cosrx);
}
else
__real__ res = __copysignf (0.0, __real__ x);
__imag__ res = __copysignf (1.0, __imag__ x);
}
else if (__real__ x == 0.0)

View File

@ -33,7 +33,14 @@ __ctanh (__complex__ double x)
if (__isinf_ns (__real__ x))
{
__real__ res = __copysign (1.0, __real__ x);
__imag__ res = __copysign (0.0, __imag__ x);
if (isfinite (__imag__ x) && fabs (__imag__ x) > 1.0)
{
double sinix, cosix;
__sincos (__imag__ x, &sinix, &cosix);
__imag__ res = __copysign (0.0, sinix * cosix);
}
else
__imag__ res = __copysign (0.0, __imag__ x);
}
else if (__imag__ x == 0.0)
{

View File

@ -33,7 +33,14 @@ __ctanhf (__complex__ float x)
if (__isinf_nsf (__real__ x))
{
__real__ res = __copysignf (1.0, __real__ x);
__imag__ res = __copysignf (0.0, __imag__ x);
if (isfinite (__imag__ x) && fabsf (__imag__ x) > 1.0f)
{
float sinix, cosix;
__sincosf (__imag__ x, &sinix, &cosix);
__imag__ res = __copysignf (0.0f, sinix * cosix);
}
else
__imag__ res = __copysignf (0.0, __imag__ x);
}
else if (__imag__ x == 0.0)
{

View File

@ -40,7 +40,14 @@ __ctanhl (__complex__ long double x)
if (__isinf_nsl (__real__ x))
{
__real__ res = __copysignl (1.0, __real__ x);
__imag__ res = __copysignl (0.0, __imag__ x);
if (isfinite (__imag__ x) && fabsl (__imag__ x) > 1.0L)
{
long double sinix, cosix;
__sincosl (__imag__ x, &sinix, &cosix);
__imag__ res = __copysignl (0.0L, sinix * cosix);
}
else
__imag__ res = __copysignl (0.0, __imag__ x);
}
else if (__imag__ x == 0.0)
{

View File

@ -39,7 +39,14 @@ __ctanl (__complex__ long double x)
{
if (__isinf_nsl (__imag__ x))
{
__real__ res = __copysignl (0.0, __real__ x);
if (isfinite (__real__ x) && fabsl (__real__ x) > 1.0L)
{
long double sinrx, cosrx;
__sincosl (__real__ x, &sinrx, &cosrx);
__real__ res = __copysignl (0.0L, sinrx * cosrx);
}
else
__real__ res = __copysignl (0.0, __real__ x);
__imag__ res = __copysignl (1.0, __imag__ x);
}
else if (__real__ x == 0.0)