Skip to content

Commit

Permalink
Fix catan, catanh spurious overflows (bug 15409).
Browse files Browse the repository at this point in the history
  • Loading branch information
Joseph Myers committed Apr 27, 2013
1 parent d5ba74f commit 5b4217d
Show file tree
Hide file tree
Showing 11 changed files with 492 additions and 91 deletions.
21 changes: 21 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,24 @@
2013-04-27 Joseph Myers <joseph@codesourcery.com>

[BZ #15409]
* math/s_catan.c (__catan): Handle arguments with large real or
imaginary part separately without squaring.
* math/s_catanf.c (__catanf): Likewise.
* math/s_catanh.c (__catanh): Likewise.
* math/s_catanhf.c (__catanhf): Likewise.
* math/s_catanhl.c [LDBL_MANT_DIG == 106] (LDBL_EPSILON): Undefine
and redefine.
(__catanhl): Handle arguments with large real or imaginary part
separately without squaring.
* math/s_catanl.c [LDBL_MANT_DIG == 106] (LDBL_EPSILON): Undefine
and redefine.
(__catanl): Handle arguments with large real or imaginary part
separately without squaring.
* math/libm-test.inc (catan_test): Add more tests.
(catanh_test): Likewise.
* sysdeps/i386/fpu/libm-test-ulps: Update.
* sysdeps/x86_64/fpu/libm-test-ulps: Likewise.

2013-04-27 Andreas Jaeger <aj@suse.de>

[BZ #15007]
Expand Down
2 changes: 1 addition & 1 deletion NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Version 2.18
15006, 15007, 15020, 15023, 15036, 15054, 15055, 15062, 15078, 15160,
15214, 15221, 15232, 15234, 15283, 15285, 15287, 15304, 15305, 15307,
15309, 15327, 15330, 15335, 15336, 15337, 15342, 15346, 15361, 15366,
15394, 15405, 15406.
15394, 15405, 15406, 15409.

* CVE-2013-0242 Buffer overrun in regexp matcher has been fixed (Bugzilla
#15078).
Expand Down
128 changes: 128 additions & 0 deletions math/libm-test.inc

Large diffs are not rendered by default.

47 changes: 32 additions & 15 deletions math/s_catan.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,27 +61,44 @@ __catan (__complex__ double x)
}
else
{
double r2, num, den, f;
if (fabs (__real__ x) >= 16.0 / DBL_EPSILON
|| fabs (__imag__ x) >= 16.0 / DBL_EPSILON)
{
__real__ res = __copysign (M_PI_2, __real__ x);
if (fabs (__real__ x) <= 1.0)
__imag__ res = 1.0 / __imag__ x;
else if (fabs (__imag__ x) <= 1.0)
__imag__ res = __imag__ x / __real__ x / __real__ x;
else
{
double h = __ieee754_hypot (__real__ x / 2.0, __imag__ x / 2.0);
__imag__ res = __imag__ x / h / h / 4.0;
}
}
else
{
double r2, num, den, f;

r2 = __real__ x * __real__ x;
r2 = __real__ x * __real__ x;

den = 1 - r2 - __imag__ x * __imag__ x;
den = 1 - r2 - __imag__ x * __imag__ x;

__real__ res = 0.5 * __ieee754_atan2 (2.0 * __real__ x, den);
__real__ res = 0.5 * __ieee754_atan2 (2.0 * __real__ x, den);

num = __imag__ x + 1.0;
num = r2 + num * num;
num = __imag__ x + 1.0;
num = r2 + num * num;

den = __imag__ x - 1.0;
den = r2 + den * den;
den = __imag__ x - 1.0;
den = r2 + den * den;

f = num / den;
if (f < 0.5)
__imag__ res = 0.25 * __ieee754_log (f);
else
{
num = 4.0 * __imag__ x;
__imag__ res = 0.25 * __log1p (num / den);
f = num / den;
if (f < 0.5)
__imag__ res = 0.25 * __ieee754_log (f);
else
{
num = 4.0 * __imag__ x;
__imag__ res = 0.25 * __log1p (num / den);
}
}

if (fabs (__real__ res) < DBL_MIN)
Expand Down
48 changes: 33 additions & 15 deletions math/s_catanf.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,27 +61,45 @@ __catanf (__complex__ float x)
}
else
{
float r2, num, den, f;
if (fabsf (__real__ x) >= 16.0f / FLT_EPSILON
|| fabsf (__imag__ x) >= 16.0f / FLT_EPSILON)
{
__real__ res = __copysignf ((float) M_PI_2, __real__ x);
if (fabsf (__real__ x) <= 1.0f)
__imag__ res = 1.0f / __imag__ x;
else if (fabsf (__imag__ x) <= 1.0f)
__imag__ res = __imag__ x / __real__ x / __real__ x;
else
{
float h = __ieee754_hypotf (__real__ x / 2.0f,
__imag__ x / 2.0f);
__imag__ res = __imag__ x / h / h / 4.0f;
}
}
else
{
float r2, num, den, f;

r2 = __real__ x * __real__ x;
r2 = __real__ x * __real__ x;

den = 1 - r2 - __imag__ x * __imag__ x;
den = 1 - r2 - __imag__ x * __imag__ x;

__real__ res = 0.5f * __ieee754_atan2f (2.0f * __real__ x, den);
__real__ res = 0.5f * __ieee754_atan2f (2.0f * __real__ x, den);

num = __imag__ x + 1.0f;
num = r2 + num * num;
num = __imag__ x + 1.0f;
num = r2 + num * num;

den = __imag__ x - 1.0f;
den = r2 + den * den;
den = __imag__ x - 1.0f;
den = r2 + den * den;

f = num / den;
if (f < 0.5f)
__imag__ res = 0.25f * __ieee754_logf (f);
else
{
num = 4.0f * __imag__ x;
__imag__ res = 0.25f * __log1pf (num / den);
f = num / den;
if (f < 0.5f)
__imag__ res = 0.25f * __ieee754_logf (f);
else
{
num = 4.0f * __imag__ x;
__imag__ res = 0.25f * __log1pf (num / den);
}
}

if (fabsf (__real__ res) < FLT_MIN)
Expand Down
47 changes: 32 additions & 15 deletions math/s_catanh.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,26 +56,43 @@ __catanh (__complex__ double x)
}
else
{
double i2 = __imag__ x * __imag__ x;
if (fabs (__real__ x) >= 16.0 / DBL_EPSILON
|| fabs (__imag__ x) >= 16.0 / DBL_EPSILON)
{
__imag__ res = __copysign (M_PI_2, __imag__ x);
if (fabs (__imag__ x) <= 1.0)
__real__ res = 1.0 / __real__ x;
else if (fabs (__real__ x) <= 1.0)
__real__ res = __real__ x / __imag__ x / __imag__ x;
else
{
double h = __ieee754_hypot (__real__ x / 2.0, __imag__ x / 2.0);
__real__ res = __real__ x / h / h / 4.0;
}
}
else
{
double i2 = __imag__ x * __imag__ x;

double num = 1.0 + __real__ x;
num = i2 + num * num;
double num = 1.0 + __real__ x;
num = i2 + num * num;

double den = 1.0 - __real__ x;
den = i2 + den * den;
double den = 1.0 - __real__ x;
den = i2 + den * den;

double f = num / den;
if (f < 0.5)
__real__ res = 0.25 * __ieee754_log (f);
else
{
num = 4.0 * __real__ x;
__real__ res = 0.25 * __log1p (num / den);
}
double f = num / den;
if (f < 0.5)
__real__ res = 0.25 * __ieee754_log (f);
else
{
num = 4.0 * __real__ x;
__real__ res = 0.25 * __log1p (num / den);
}

den = 1 - __real__ x * __real__ x - i2;
den = 1 - __real__ x * __real__ x - i2;

__imag__ res = 0.5 * __ieee754_atan2 (2.0 * __imag__ x, den);
__imag__ res = 0.5 * __ieee754_atan2 (2.0 * __imag__ x, den);
}

if (fabs (__real__ res) < DBL_MIN)
{
Expand Down
48 changes: 33 additions & 15 deletions math/s_catanhf.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,26 +56,44 @@ __catanhf (__complex__ float x)
}
else
{
float i2 = __imag__ x * __imag__ x;
if (fabsf (__real__ x) >= 16.0f / FLT_EPSILON
|| fabsf (__imag__ x) >= 16.0f / FLT_EPSILON)
{
__imag__ res = __copysignf ((float) M_PI_2, __imag__ x);
if (fabsf (__imag__ x) <= 1.0f)
__real__ res = 1.0f / __real__ x;
else if (fabsf (__real__ x) <= 1.0f)
__real__ res = __real__ x / __imag__ x / __imag__ x;
else
{
float h = __ieee754_hypotf (__real__ x / 2.0f,
__imag__ x / 2.0f);
__real__ res = __real__ x / h / h / 4.0f;
}
}
else
{
float i2 = __imag__ x * __imag__ x;

float num = 1.0f + __real__ x;
num = i2 + num * num;
float num = 1.0f + __real__ x;
num = i2 + num * num;

float den = 1.0f - __real__ x;
den = i2 + den * den;
float den = 1.0f - __real__ x;
den = i2 + den * den;

float f = num / den;
if (f < 0.5f)
__real__ res = 0.25f * __ieee754_logf (f);
else
{
num = 4.0f * __real__ x;
__real__ res = 0.25f * __log1pf (num / den);
}
float f = num / den;
if (f < 0.5f)
__real__ res = 0.25f * __ieee754_logf (f);
else
{
num = 4.0f * __real__ x;
__real__ res = 0.25f * __log1pf (num / den);
}

den = 1 - __real__ x * __real__ x - i2;
den = 1 - __real__ x * __real__ x - i2;

__imag__ res = 0.5f * __ieee754_atan2f (2.0f * __imag__ x, den);
__imag__ res = 0.5f * __ieee754_atan2f (2.0f * __imag__ x, den);
}

if (fabsf (__real__ res) < FLT_MIN)
{
Expand Down
55 changes: 40 additions & 15 deletions math/s_catanhl.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,13 @@
#include <math_private.h>
#include <float.h>

/* To avoid spurious overflows, use this definition to treat IBM long
double as approximating an IEEE-style format. */
#if LDBL_MANT_DIG == 106
# undef LDBL_EPSILON
# define LDBL_EPSILON 0x1p-106L
#endif

__complex__ long double
__catanhl (__complex__ long double x)
{
Expand Down Expand Up @@ -56,26 +63,44 @@ __catanhl (__complex__ long double x)
}
else
{
long double i2 = __imag__ x * __imag__ x;
if (fabsl (__real__ x) >= 16.0L / LDBL_EPSILON
|| fabsl (__imag__ x) >= 16.0L / LDBL_EPSILON)
{
__imag__ res = __copysignl (M_PI_2l, __imag__ x);
if (fabsl (__imag__ x) <= 1.0L)
__real__ res = 1.0L / __real__ x;
else if (fabsl (__real__ x) <= 1.0L)
__real__ res = __real__ x / __imag__ x / __imag__ x;
else
{
long double h = __ieee754_hypotl (__real__ x / 2.0L,
__imag__ x / 2.0L);
__real__ res = __real__ x / h / h / 4.0L;
}
}
else
{
long double i2 = __imag__ x * __imag__ x;

long double num = 1.0L + __real__ x;
num = i2 + num * num;
long double num = 1.0L + __real__ x;
num = i2 + num * num;

long double den = 1.0L - __real__ x;
den = i2 + den * den;
long double den = 1.0L - __real__ x;
den = i2 + den * den;

long double f = num / den;
if (f < 0.5L)
__real__ res = 0.25L * __ieee754_logl (f);
else
{
num = 4.0L * __real__ x;
__real__ res = 0.25L * __log1pl (num / den);
}
long double f = num / den;
if (f < 0.5L)
__real__ res = 0.25L * __ieee754_logl (f);
else
{
num = 4.0L * __real__ x;
__real__ res = 0.25L * __log1pl (num / den);
}

den = 1 - __real__ x * __real__ x - i2;
den = 1 - __real__ x * __real__ x - i2;

__imag__ res = 0.5L * __ieee754_atan2l (2.0L * __imag__ x, den);
__imag__ res = 0.5L * __ieee754_atan2l (2.0L * __imag__ x, den);
}

if (fabsl (__real__ res) < LDBL_MIN)
{
Expand Down
Loading

0 comments on commit 5b4217d

Please sign in to comment.