Update.
[jlayton/glibc.git] / sysdeps / generic / s_cexpl.c
1 /* Return value of complex exponential function for long 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 Library General Public License as
8    published by the Free Software Foundation; either version 2 of the
9    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    Library General Public License for more details.
15
16    You should have received a copy of the GNU Library General Public
17    License along with the GNU C Library; see the file COPYING.LIB.  If not,
18    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19    Boston, MA 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__ long double
29 __cexpl (__complex__ long double x)
30 {
31   __complex__ long 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           long double exp_val = __ieee754_expl (__real__ x);
42           long double sinix, cosix;
43
44           __sincosl (__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 = __copysignl (exp_val, cosix);
54               __imag__ retval = __copysignl (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 = __nanl ("");
62           __imag__ retval = __nanl ("");
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           long double value = signbit (__real__ x) ? 0.0 : HUGE_VALL;
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               long double sinix, cosix;
86
87               __sincosl (__imag__ x, &sinix, &cosix);
88
89               __real__ retval = __copysignl (value, cosix);
90               __imag__ retval = __copysignl (value, sinix);
91             }
92         }
93       else if (signbit (__real__ x) == 0)
94         {
95           __real__ retval = HUGE_VALL;
96           __imag__ retval = __nanl ("");
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 = __copysignl (0.0, __imag__ x);
107         }
108     }
109   else
110     {
111       /* If the real part is NaN the result is NaN + iNaN.  */
112       __real__ retval = __nanl ("");
113       __imag__ retval = __nanl ("");
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 (__cexpl, cexpl)