Fix csqrt spurious underflows (bug 18823).

The csqrt functions scale up small arguments to avoid underflows when
calling hypot functions.  However, even when hypot does not underflow,
a subsequent calculation of 0.5 * hypot can underflow.  This patch
duly increases the threshold and scale factor to avoid such underflows
as well.

Tested for x86_64, x86 and mips64.

	[BZ #18823]
	* math/s_csqrt.c (__csqrt): Increase threshold and scale factor
	for scaling up small arguments.
	* math/s_csqrtf.c (__csqrtf): Likewise.
	* math/s_csqrtl.c (__csqrtl): Likewise.
	* math/auto-libm-test-in: Add more tests of csqrt.
	* math/auto-libm-test-out: Regenerated.
This commit is contained in:
Joseph Myers 2015-08-17 23:02:54 +00:00
parent 1e15a853ed
commit 3fb4cfaf1f
7 changed files with 1861 additions and 10 deletions

View File

@ -1,3 +1,13 @@
2015-08-17 Joseph Myers <joseph@codesourcery.com>
[BZ #18823]
* math/s_csqrt.c (__csqrt): Increase threshold and scale factor
for scaling up small arguments.
* math/s_csqrtf.c (__csqrtf): Likewise.
* math/s_csqrtl.c (__csqrtl): Likewise.
* math/auto-libm-test-in: Add more tests of csqrt.
* math/auto-libm-test-out: Regenerated.
2015-08-17 Andreas Schwab <schwab@suse.de>
* sysdeps/unix/sysv/linux/powerpc/Versions (libm): Add empty

2
NEWS
View File

@ -11,7 +11,7 @@ Version 2.23
16517, 16519, 16520, 16734, 17905, 18084, 18086, 18265, 18480, 18525,
18618, 18647, 18661, 18681, 18674, 18778, 18781, 18787, 18789, 18790,
18795, 18820, 18824.
18795, 18820, 18823, 18824.
* The obsolete header <regexp.h> has been removed. Programs that require
this header must be updated to use <regex.h> instead.

View File

@ -1162,6 +1162,15 @@ csqrt -0x0.ffp1024 0x1.1p-509
csqrt 0x0.ffp16384 0x1.1p-8189
csqrt -0x0.ffp16384 0x1.1p-8189
csqrt 0x1p-149 0x1.000002p-126
csqrt 0x1p-149 0x1.000004p-126
csqrt 0x1p-1074 0x1.0000000000001p-1022
csqrt 0x1p-1074 0x1.0000000000002p-1022
csqrt 0x1p-16445 0x1.0000000000000002p-16382
csqrt 0x1p-16445 0x1.0000000000000004p-16382
csqrt 0x1p-16494 0x1.0000000000000000000000000001p-16382
csqrt 0x1p-16494 0x1.0000000000000000000000000002p-16382
ctan 0 0
ctan 0 -0
ctan -0 0

File diff suppressed because it is too large Load Diff

View File

@ -104,10 +104,10 @@ __csqrt (__complex__ double x)
__real__ x = 0.0;
__imag__ x = __scalbn (__imag__ x, -2 * scale);
}
else if (fabs (__real__ x) < DBL_MIN
&& fabs (__imag__ x) < DBL_MIN)
else if (fabs (__real__ x) < 2.0 * DBL_MIN
&& fabs (__imag__ x) < 2.0 * DBL_MIN)
{
scale = -(DBL_MANT_DIG / 2);
scale = -((DBL_MANT_DIG + 1) / 2);
__real__ x = __scalbn (__real__ x, -2 * scale);
__imag__ x = __scalbn (__imag__ x, -2 * scale);
}

View File

@ -104,10 +104,10 @@ __csqrtf (__complex__ float x)
__real__ x = 0.0f;
__imag__ x = __scalbnf (__imag__ x, -2 * scale);
}
else if (fabsf (__real__ x) < FLT_MIN
&& fabsf (__imag__ x) < FLT_MIN)
else if (fabsf (__real__ x) < 2.0f * FLT_MIN
&& fabsf (__imag__ x) < 2.0f * FLT_MIN)
{
scale = -(FLT_MANT_DIG / 2);
scale = -((FLT_MANT_DIG + 1) / 2);
__real__ x = __scalbnf (__real__ x, -2 * scale);
__imag__ x = __scalbnf (__imag__ x, -2 * scale);
}

View File

@ -104,10 +104,10 @@ __csqrtl (__complex__ long double x)
__real__ x = 0.0L;
__imag__ x = __scalbnl (__imag__ x, -2 * scale);
}
else if (fabsl (__real__ x) < LDBL_MIN
&& fabsl (__imag__ x) < LDBL_MIN)
else if (fabsl (__real__ x) < 2.0L * LDBL_MIN
&& fabsl (__imag__ x) < 2.0L * LDBL_MIN)
{
scale = -(LDBL_MANT_DIG / 2);
scale = -((LDBL_MANT_DIG + 1) / 2);
__real__ x = __scalbnl (__real__ x, -2 * scale);
__imag__ x = __scalbnl (__imag__ x, -2 * scale);
}