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 = 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}
123weak_alias (__cexp, cexp)
124#ifdef NO_LONG_DOUBLE
125strong_alias (__cexp, __cexpl)
126weak_alias (__cexp, cexpl)
127#endif
128