1/* Complex cosine hyperbolic function for float types.
2   Copyright (C) 1997-2018 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 "quadmath-imp.h"
21
22__complex128
23ccoshq (__complex128 x)
24{
25  __complex128 retval;
26  int rcls = fpclassifyq (__real__ x);
27  int icls = fpclassifyq (__imag__ x);
28
29  if (__glibc_likely (rcls >= QUADFP_ZERO))
30    {
31      /* Real part is finite.  */
32      if (__glibc_likely (icls >= QUADFP_ZERO))
33	{
34	  /* Imaginary part is finite.  */
35	  const int t = (int) ((FLT128_MAX_EXP - 1) * M_LN2q);
36	  __float128 sinix, cosix;
37
38	  if (__glibc_likely (fabsq (__imag__ x) > FLT128_MIN))
39	    {
40	      sincosq (__imag__ x, &sinix, &cosix);
41	    }
42	  else
43	    {
44	      sinix = __imag__ x;
45	      cosix = 1;
46	    }
47
48	  if (fabsq (__real__ x) > t)
49	    {
50	      __float128 exp_t = expq (t);
51	      __float128 rx = fabsq (__real__ x);
52	      if (signbitq (__real__ x))
53		sinix = -sinix;
54	      rx -= t;
55	      sinix *= exp_t / 2;
56	      cosix *= exp_t / 2;
57	      if (rx > t)
58		{
59		  rx -= t;
60		  sinix *= exp_t;
61		  cosix *= exp_t;
62		}
63	      if (rx > t)
64		{
65		  /* Overflow (original real part of x > 3t).  */
66		  __real__ retval = FLT128_MAX * cosix;
67		  __imag__ retval = FLT128_MAX * sinix;
68		}
69	      else
70		{
71		  __float128 exp_val = expq (rx);
72		  __real__ retval = exp_val * cosix;
73		  __imag__ retval = exp_val * sinix;
74		}
75	    }
76	  else
77	    {
78	      __real__ retval = coshq (__real__ x) * cosix;
79	      __imag__ retval = sinhq (__real__ x) * sinix;
80	    }
81
82	  math_check_force_underflow_complex (retval);
83	}
84      else
85	{
86	  __imag__ retval = __real__ x == 0 ? 0 : nanq ("");
87	  __real__ retval = __imag__ x - __imag__ x;
88	}
89    }
90  else if (rcls == QUADFP_INFINITE)
91    {
92      /* Real part is infinite.  */
93      if (__glibc_likely (icls > QUADFP_ZERO))
94	{
95	  /* Imaginary part is finite.  */
96	  __float128 sinix, cosix;
97
98	  if (__glibc_likely (fabsq (__imag__ x) > FLT128_MIN))
99	    {
100	      sincosq (__imag__ x, &sinix, &cosix);
101	    }
102	  else
103	    {
104	      sinix = __imag__ x;
105	      cosix = 1;
106	    }
107
108	  __real__ retval = copysignq (HUGE_VALQ, cosix);
109	  __imag__ retval = (copysignq (HUGE_VALQ, sinix)
110			     * copysignq (1, __real__ x));
111	}
112      else if (icls == QUADFP_ZERO)
113	{
114	  /* Imaginary part is 0.0.  */
115	  __real__ retval = HUGE_VALQ;
116	  __imag__ retval = __imag__ x * copysignq (1, __real__ x);
117	}
118      else
119	{
120	  __real__ retval = HUGE_VALQ;
121	  __imag__ retval = __imag__ x - __imag__ x;
122	}
123    }
124  else
125    {
126      __real__ retval = nanq ("");
127      __imag__ retval = __imag__ x == 0 ? __imag__ x : nanq ("");
128    }
129
130  return retval;
131}
132