2.5-18.1
[jlayton/glibc.git] / math / s_cexp.c
1 /* Return value of complex exponential function for double complex value.
2    Copyright (C) 1997 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, write to the Free
18    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19    02111-1307 USA.  */
20
21 #include <complex.h>
22 #include <fenv.h>
23 #include <math.h>
24
25 #include "math_private.h"
26
27
28 __complex__ double
29 __cexp (__complex__ double x)
30 {
31   __complex__ double retval;
32   int rcls = fpclassify (__real__ x);
33   int icls = fpclassify (__imag__ x);
34
35   if (rcls >= FP_ZERO)
36     {
37       /* Real part is finite.  */
38       if (icls >= FP_ZERO)
39         {
40           /* Imaginary part is finite.  */
41           double exp_val = __ieee754_exp (__real__ x);
42           double sinix, cosix;
43
44           __sincos (__imag__ x, &sinix, &cosix);
45
46           if (isfinite (exp_val))
47             {
48               __real__ retval = exp_val * cosix;
49               __imag__ retval = exp_val * sinix;
50             }
51           else
52             {
53               __real__ retval = __copysign (exp_val, cosix);
54               __imag__ retval = __copysign (exp_val, sinix);
55             }
56         }
57       else
58         {
59           /* If the imaginary part is +-inf or NaN and the real part
60              is not +-inf the result is NaN + iNaN.  */
61           __real__ retval = __nan ("");
62           __imag__ retval = __nan ("");
63
64 #ifdef FE_INVALID
65           feraiseexcept (FE_INVALID);
66 #endif
67         }
68     }
69   else if (rcls == FP_INFINITE)
70     {
71       /* Real part is infinite.  */
72       if (icls >= FP_ZERO)
73         {
74           /* Imaginary part is finite.  */
75           double value = signbit (__real__ x) ? 0.0 : HUGE_VAL;
76
77           if (icls == FP_ZERO)
78             {
79               /* Imaginary part is 0.0.  */
80               __real__ retval = value;
81               __imag__ retval = __imag__ x;
82             }
83           else
84             {
85               double sinix, cosix;
86
87               __sincos (__imag__ x, &sinix, &cosix);
88
89               __real__ retval = __copysign (value, cosix);
90               __imag__ retval = __copysign (value, sinix);
91             }
92         }
93       else if (signbit (__real__ x) == 0)
94         {
95           __real__ retval = HUGE_VAL;
96           __imag__ retval = __nan ("");
97
98 #ifdef FE_INVALID
99           if (icls == FP_INFINITE)
100             feraiseexcept (FE_INVALID);
101 #endif
102         }
103       else
104         {
105           __real__ retval = 0.0;
106           __imag__ retval = __copysign (0.0, __imag__ x);
107         }
108     }
109   else
110     {
111       /* If the real part is NaN the result is NaN + iNaN.  */
112       __real__ retval = __nan ("");
113       __imag__ retval = __nan ("");
114
115 #ifdef FE_INVALID
116       if (rcls != FP_NAN || icls != FP_NAN)
117         feraiseexcept (FE_INVALID);
118 #endif
119     }
120
121   return retval;
122 }
123 weak_alias (__cexp, cexp)
124 #ifdef NO_LONG_DOUBLE
125 strong_alias (__cexp, __cexpl)
126 weak_alias (__cexp, cexpl)
127 #endif