about summary refs log tree commit diff
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.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.c31
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