aboutsummaryrefslogtreecommitdiff
path: root/math
diff options
context:
space:
mode:
authorJoseph Myers <joseph@codesourcery.com>2012-03-19 20:13:10 +0000
committerJoseph Myers <joseph@codesourcery.com>2012-03-19 20:14:26 +0000
commit1897ad44326bb7761dcda46132ae303f7288aba9 (patch)
treefd8357b0066902deb5b6b9476b8c456f68ffc56e /math
parent7726d6a95d5a2c08c8d43186002f040b9b889c27 (diff)
downloadglibc-1897ad44326bb7761dcda46132ae303f7288aba9.zip
glibc-1897ad44326bb7761dcda46132ae303f7288aba9.tar.gz
glibc-1897ad44326bb7761dcda46132ae303f7288aba9.tar.bz2
Fix clog overflow/underflow (bug 13629).
Diffstat (limited to 'math')
-rw-r--r--math/libm-test.inc36
-rw-r--r--math/s_clog.c27
-rw-r--r--math/s_clog10.c28
-rw-r--r--math/s_clog10f.c28
-rw-r--r--math/s_clog10l.c28
-rw-r--r--math/s_clogf.c28
-rw-r--r--math/s_clogl.c27
7 files changed, 180 insertions, 22 deletions
diff --git a/math/libm-test.inc b/math/libm-test.inc
index 817864a..8bb4358 100644
--- a/math/libm-test.inc
+++ b/math/libm-test.inc
@@ -1969,6 +1969,24 @@ clog_test (void)
TEST_c_c (clog, 0.75L, 1.25L, 0.376885901188190075998919126749298416L, 1.03037682652431246378774332703115153L);
TEST_c_c (clog, -2, -3, 1.2824746787307683680267437207826593L, -2.1587989303424641704769327722648368L);
+ TEST_c_c (clog, 0x1.fffffep+127L, 0x1.fffffep+127L, 89.06941264234832570836679262104313101776L, M_PI_4l);
+ TEST_c_c (clog, 0x1.fffffep+127L, 1.0L, 88.72283905206835305365817656031404273372L, 2.938736052218037251011746307725933020145e-39L);
+ TEST_c_c (clog, 0x1p-149L, 0x1p-149L, -102.9323563131518784484589700365392203592L, M_PI_4l);
+ TEST_c_c (clog, 0x1p-147L, 0x1p-147L, -101.5460619520319878296245057936228672231L, M_PI_4l);
+
+#ifndef TEST_FLOAT
+ TEST_c_c (clog, 0x1.fffffffffffffp+1023L, 0x1.fffffffffffffp+1023L, 710.1292864836639693869320059713862337880L, M_PI_4l);
+ TEST_c_c (clog, 0x1.fffffffffffffp+1023L, 0x1p+1023L, 709.8942846690411016323109979483151967689L, 0.4636476090008061606231772164674799632783L);
+ TEST_c_c (clog, 0x1p-1074L, 0x1p-1074L, -744.0934983311012896593986823853525458290L, M_PI_4l);
+ TEST_c_c (clog, 0x1p-1073L, 0x1p-1073L, -743.4003511505413443499814502638943692610L, M_PI_4l);
+#endif
+
+#if defined TEST_LDOUBLE && LDBL_MAX_EXP >= 16384
+ TEST_c_c (clog, 0x1.fp+16383L, 0x1.fp+16383L, 11356.83823118610934184548269774874545400L, M_PI_4l);
+ TEST_c_c (clog, 0x1.fp+16383L, 0x1p+16383L, 11356.60974243783798653123798337822335902L, 0.4764674194737066993385333770295162295856L);
+ TEST_c_c (clog, 0x1p-16440L, 0x1p-16441L, -11395.22807662984378194141292922726786191L, 0.4636476090008061162142562314612144020285L);
+#endif
+
END (clog, complex);
}
@@ -2035,6 +2053,24 @@ clog10_test (void)
TEST_c_c (clog10, 0.75L, 1.25L, 0.163679467193165171449476605077428975L, 0.447486970040493067069984724340855636L);
TEST_c_c (clog10, -2, -3, 0.556971676153418384603252578971164214L, -0.937554462986374708541507952140189646L);
+ TEST_c_c (clog10, 0x1.fffffep+127L, 0x1.fffffep+127L, 38.68235441693561449174780668781319348761L, M_PI4_LOG10El);
+ TEST_c_c (clog10, 0x1.fffffep+127L, 1.0L, 38.53183941910362389414093724045094697423L, 1.276276851248440096917018665609900318458e-39L);
+ TEST_c_c (clog10, 0x1p-149L, 0x1p-149L, -44.70295435610120748924022586658721447508L, M_PI4_LOG10El);
+ TEST_c_c (clog10, 0x1p-147L, 0x1p-147L, -44.10089436477324509881274807713822842154L, M_PI4_LOG10El);
+
+#ifndef TEST_FLOAT
+ TEST_c_c (clog10, 0x1.fffffffffffffp+1023L, 0x1.fffffffffffffp+1023L, 308.4052305577487344482591243175787477115L, M_PI4_LOG10El);
+ TEST_c_c (clog10, 0x1.fffffffffffffp+1023L, 0x1p+1023L, 308.3031705664207720674749211936626341569L, 0.2013595981366865903254995612594728746470L);
+ TEST_c_c (clog10, 0x1p-1074L, 0x1p-1074L, -323.1557003452838130619487034867432642357L, M_PI4_LOG10El);
+ TEST_c_c (clog10, 0x1p-1073L, 0x1p-1073L, -322.8546703496198318667349645920187712089L, M_PI4_LOG10El);
+#endif
+
+#if defined TEST_LDOUBLE && LDBL_MAX_EXP >= 16384
+ TEST_c_c (clog10, 0x1.fp+16383L, 0x1.fp+16383L, 4932.212175672014259683102930239951947672L, M_PI4_LOG10El);
+ TEST_c_c (clog10, 0x1.fp+16383L, 0x1p+16383L, 4932.112944269463028900262609694408579449L, 0.2069271710841128115912940666587802677383L);
+ TEST_c_c (clog10, 0x1p-16440L, 0x1p-16441L, -4948.884673709346821106688037612752099609L, 0.2013595981366865710389502301937289472543L);
+#endif
+
END (clog10, complex);
}
diff --git a/math/s_clog.c b/math/s_clog.c
index 5bbca00..15e5e9c 100644
--- a/math/s_clog.c
+++ b/math/s_clog.c
@@ -1,5 +1,5 @@
/* Compute complex natural logarithm.
- Copyright (C) 1997, 2011 Free Software Foundation, Inc.
+ Copyright (C) 1997-2012 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
@@ -20,7 +20,7 @@
#include <complex.h>
#include <math.h>
#include <math_private.h>
-
+#include <float.h>
__complex__ double
__clog (__complex__ double x)
@@ -40,8 +40,27 @@ __clog (__complex__ double x)
else if (__builtin_expect (rcls != FP_NAN && icls != FP_NAN, 1))
{
/* Neither real nor imaginary part is NaN. */
- __real__ result = __ieee754_log (__ieee754_hypot (__real__ x,
- __imag__ x));
+ double d;
+ int scale = 0;
+
+ if (fabs (__real__ x) > DBL_MAX / 2.0
+ || fabs (__imag__ x) > DBL_MAX / 2.0)
+ {
+ scale = -1;
+ __real__ x = __scalbn (__real__ x, scale);
+ __imag__ x = __scalbn (__imag__ x, scale);
+ }
+ else if (fabs (__real__ x) < DBL_MIN
+ && fabs (__imag__ x) < DBL_MIN)
+ {
+ scale = DBL_MANT_DIG;
+ __real__ x = __scalbn (__real__ x, scale);
+ __imag__ x = __scalbn (__imag__ x, scale);
+ }
+
+ d = __ieee754_hypot (__real__ x, __imag__ x);
+
+ __real__ result = __ieee754_log (d) - scale * M_LN2;
__imag__ result = __ieee754_atan2 (__imag__ x, __real__ x);
}
else
diff --git a/math/s_clog10.c b/math/s_clog10.c
index 3eb9c51..9d366d6 100644
--- a/math/s_clog10.c
+++ b/math/s_clog10.c
@@ -1,5 +1,5 @@
/* Compute complex base 10 logarithm.
- Copyright (C) 1997, 2011 Free Software Foundation, Inc.
+ Copyright (C) 1997-2012 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
@@ -20,7 +20,10 @@
#include <complex.h>
#include <math.h>
#include <math_private.h>
+#include <float.h>
+/* log_10 (2). */
+#define M_LOG10_2 0.3010299956639811952137388947244930267682
__complex__ double
__clog10 (__complex__ double x)
@@ -40,8 +43,27 @@ __clog10 (__complex__ double x)
else if (__builtin_expect (rcls != FP_NAN && icls != FP_NAN, 1))
{
/* Neither real nor imaginary part is NaN. */
- __real__ result = __ieee754_log10 (__ieee754_hypot (__real__ x,
- __imag__ x));
+ double d;
+ int scale = 0;
+
+ if (fabs (__real__ x) > DBL_MAX / 2.0
+ || fabs (__imag__ x) > DBL_MAX / 2.0)
+ {
+ scale = -1;
+ __real__ x = __scalbn (__real__ x, scale);
+ __imag__ x = __scalbn (__imag__ x, scale);
+ }
+ else if (fabs (__real__ x) < DBL_MIN
+ && fabs (__imag__ x) < DBL_MIN)
+ {
+ scale = DBL_MANT_DIG;
+ __real__ x = __scalbn (__real__ x, scale);
+ __imag__ x = __scalbn (__imag__ x, scale);
+ }
+
+ d = __ieee754_hypot (__real__ x, __imag__ x);
+
+ __real__ result = __ieee754_log10 (d) - scale * M_LOG10_2;
__imag__ result = M_LOG10E * __ieee754_atan2 (__imag__ x, __real__ x);
}
else
diff --git a/math/s_clog10f.c b/math/s_clog10f.c
index e48d928..11bb0bb 100644
--- a/math/s_clog10f.c
+++ b/math/s_clog10f.c
@@ -1,5 +1,5 @@
/* Compute complex base 10 logarithm.
- Copyright (C) 1997, 2011 Free Software Foundation, Inc.
+ Copyright (C) 1997-2012 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
@@ -20,7 +20,10 @@
#include <complex.h>
#include <math.h>
#include <math_private.h>
+#include <float.h>
+/* log_10 (2). */
+#define M_LOG10_2f 0.3010299956639811952137388947244930267682f
__complex__ float
__clog10f (__complex__ float x)
@@ -40,8 +43,27 @@ __clog10f (__complex__ float x)
else if (__builtin_expect (rcls != FP_NAN && icls != FP_NAN, 1))
{
/* Neither real nor imaginary part is NaN. */
- __real__ result = __ieee754_log10f (__ieee754_hypotf (__real__ x,
- __imag__ x));
+ float d;
+ int scale = 0;
+
+ if (fabsf (__real__ x) > FLT_MAX / 2.0f
+ || fabsf (__imag__ x) > FLT_MAX / 2.0f)
+ {
+ scale = -1;
+ __real__ x = __scalbnf (__real__ x, scale);
+ __imag__ x = __scalbnf (__imag__ x, scale);
+ }
+ else if (fabsf (__real__ x) < FLT_MIN
+ && fabsf (__imag__ x) < FLT_MIN)
+ {
+ scale = FLT_MANT_DIG;
+ __real__ x = __scalbnf (__real__ x, scale);
+ __imag__ x = __scalbnf (__imag__ x, scale);
+ }
+
+ d = __ieee754_hypotf (__real__ x, __imag__ x);
+
+ __real__ result = __ieee754_log10f (d) - scale * M_LOG10_2f;
__imag__ result = M_LOG10E * __ieee754_atan2f (__imag__ x, __real__ x);
}
else
diff --git a/math/s_clog10l.c b/math/s_clog10l.c
index 72b5531..d1fc872 100644
--- a/math/s_clog10l.c
+++ b/math/s_clog10l.c
@@ -1,5 +1,5 @@
/* Compute complex base 10 logarithm.
- Copyright (C) 1997, 1998, 2011 Free Software Foundation, Inc.
+ Copyright (C) 1997-2012 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
@@ -20,7 +20,10 @@
#include <complex.h>
#include <math.h>
#include <math_private.h>
+#include <float.h>
+/* log_10 (2). */
+#define M_LOG10_2l 0.3010299956639811952137388947244930267682L
__complex__ long double
__clog10l (__complex__ long double x)
@@ -40,8 +43,27 @@ __clog10l (__complex__ long double x)
else if (__builtin_expect (rcls != FP_NAN && icls != FP_NAN, 1))
{
/* Neither real nor imaginary part is NaN. */
- __real__ result = __ieee754_log10l (__ieee754_hypotl (__real__ x,
- __imag__ x));
+ long double d;
+ int scale = 0;
+
+ if (fabsl (__real__ x) > LDBL_MAX / 2.0L
+ || fabsl (__imag__ x) > LDBL_MAX / 2.0L)
+ {
+ scale = -1;
+ __real__ x = __scalbnl (__real__ x, scale);
+ __imag__ x = __scalbnl (__imag__ x, scale);
+ }
+ else if (fabsl (__real__ x) < LDBL_MIN
+ && fabsl (__imag__ x) < LDBL_MIN)
+ {
+ scale = LDBL_MANT_DIG;
+ __real__ x = __scalbnl (__real__ x, scale);
+ __imag__ x = __scalbnl (__imag__ x, scale);
+ }
+
+ d = __ieee754_hypotl (__real__ x, __imag__ x);
+
+ __real__ result = __ieee754_log10l (d) - scale * M_LOG10_2l;
__imag__ result = M_LOG10El * __ieee754_atan2l (__imag__ x, __real__ x);
}
else
diff --git a/math/s_clogf.c b/math/s_clogf.c
index eb8433a..0b27506 100644
--- a/math/s_clogf.c
+++ b/math/s_clogf.c
@@ -1,5 +1,5 @@
/* Compute complex natural logarithm.
- Copyright (C) 1997, 2011 Free Software Foundation, Inc.
+ Copyright (C) 1997-2012 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
@@ -19,9 +19,8 @@
#include <complex.h>
#include <math.h>
-
#include <math_private.h>
-
+#include <float.h>
__complex__ float
__clogf (__complex__ float x)
@@ -41,8 +40,27 @@ __clogf (__complex__ float x)
else if (__builtin_expect (rcls != FP_NAN && icls != FP_NAN, 1))
{
/* Neither real nor imaginary part is NaN. */
- __real__ result = __ieee754_logf (__ieee754_hypotf (__real__ x,
- __imag__ x));
+ float d;
+ int scale = 0;
+
+ if (fabsf (__real__ x) > FLT_MAX / 2.0f
+ || fabsf (__imag__ x) > FLT_MAX / 2.0f)
+ {
+ scale = -1;
+ __real__ x = __scalbnf (__real__ x, scale);
+ __imag__ x = __scalbnf (__imag__ x, scale);
+ }
+ else if (fabsf (__real__ x) < FLT_MIN
+ && fabsf (__imag__ x) < FLT_MIN)
+ {
+ scale = FLT_MANT_DIG;
+ __real__ x = __scalbnf (__real__ x, scale);
+ __imag__ x = __scalbnf (__imag__ x, scale);
+ }
+
+ d = __ieee754_hypotf (__real__ x, __imag__ x);
+
+ __real__ result = __ieee754_logf (d) - scale * (float) M_LN2;
__imag__ result = __ieee754_atan2f (__imag__ x, __real__ x);
}
else
diff --git a/math/s_clogl.c b/math/s_clogl.c
index 11d4878..8968eef 100644
--- a/math/s_clogl.c
+++ b/math/s_clogl.c
@@ -1,5 +1,5 @@
/* Compute complex natural logarithm.
- Copyright (C) 1997, 1998, 2011 Free Software Foundation, Inc.
+ Copyright (C) 1997-2012 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
@@ -20,7 +20,7 @@
#include <complex.h>
#include <math.h>
#include <math_private.h>
-
+#include <float.h>
__complex__ long double
__clogl (__complex__ long double x)
@@ -40,8 +40,27 @@ __clogl (__complex__ long double x)
else if (__builtin_expect (rcls != FP_NAN && icls != FP_NAN, 1))
{
/* Neither real nor imaginary part is NaN. */
- __real__ result = __ieee754_logl (__ieee754_hypotl (__real__ x,
- __imag__ x));
+ long double d;
+ int scale = 0;
+
+ if (fabsl (__real__ x) > LDBL_MAX / 2.0L
+ || fabsl (__imag__ x) > LDBL_MAX / 2.0L)
+ {
+ scale = -1;
+ __real__ x = __scalbnl (__real__ x, scale);
+ __imag__ x = __scalbnl (__imag__ x, scale);
+ }
+ else if (fabsl (__real__ x) < LDBL_MIN
+ && fabsl (__imag__ x) < LDBL_MIN)
+ {
+ scale = LDBL_MANT_DIG;
+ __real__ x = __scalbnl (__real__ x, scale);
+ __imag__ x = __scalbnl (__imag__ x, scale);
+ }
+
+ d = __ieee754_hypotl (__real__ x, __imag__ x);
+
+ __real__ result = __ieee754_logl (d) - scale * M_LN2l;
__imag__ result = __ieee754_atan2l (__imag__ x, __real__ x);
}
else