8bfc7e251dd9775d21eaac3da41cc15fdea81263
[jlayton/glibc.git] / math / s_cexpf.c
1 /* Return value of complex exponential function for float complex value.
2    Copyright (C) 1997-2014 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 <complex.h>
21 #include <fenv.h>
22 #include <math.h>
23 #include <math_private.h>
24 #include <float.h>
25
26 __complex__ float
27 __cexpf (__complex__ float x)
28 {
29   __complex__ float retval;
30   int rcls = fpclassify (__real__ x);
31   int icls = fpclassify (__imag__ x);
32
33   if (__builtin_expect (rcls >= FP_ZERO, 1))
34     {
35       /* Real part is finite.  */
36       if (__builtin_expect (icls >= FP_ZERO, 1))
37         {
38           /* Imaginary part is finite.  */
39           const int t = (int) ((FLT_MAX_EXP - 1) * M_LN2);
40           float sinix, cosix;
41
42           if (__builtin_expect (icls != FP_SUBNORMAL, 1))
43             {
44               __sincosf (__imag__ x, &sinix, &cosix);
45             }
46           else
47             {
48               sinix = __imag__ x;
49               cosix = 1.0f;
50             }
51
52           if (__real__ x > t)
53             {
54               float exp_t = __ieee754_expf (t);
55               __real__ x -= t;
56               sinix *= exp_t;
57               cosix *= exp_t;
58               if (__real__ x > t)
59                 {
60                   __real__ x -= t;
61                   sinix *= exp_t;
62                   cosix *= exp_t;
63                 }
64             }
65           if (__real__ x > t)
66             {
67               /* Overflow (original real part of x > 3t).  */
68               __real__ retval = FLT_MAX * cosix;
69               __imag__ retval = FLT_MAX * sinix;
70             }
71           else
72             {
73               float exp_val = __ieee754_expf (__real__ x);
74               __real__ retval = exp_val * cosix;
75               __imag__ retval = exp_val * sinix;
76             }
77           if (fabsf (__real__ retval) < FLT_MIN)
78             {
79               volatile float force_underflow
80                 = __real__ retval * __real__ retval;
81               (void) force_underflow;
82             }
83           if (fabsf (__imag__ retval) < FLT_MIN)
84             {
85               volatile float force_underflow
86                 = __imag__ retval * __imag__ retval;
87               (void) force_underflow;
88             }
89         }
90       else
91         {
92           /* If the imaginary part is +-inf or NaN and the real part
93              is not +-inf the result is NaN + iNaN.  */
94           __real__ retval = __nanf ("");
95           __imag__ retval = __nanf ("");
96
97           feraiseexcept (FE_INVALID);
98         }
99     }
100   else if (__builtin_expect (rcls == FP_INFINITE, 1))
101     {
102       /* Real part is infinite.  */
103       if (__builtin_expect (icls >= FP_ZERO, 1))
104         {
105           /* Imaginary part is finite.  */
106           float value = signbit (__real__ x) ? 0.0 : HUGE_VALF;
107
108           if (icls == FP_ZERO)
109             {
110               /* Imaginary part is 0.0.  */
111               __real__ retval = value;
112               __imag__ retval = __imag__ x;
113             }
114           else
115             {
116               float sinix, cosix;
117
118               if (__builtin_expect (icls != FP_SUBNORMAL, 1))
119                 {
120                   __sincosf (__imag__ x, &sinix, &cosix);
121                 }
122               else
123                 {
124                   sinix = __imag__ x;
125                   cosix = 1.0f;
126                 }
127
128               __real__ retval = __copysignf (value, cosix);
129               __imag__ retval = __copysignf (value, sinix);
130             }
131         }
132       else if (signbit (__real__ x) == 0)
133         {
134           __real__ retval = HUGE_VALF;
135           __imag__ retval = __nanf ("");
136
137           if (icls == FP_INFINITE)
138             feraiseexcept (FE_INVALID);
139         }
140       else
141         {
142           __real__ retval = 0.0;
143           __imag__ retval = __copysignf (0.0, __imag__ x);
144         }
145     }
146   else
147     {
148       /* If the real part is NaN the result is NaN + iNaN unless the
149          imaginary part is zero.  */
150       __real__ retval = __nanf ("");
151       if (icls == FP_ZERO)
152         __imag__ retval = __imag__ x;
153       else
154         {
155           __imag__ retval = __nanf ("");
156
157           if (rcls != FP_NAN || icls != FP_NAN)
158             feraiseexcept (FE_INVALID);
159         }
160     }
161
162   return retval;
163 }
164 #ifndef __cexpf
165 weak_alias (__cexpf, cexpf)
166 #endif