diff options
author | Joseph Myers <joseph@codesourcery.com> | 2012-03-19 20:13:10 +0000 |
---|---|---|
committer | Joseph Myers <joseph@codesourcery.com> | 2012-03-19 20:14:26 +0000 |
commit | 1897ad44326bb7761dcda46132ae303f7288aba9 (patch) | |
tree | fd8357b0066902deb5b6b9476b8c456f68ffc56e /math | |
parent | 7726d6a95d5a2c08c8d43186002f040b9b889c27 (diff) | |
download | glibc-1897ad44326bb7761dcda46132ae303f7288aba9.tar.gz glibc-1897ad44326bb7761dcda46132ae303f7288aba9.tar.xz glibc-1897ad44326bb7761dcda46132ae303f7288aba9.zip |
Fix clog overflow/underflow (bug 13629).
Diffstat (limited to 'math')
-rw-r--r-- | math/libm-test.inc | 36 | ||||
-rw-r--r-- | math/s_clog.c | 27 | ||||
-rw-r--r-- | math/s_clog10.c | 28 | ||||
-rw-r--r-- | math/s_clog10f.c | 28 | ||||
-rw-r--r-- | math/s_clog10l.c | 28 | ||||
-rw-r--r-- | math/s_clogf.c | 28 | ||||
-rw-r--r-- | math/s_clogl.c | 27 |
7 files changed, 180 insertions, 22 deletions
diff --git a/math/libm-test.inc b/math/libm-test.inc index 817864aeb2..8bb435875d 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 5bbca00388..15e5e9c678 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 3eb9c518a8..9d366d6f2b 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 e48d928b3c..11bb0bb9ad 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 72b553152e..d1fc872cba 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 eb8433a280..0b27506fb4 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 11d4878252..8968eefee3 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 |