1 /* Return value of complex exponential function for complex __float128 value.
2    Copyright (C) 1997-2012 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
5 
6    The GNU C Library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Lesser General Public
8    License as published by the Free Software Foundation; either
9    version 2.1 of the License, or (at your option) any later version.
10 
11    The GNU C Library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Lesser General Public License for more details.
15 
16    You should have received a copy of the GNU Lesser General Public
17    License along with the GNU C Library; if not, see
18    <http://www.gnu.org/licenses/>.  */
19 
20 #include "quadmath-imp.h"
21 
22 #ifdef HAVE_FENV_H
23 # include <fenv.h>
24 #endif
25 
26 
27 __complex128
cexpq(__complex128 x)28 cexpq (__complex128 x)
29 {
30   __complex128 retval;
31   int rcls = fpclassifyq (__real__ x);
32   int icls = fpclassifyq (__imag__ x);
33 
34   if (__builtin_expect (rcls >= QUADFP_ZERO, 1))
35     {
36       /* Real part is finite.  */
37       if (__builtin_expect (icls >= QUADFP_ZERO, 1))
38 	{
39 	  /* Imaginary part is finite.  */
40 	  const int t = (int) ((FLT128_MAX_EXP - 1) * M_LN2q);
41 	  __float128 sinix, cosix;
42 
43 	  if (__builtin_expect (icls != QUADFP_SUBNORMAL, 1))
44 	    {
45 	      sincosq (__imag__ x, &sinix, &cosix);
46 	    }
47 	  else
48 	    {
49 	      sinix = __imag__ x;
50 	      cosix = 1.0Q;
51 	    }
52 
53 	  if (__real__ x > t)
54 	    {
55 	      __float128 exp_t = expq (t);
56 	      __real__ x -= t;
57 	      sinix *= exp_t;
58 	      cosix *= exp_t;
59 	      if (__real__ x > t)
60 		{
61 		  __real__ x -= t;
62 		  sinix *= exp_t;
63 		  cosix *= exp_t;
64 		}
65 	    }
66 	  if (__real__ x > t)
67 	    {
68 	      /* Overflow (original real part of x > 3t).  */
69 	      __real__ retval = FLT128_MAX * cosix;
70 	      __imag__ retval = FLT128_MAX * sinix;
71 	    }
72 	  else
73 	    {
74 	      __float128 exp_val = expq (__real__ x);
75 	      __real__ retval = exp_val * cosix;
76 	      __imag__ retval = exp_val * sinix;
77 	    }
78 	}
79       else
80 	{
81 	  /* If the imaginary part is +-inf or NaN and the real part
82 	     is not +-inf the result is NaN + iNaN.  */
83 	  __real__ retval = nanq ("");
84 	  __imag__ retval = nanq ("");
85 
86 #ifdef HAVE_FENV_H
87 	  feraiseexcept (FE_INVALID);
88 #endif
89 	}
90     }
91   else if (__builtin_expect (rcls == QUADFP_INFINITE, 1))
92     {
93       /* Real part is infinite.  */
94       if (__builtin_expect (icls >= QUADFP_ZERO, 1))
95 	{
96 	  /* Imaginary part is finite.  */
97 	  __float128 value = signbitq (__real__ x) ? 0.0Q : HUGE_VALQ;
98 
99 	  if (icls == QUADFP_ZERO)
100 	    {
101 	      /* Imaginary part is 0.0.  */
102 	      __real__ retval = value;
103 	      __imag__ retval = __imag__ x;
104 	    }
105 	  else
106 	    {
107 	      __float128 sinix, cosix;
108 
109 	      if (__builtin_expect (icls != QUADFP_SUBNORMAL, 1))
110 		{
111 		  sincosq (__imag__ x, &sinix, &cosix);
112 		}
113 	      else
114 		{
115 		  sinix = __imag__ x;
116 		  cosix = 1.0Q;
117 		}
118 
119 	      __real__ retval = copysignq (value, cosix);
120 	      __imag__ retval = copysignq (value, sinix);
121 	    }
122 	}
123       else if (signbitq (__real__ x) == 0)
124 	{
125 	  __real__ retval = HUGE_VALQ;
126 	  __imag__ retval = nanq ("");
127 
128 #ifdef HAVE_FENV_H
129 	  if (icls == QUADFP_INFINITE)
130 	    feraiseexcept (FE_INVALID);
131 #endif
132 	}
133       else
134 	{
135 	  __real__ retval = 0.0Q;
136 	  __imag__ retval = copysignq (0.0Q, __imag__ x);
137 	}
138     }
139   else
140     {
141       /* If the real part is NaN the result is NaN + iNaN.  */
142       __real__ retval = nanq ("");
143       __imag__ retval = nanq ("");
144 
145 #ifdef HAVE_FENV_H
146       if (rcls != QUADFP_NAN || icls != QUADFP_NAN)
147 	feraiseexcept (FE_INVALID);
148 #endif
149     }
150 
151   return retval;
152 }
153