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_cexpf.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_cexpf.c')
-rw-r--r-- | math/s_cexpf.c | 31 |
1 files changed, 23 insertions, 8 deletions
diff --git a/math/s_cexpf.c b/math/s_cexpf.c index a9c28ed8c2..4aa9765818 100644 --- a/math/s_cexpf.c +++ b/math/s_cexpf.c @@ -1,5 +1,5 @@ /* Return value of complex exponential function for float 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__ float __cexpf (__complex__ float x) @@ -36,20 +36,35 @@ __cexpf (__complex__ float x) if (__builtin_expect (icls >= FP_ZERO, 1)) { /* Imaginary part is finite. */ - float exp_val = __ieee754_expf (__real__ x); + const int t = (int) ((FLT_MAX_EXP - 1) * M_LN2); float sinix, cosix; __sincosf (__imag__ x, &sinix, &cosix); - if (isfinite (exp_val)) + if (__real__ x > t) { - __real__ retval = exp_val * cosix; - __imag__ retval = exp_val * sinix; + float exp_t = __ieee754_expf (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 = FLT_MAX * cosix; + __imag__ retval = FLT_MAX * sinix; } else { - __real__ retval = __copysignf (exp_val, cosix); - __imag__ retval = __copysignf (exp_val, sinix); + float exp_val = __ieee754_expf (__real__ x); + __real__ retval = exp_val * cosix; + __imag__ retval = exp_val * sinix; } } else |