S/390: Fix uc_link == NULL handling for makecontext
[platform/upstream/glibc.git] / math / s_cexp.c
1 /* Return value of complex exponential function for double complex 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 <complex.h>
21 #include <fenv.h>
22 #include <math.h>
23 #include <math_private.h>
24 #include <float.h>
25
26 __complex__ double
27 __cexp (__complex__ double x)
28 {
29   __complex__ double 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) ((DBL_MAX_EXP - 1) * M_LN2);
40           double sinix, cosix;
41
42           __sincos (__imag__ x, &sinix, &cosix);
43
44           if (__real__ x > t)
45             {
46               double exp_t = __ieee754_exp (t);
47               __real__ x -= t;
48               sinix *= exp_t;
49               cosix *= exp_t;
50               if (__real__ x > t)
51                 {
52                   __real__ x -= t;
53                   sinix *= exp_t;
54                   cosix *= exp_t;
55                 }
56             }
57           if (__real__ x > t)
58             {
59               /* Overflow (original real part of x > 3t).  */
60               __real__ retval = DBL_MAX * cosix;
61               __imag__ retval = DBL_MAX * sinix;
62             }
63           else
64             {
65               double exp_val = __ieee754_exp (__real__ x);
66               __real__ retval = exp_val * cosix;
67               __imag__ retval = exp_val * sinix;
68             }
69         }
70       else
71         {
72           /* If the imaginary part is +-inf or NaN and the real part
73              is not +-inf the result is NaN + iNaN.  */
74           __real__ retval = __nan ("");
75           __imag__ retval = __nan ("");
76
77           feraiseexcept (FE_INVALID);
78         }
79     }
80   else if (__builtin_expect (rcls == FP_INFINITE, 1))
81     {
82       /* Real part is infinite.  */
83       if (__builtin_expect (icls >= FP_ZERO, 1))
84         {
85           /* Imaginary part is finite.  */
86           double value = signbit (__real__ x) ? 0.0 : HUGE_VAL;
87
88           if (icls == FP_ZERO)
89             {
90               /* Imaginary part is 0.0.  */
91               __real__ retval = value;
92               __imag__ retval = __imag__ x;
93             }
94           else
95             {
96               double sinix, cosix;
97
98               __sincos (__imag__ x, &sinix, &cosix);
99
100               __real__ retval = __copysign (value, cosix);
101               __imag__ retval = __copysign (value, sinix);
102             }
103         }
104       else if (signbit (__real__ x) == 0)
105         {
106           __real__ retval = HUGE_VAL;
107           __imag__ retval = __nan ("");
108
109           if (icls == FP_INFINITE)
110             feraiseexcept (FE_INVALID);
111         }
112       else
113         {
114           __real__ retval = 0.0;
115           __imag__ retval = __copysign (0.0, __imag__ x);
116         }
117     }
118   else
119     {
120       /* If the real part is NaN the result is NaN + iNaN.  */
121       __real__ retval = __nan ("");
122       __imag__ retval = __nan ("");
123
124       if (rcls != FP_NAN || icls != FP_NAN)
125         feraiseexcept (FE_INVALID);
126     }
127
128   return retval;
129 }
130 weak_alias (__cexp, cexp)
131 #ifdef NO_LONG_DOUBLE
132 strong_alias (__cexp, __cexpl)
133 weak_alias (__cexp, cexpl)
134 #endif