2012-03-23 Daniel Jacobowitz <dmj@google.com>
[platform/upstream/linaro-glibc.git] / math / s_csin.c
1 /* Complex sine function for double.
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__ double
28 __csin (__complex__ double x)
29 {
30   __complex__ double retval;
31   int negate = signbit (__real__ x);
32   int rcls = fpclassify (__real__ x);
33   int icls = fpclassify (__imag__ x);
34
35   __real__ x = fabs (__real__ x);
36
37   if (__builtin_expect (icls >= FP_ZERO, 1))
38     {
39       /* Imaginary part is finite.  */
40       if (__builtin_expect (rcls >= FP_ZERO, 1))
41         {
42           /* Real part is finite.  */
43           double sinh_val = __ieee754_sinh (__imag__ x);
44           double cosh_val = __ieee754_cosh (__imag__ x);
45           double sinix, cosix;
46
47           __sincos (__real__ x, &sinix, &cosix);
48
49           __real__ retval = cosh_val * sinix;
50           __imag__ retval = sinh_val * cosix;
51
52           if (negate)
53             __real__ retval = -__real__ retval;
54         }
55       else
56         {
57           if (icls == FP_ZERO)
58             {
59               /* Imaginary part is 0.0.  */
60               __real__ retval = __nan ("");
61               __imag__ retval = __imag__ x;
62
63               if (rcls == FP_INFINITE)
64                 feraiseexcept (FE_INVALID);
65             }
66           else
67             {
68               __real__ retval = __nan ("");
69               __imag__ retval = __nan ("");
70
71               feraiseexcept (FE_INVALID);
72             }
73         }
74     }
75   else if (icls == FP_INFINITE)
76     {
77       /* Imaginary part is infinite.  */
78       if (rcls == FP_ZERO)
79         {
80           /* Real part is 0.0.  */
81           __real__ retval = __copysign (0.0, negate ? -1.0 : 1.0);
82           __imag__ retval = __imag__ x;
83         }
84       else if (rcls > FP_ZERO)
85         {
86           /* Real part is finite.  */
87           double sinix, cosix;
88
89           __sincos (__real__ x, &sinix, &cosix);
90
91           __real__ retval = __copysign (HUGE_VAL, sinix);
92           __imag__ retval = __copysign (HUGE_VAL, cosix);
93
94           if (negate)
95             __real__ retval = -__real__ retval;
96           if (signbit (__imag__ x))
97             __imag__ retval = -__imag__ retval;
98         }
99       else
100         {
101           /* The addition raises the invalid exception.  */
102           __real__ retval = __nan ("");
103           __imag__ retval = HUGE_VAL;
104
105           if (rcls == FP_INFINITE)
106             feraiseexcept (FE_INVALID);
107         }
108     }
109   else
110     {
111       if (rcls == FP_ZERO)
112         __real__ retval = __copysign (0.0, negate ? -1.0 : 1.0);
113       else
114         __real__ retval = __nan ("");
115       __imag__ retval = __nan ("");
116     }
117
118   return retval;
119 }
120 weak_alias (__csin, csin)
121 #ifdef NO_LONG_DOUBLE
122 strong_alias (__csin, __csinl)
123 weak_alias (__csin, csinl)
124 #endif