summaryrefslogtreecommitdiff
path: root/math/s_cexpl.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_cexpl.c
parent81b035fe638d677f90200598294d15811dcccf68 (diff)
Fix cexp overflow (bug 13892).
Diffstat (limited to 'math/s_cexpl.c')
-rw-r--r--math/s_cexpl.c31
1 files changed, 23 insertions, 8 deletions
diff --git a/math/s_cexpl.c b/math/s_cexpl.c
index 3059880dbc..256824924f 100644
--- a/math/s_cexpl.c
+++ b/math/s_cexpl.c
@@ -1,5 +1,5 @@
/* Return value of complex exponential function for long 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__ long double
__cexpl (__complex__ long double x)
@@ -36,20 +36,35 @@ __cexpl (__complex__ long double x)
if (__builtin_expect (icls >= FP_ZERO, 1))
{
/* Imaginary part is finite. */
- long double exp_val = __ieee754_expl (__real__ x);
+ const int t = (int) ((LDBL_MAX_EXP - 1) * M_LN2l);
long double sinix, cosix;
__sincosl (__imag__ x, &sinix, &cosix);
- if (isfinite (exp_val))
+ if (__real__ x > t)
{
- __real__ retval = exp_val * cosix;
- __imag__ retval = exp_val * sinix;
+ long double exp_t = __ieee754_expl (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 = LDBL_MAX * cosix;
+ __imag__ retval = LDBL_MAX * sinix;
}
else
{
- __real__ retval = __copysignl (exp_val, cosix);
- __imag__ retval = __copysignl (exp_val, sinix);
+ long double exp_val = __ieee754_expl (__real__ x);
+ __real__ retval = exp_val * cosix;
+ __imag__ retval = exp_val * sinix;
}
}
else