2012-03-23 Daniel Jacobowitz <dmj@google.com>
[platform/upstream/linaro-glibc.git] / math / s_csinhf.c
1 /* Complex sine hyperbole function for float.
2    Copyright (C) 1997, 2011 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
24 #include <math_private.h>
25
26
27 __complex__ float
28 __csinhf (__complex__ float x)
29 {
30   __complex__ float retval;
31   int negate = signbit (__real__ x);
32   int rcls = fpclassify (__real__ x);
33   int icls = fpclassify (__imag__ x);
34
35   __real__ x = fabsf (__real__ x);
36
37   if (__builtin_expect (rcls >= FP_ZERO, 1))
38     {
39       /* Real part is finite.  */
40       if (__builtin_expect (icls >= FP_ZERO, 1))
41         {
42           /* Imaginary part is finite.  */
43           float sinh_val = __ieee754_sinhf (__real__ x);
44           float cosh_val = __ieee754_coshf (__real__ x);
45           float sinix, cosix;
46
47           __sincosf (__imag__ x, &sinix, &cosix);
48
49           __real__ retval = sinh_val * cosix;
50           __imag__ retval = cosh_val * sinix;
51
52           if (negate)
53             __real__ retval = -__real__ retval;
54         }
55       else
56         {
57           if (rcls == FP_ZERO)
58             {
59               /* Real part is 0.0.  */
60               __real__ retval = __copysignf (0.0, negate ? -1.0 : 1.0);
61               __imag__ retval = __nanf ("") + __nanf ("");
62
63               if (icls == FP_INFINITE)
64                 feraiseexcept (FE_INVALID);
65             }
66           else
67             {
68               __real__ retval = __nanf ("");
69               __imag__ retval = __nanf ("");
70
71               feraiseexcept (FE_INVALID);
72             }
73         }
74     }
75   else if (__builtin_expect (rcls == FP_INFINITE, 1))
76     {
77       /* Real part is infinite.  */
78       if (__builtin_expect (icls > FP_ZERO, 1))
79         {
80           /* Imaginary part is finite.  */
81           float sinix, cosix;
82
83           __sincosf (__imag__ x, &sinix, &cosix);
84
85           __real__ retval = __copysignf (HUGE_VALF, cosix);
86           __imag__ retval = __copysignf (HUGE_VALF, sinix);
87
88           if (negate)
89             __real__ retval = -__real__ retval;
90         }
91       else if (icls == FP_ZERO)
92         {
93           /* Imaginary part is 0.0.  */
94           __real__ retval = negate ? -HUGE_VALF : HUGE_VALF;
95           __imag__ retval = __imag__ x;
96         }
97       else
98         {
99           /* The addition raises the invalid exception.  */
100           __real__ retval = HUGE_VALF;
101           __imag__ retval = __nanf ("") + __nanf ("");
102
103 #ifdef FE_INVALID
104           if (icls == FP_INFINITE)
105             feraiseexcept (FE_INVALID);
106 #endif
107         }
108     }
109   else
110     {
111       __real__ retval = __nanf ("");
112       __imag__ retval = __imag__ x == 0.0 ? __imag__ x : __nanf ("");
113     }
114
115   return retval;
116 }
117 #ifndef __csinhf
118 weak_alias (__csinhf, csinhf)
119 #endif