Skip to content

Commit

Permalink
Fix sign of zero part from ctan / ctanh when argument infinite (bug 1…
Browse files Browse the repository at this point in the history
…7118).

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.
  • Loading branch information
Joseph Myers committed Sep 17, 2015
1 parent b868239 commit 61f8937
Show file tree
Hide file tree
Showing 9 changed files with 198 additions and 11 deletions.
17 changes: 17 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -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]
Expand Down
10 changes: 5 additions & 5 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
128 changes: 128 additions & 0 deletions math/libm-test.inc
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand All @@ -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),
Expand Down Expand Up @@ -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),
Expand All @@ -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),
Expand Down
9 changes: 8 additions & 1 deletion math/s_ctan.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
9 changes: 8 additions & 1 deletion math/s_ctanf.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
9 changes: 8 additions & 1 deletion math/s_ctanh.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down
9 changes: 8 additions & 1 deletion math/s_ctanhf.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down
9 changes: 8 additions & 1 deletion math/s_ctanhl.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down
9 changes: 8 additions & 1 deletion math/s_ctanl.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down

0 comments on commit 61f8937

Please sign in to comment.