Fix casinh inaccuracy near i, imaginary part > 1 (bug 15307).
[platform/upstream/glibc.git] / math / s_cexpf.c
1 /* Return value of complex exponential function for float complex value.
2    Copyright (C) 1997-2013 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         }
78       else
79         {
80           /* If the imaginary part is +-inf or NaN and the real part
81              is not +-inf the result is NaN + iNaN.  */
82           __real__ retval = __nanf ("");
83           __imag__ retval = __nanf ("");
84
85           feraiseexcept (FE_INVALID);
86         }
87     }
88   else if (__builtin_expect (rcls == FP_INFINITE, 1))
89     {
90       /* Real part is infinite.  */
91       if (__builtin_expect (icls >= FP_ZERO, 1))
92         {
93           /* Imaginary part is finite.  */
94           float value = signbit (__real__ x) ? 0.0 : HUGE_VALF;
95
96           if (icls == FP_ZERO)
97             {
98               /* Imaginary part is 0.0.  */
99               __real__ retval = value;
100               __imag__ retval = __imag__ x;
101             }
102           else
103             {
104               float sinix, cosix;
105
106               if (__builtin_expect (icls != FP_SUBNORMAL, 1))
107                 {
108                   __sincosf (__imag__ x, &sinix, &cosix);
109                 }
110               else
111                 {
112                   sinix = __imag__ x;
113                   cosix = 1.0f;
114                 }
115
116               __real__ retval = __copysignf (value, cosix);
117               __imag__ retval = __copysignf (value, sinix);
118             }
119         }
120       else if (signbit (__real__ x) == 0)
121         {
122           __real__ retval = HUGE_VALF;
123           __imag__ retval = __nanf ("");
124
125           if (icls == FP_INFINITE)
126             feraiseexcept (FE_INVALID);
127         }
128       else
129         {
130           __real__ retval = 0.0;
131           __imag__ retval = __copysignf (0.0, __imag__ x);
132         }
133     }
134   else
135     {
136       /* If the real part is NaN the result is NaN + iNaN.  */
137       __real__ retval = __nanf ("");
138       __imag__ retval = __nanf ("");
139
140       if (rcls != FP_NAN || icls != FP_NAN)
141         feraiseexcept (FE_INVALID);
142     }
143
144   return retval;
145 }
146 #ifndef __cexpf
147 weak_alias (__cexpf, cexpf)
148 #endif