diff options
author | Joseph Myers <joseph@codesourcery.com> | 2012-03-22 19:38:09 +0000 |
---|---|---|
committer | Joseph Myers <joseph@codesourcery.com> | 2012-03-22 19:38:09 +0000 |
commit | 7c69cd143bacc3dbb7daeac4abf08a321aeeb185 (patch) | |
tree | b28c17e11ccc75dc64b0bd46ebf6203b16fd6b0f /math/s_cexp.c | |
parent | 81b035fe638d677f90200598294d15811dcccf68 (diff) | |
download | glibc-7c69cd143bacc3dbb7daeac4abf08a321aeeb185.tar.gz glibc-7c69cd143bacc3dbb7daeac4abf08a321aeeb185.tar.xz glibc-7c69cd143bacc3dbb7daeac4abf08a321aeeb185.zip |
Fix cexp overflow (bug 13892).
Diffstat (limited to 'math/s_cexp.c')
-rw-r--r-- | math/s_cexp.c | 31 |
1 files changed, 23 insertions, 8 deletions
diff --git a/math/s_cexp.c b/math/s_cexp.c index 82fe8148f7..1d7a5a2c40 100644 --- a/math/s_cexp.c +++ b/math/s_cexp.c @@ -1,5 +1,5 @@ /* Return value of complex exponential function for double complex value. - 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. @@ -21,7 +21,7 @@ #include <fenv.h> #include <math.h> #include <math_private.h> - +#include <float.h> __complex__ double __cexp (__complex__ double x) @@ -36,20 +36,35 @@ __cexp (__complex__ double x) if (__builtin_expect (icls >= FP_ZERO, 1)) { /* Imaginary part is finite. */ - double exp_val = __ieee754_exp (__real__ x); + const int t = (int) ((DBL_MAX_EXP - 1) * M_LN2); double sinix, cosix; __sincos (__imag__ x, &sinix, &cosix); - if (isfinite (exp_val)) + if (__real__ x > t) { - __real__ retval = exp_val * cosix; - __imag__ retval = exp_val * sinix; + double exp_t = __ieee754_exp (t); + __real__ x -= t; + sinix *= exp_t; + cosix *= exp_t; + if (__real__ x > t) + { + __real__ x -= t; + sinix *= exp_t; + cosix *= exp_t; + } + } + if (__real__ x > t) + { + /* Overflow (original real part of x > 3t). */ + __real__ retval = DBL_MAX * cosix; + __imag__ retval = DBL_MAX * sinix; } else { - __real__ retval = __copysign (exp_val, cosix); - __imag__ retval = __copysign (exp_val, sinix); + double exp_val = __ieee754_exp (__real__ x); + __real__ retval = exp_val * cosix; + __imag__ retval = exp_val * sinix; } } else |