1 /* Return value of complex exponential function for a float type.
2    Copyright (C) 1997-2018 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 __complex128
cexpq(__complex128 x)23 cexpq (__complex128 x)
24 {
25   __complex128 retval;
26   int rcls = fpclassifyq (__real__ x);
27   int icls = fpclassifyq (__imag__ x);
28 
29   if (__glibc_likely (rcls >= QUADFP_ZERO))
30     {
31       /* Real part is finite.  */
32       if (__glibc_likely (icls >= QUADFP_ZERO))
33 	{
34 	  /* Imaginary part is finite.  */
35 	  const int t = (int) ((FLT128_MAX_EXP - 1) * M_LN2q);
36 	  __float128 sinix, cosix;
37 
38 	  if (__glibc_likely (fabsq (__imag__ x) > FLT128_MIN))
39 	    {
40 	      sincosq (__imag__ x, &sinix, &cosix);
41 	    }
42 	  else
43 	    {
44 	      sinix = __imag__ x;
45 	      cosix = 1;
46 	    }
47 
48 	  if (__real__ x > t)
49 	    {
50 	      __float128 exp_t = expq (t);
51 	      __real__ x -= t;
52 	      sinix *= exp_t;
53 	      cosix *= exp_t;
54 	      if (__real__ x > t)
55 		{
56 		  __real__ x -= t;
57 		  sinix *= exp_t;
58 		  cosix *= exp_t;
59 		}
60 	    }
61 	  if (__real__ x > t)
62 	    {
63 	      /* Overflow (original real part of x > 3t).  */
64 	      __real__ retval = FLT128_MAX * cosix;
65 	      __imag__ retval = FLT128_MAX * sinix;
66 	    }
67 	  else
68 	    {
69 	      __float128 exp_val = expq (__real__ x);
70 	      __real__ retval = exp_val * cosix;
71 	      __imag__ retval = exp_val * sinix;
72 	    }
73 	  math_check_force_underflow_complex (retval);
74 	}
75       else
76 	{
77 	  /* If the imaginary part is +-inf or NaN and the real part
78 	     is not +-inf the result is NaN + iNaN.  */
79 	  __real__ retval = nanq ("");
80 	  __imag__ retval = nanq ("");
81 
82 	  feraiseexcept (FE_INVALID);
83 	}
84     }
85   else if (__glibc_likely (rcls == QUADFP_INFINITE))
86     {
87       /* Real part is infinite.  */
88       if (__glibc_likely (icls >= QUADFP_ZERO))
89 	{
90 	  /* Imaginary part is finite.  */
91 	  __float128 value = signbitq (__real__ x) ? 0 : HUGE_VALQ;
92 
93 	  if (icls == QUADFP_ZERO)
94 	    {
95 	      /* Imaginary part is 0.0.  */
96 	      __real__ retval = value;
97 	      __imag__ retval = __imag__ x;
98 	    }
99 	  else
100 	    {
101 	      __float128 sinix, cosix;
102 
103 	      if (__glibc_likely (fabsq (__imag__ x) > FLT128_MIN))
104 		{
105 		  sincosq (__imag__ x, &sinix, &cosix);
106 		}
107 	      else
108 		{
109 		  sinix = __imag__ x;
110 		  cosix = 1;
111 		}
112 
113 	      __real__ retval = copysignq (value, cosix);
114 	      __imag__ retval = copysignq (value, sinix);
115 	    }
116 	}
117       else if (signbitq (__real__ x) == 0)
118 	{
119 	  __real__ retval = HUGE_VALQ;
120 	  __imag__ retval = __imag__ x - __imag__ x;
121 	}
122       else
123 	{
124 	  __real__ retval = 0;
125 	  __imag__ retval = copysignq (0, __imag__ x);
126 	}
127     }
128   else
129     {
130       /* If the real part is NaN the result is NaN + iNaN unless the
131 	 imaginary part is zero.  */
132       __real__ retval = nanq ("");
133       if (icls == QUADFP_ZERO)
134 	__imag__ retval = __imag__ x;
135       else
136 	{
137 	  __imag__ retval = nanq ("");
138 
139 	  if (rcls != QUADFP_NAN || icls != QUADFP_NAN)
140 	    feraiseexcept (FE_INVALID);
141 	}
142     }
143 
144   return retval;
145 }
146