aboutsummaryrefslogtreecommitdiff
path: root/math/s_cexp.c
diff options
context:
space:
mode:
authorJoseph Myers <joseph@codesourcery.com>2012-03-22 19:38:09 +0000
committerJoseph Myers <joseph@codesourcery.com>2012-03-22 19:38:09 +0000
commit7c69cd143bacc3dbb7daeac4abf08a321aeeb185 (patch)
treeb28c17e11ccc75dc64b0bd46ebf6203b16fd6b0f /math/s_cexp.c
parent81b035fe638d677f90200598294d15811dcccf68 (diff)
downloadglibc-7c69cd143bacc3dbb7daeac4abf08a321aeeb185.zip
glibc-7c69cd143bacc3dbb7daeac4abf08a321aeeb185.tar.gz
glibc-7c69cd143bacc3dbb7daeac4abf08a321aeeb185.tar.bz2
Fix cexp overflow (bug 13892).
Diffstat (limited to 'math/s_cexp.c')
-rw-r--r--math/s_cexp.c31
1 files changed, 23 insertions, 8 deletions
diff --git a/math/s_cexp.c b/math/s_cexp.c
index 82fe814..1d7a5a2 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