1e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott/*
2e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott * Copyright (c) 1999
3e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott * Silicon Graphics Computer Systems, Inc.
4e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott *
5e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott * Copyright (c) 1999
6e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott * Boris Fomitchev
7e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott *
8e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott * This material is provided "as is", with absolutely no warranty expressed
9e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott * or implied. Any use is at your own risk.
10e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott *
11e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott * Permission to use or copy this software for any purpose is hereby granted
12e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott * without fee, provided the above notices are retained on all copies.
13e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott * Permission to modify the code and to distribute modified code is granted,
14e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott * provided the above notices are retained, and a notice that the code was
15e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott * modified is included with the above copyright notice.
16e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott *
17e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott */
18e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#include "stlport_prefix.h"
19e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
20e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
21e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott// Trigonometric and hyperbolic functions for complex<float>,
22e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott// complex<double>, and complex<long double>
23e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#include <complex>
24e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#include <cfloat>
25e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#include <cmath>
26e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
27e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott_STLP_BEGIN_NAMESPACE
28e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
29e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
30e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott//----------------------------------------------------------------------
31e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott// helpers
32e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#if defined (__sgi)
33e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  static const union { unsigned int i; float f; } float_ulimit = { 0x42b2d4fc };
34e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  static const float float_limit = float_ulimit.f;
35e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  static union {
36e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    struct { unsigned int h; unsigned int l; } w;
37e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    double d;
38e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  } double_ulimit = { 0x408633ce, 0x8fb9f87d };
39e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  static const double double_limit = double_ulimit.d;
40e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  static union {
41e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    struct { unsigned int h[2]; unsigned int l[2]; } w;
42e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    long double ld;
43e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  } ldouble_ulimit = {0x408633ce, 0x8fb9f87e, 0xbd23b659, 0x4e9bd8b1};
44e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#  if !defined (_STLP_NO_LONG_DOUBLE)
457eced231853cc34e9f2710a81664dee108176317Andrew Hsieh#    define ldouble_limit ldouble_ulimit.ld
46e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#  endif
47e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#else
48e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#  if defined (M_LN2) && defined (FLT_MAX_EXP)
49e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  static const float float_limit = float(M_LN2 * FLT_MAX_EXP);
50e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  static const double double_limit = M_LN2 * DBL_MAX_EXP;
51e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#  else
52e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  static const float float_limit = ::log(FLT_MAX);
53e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  static const double double_limit = ::log(DBL_MAX);
54e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#  endif
55e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#  if !defined (_STLP_NO_LONG_DOUBLE)
56e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#    if defined (M_LN2l)
577eced231853cc34e9f2710a81664dee108176317Andrew Hsieh#      define ldouble_limit (M_LN2l * LDBL_MAX_EXP)
58e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#    else
597eced231853cc34e9f2710a81664dee108176317Andrew Hsieh#      define ldouble_limit ::log(LDBL_MAX)
60e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#    endif
61e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#  endif
62e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#endif
63e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
64e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
65e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott//----------------------------------------------------------------------
66e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott// sin
67e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scotttemplate <class _Tp>
68e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottstatic complex<_Tp> sinT(const complex<_Tp>& z) {
69e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  return complex<_Tp>(::sin(z._M_re) * ::cosh(z._M_im),
70e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott                      ::cos(z._M_re) * ::sinh(z._M_im));
71e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott}
72e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
73e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott_STLP_DECLSPEC complex<float> _STLP_CALL sin(const complex<float>& z)
74e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott{ return sinT(z); }
75e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
76e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott_STLP_DECLSPEC complex<double> _STLP_CALL sin(const complex<double>& z)
77e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott{ return sinT(z); }
78e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
79e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#if !defined (_STLP_NO_LONG_DOUBLE)
80e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott_STLP_DECLSPEC complex<long double> _STLP_CALL sin(const complex<long double>& z)
81e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott{ return sinT(z); }
82e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#endif
83e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
84e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott//----------------------------------------------------------------------
85e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott// cos
86e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scotttemplate <class _Tp>
87e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottstatic complex<_Tp> cosT(const complex<_Tp>& z) {
88e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  return complex<_Tp>(::cos(z._M_re) * ::cosh(z._M_im),
89e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott                     -::sin(z._M_re) * ::sinh(z._M_im));
90e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott}
91e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
92e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott_STLP_DECLSPEC complex<float> _STLP_CALL cos(const complex<float>& z)
93e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott{ return cosT(z); }
94e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
95e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott_STLP_DECLSPEC complex<double> _STLP_CALL cos(const complex<double>& z)
96e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott{ return cosT(z); }
97e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
98e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#if !defined (_STLP_NO_LONG_DOUBLE)
99e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott_STLP_DECLSPEC complex<long double> _STLP_CALL cos(const complex<long double>& z)
100e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott{ return cosT(z); }
101e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#endif
102e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
103e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott//----------------------------------------------------------------------
104e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott// tan
105e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scotttemplate <class _Tp>
106e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottstatic complex<_Tp> tanT(const complex<_Tp>& z, const _Tp& Tp_limit) {
107e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  _Tp re2 = 2.f * z._M_re;
108e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  _Tp im2 = 2.f * z._M_im;
109e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
110e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  if (::abs(im2) > Tp_limit)
111e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    return complex<_Tp>(0.f, (im2 > 0 ? 1.f : -1.f));
112e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  else {
113e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    _Tp den = ::cos(re2) + ::cosh(im2);
114e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    return complex<_Tp>(::sin(re2) / den, ::sinh(im2) / den);
115e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  }
116e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott}
117e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
118e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott_STLP_DECLSPEC complex<float> _STLP_CALL tan(const complex<float>& z)
119e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott{ return tanT(z, float_limit); }
120e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
121e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott_STLP_DECLSPEC complex<double> _STLP_CALL tan(const complex<double>& z)
122e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott{ return tanT(z, double_limit); }
123e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
124e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#if !defined (_STLP_NO_LONG_DOUBLE)
125e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott_STLP_DECLSPEC complex<long double> _STLP_CALL tan(const complex<long double>& z)
126e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott{ return tanT(z, ldouble_limit); }
127e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#endif
128e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
129e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott//----------------------------------------------------------------------
130e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott// sinh
131e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scotttemplate <class _Tp>
132e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottstatic complex<_Tp> sinhT(const complex<_Tp>& z) {
133e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  return complex<_Tp>(::sinh(z._M_re) * ::cos(z._M_im),
134e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott                      ::cosh(z._M_re) * ::sin(z._M_im));
135e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott}
136e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
137e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott_STLP_DECLSPEC complex<float> _STLP_CALL sinh(const complex<float>& z)
138e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott{ return sinhT(z); }
139e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
140e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott_STLP_DECLSPEC complex<double> _STLP_CALL sinh(const complex<double>& z)
141e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott{ return sinhT(z); }
142e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
143e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#if !defined (_STLP_NO_LONG_DOUBLE)
144e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott_STLP_DECLSPEC complex<long double> _STLP_CALL sinh(const complex<long double>& z)
145e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott{ return sinhT(z); }
146e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#endif
147e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
148e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott//----------------------------------------------------------------------
149e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott// cosh
150e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scotttemplate <class _Tp>
151e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottstatic complex<_Tp> coshT(const complex<_Tp>& z) {
152e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  return complex<_Tp>(::cosh(z._M_re) * ::cos(z._M_im),
153e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott                      ::sinh(z._M_re) * ::sin(z._M_im));
154e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott}
155e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
156e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott_STLP_DECLSPEC complex<float> _STLP_CALL cosh(const complex<float>& z)
157e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott{ return coshT(z); }
158e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
159e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott_STLP_DECLSPEC complex<double> _STLP_CALL cosh(const complex<double>& z)
160e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott{ return coshT(z); }
161e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
162e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#if !defined (_STLP_NO_LONG_DOUBLE)
163e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott_STLP_DECLSPEC complex<long double> _STLP_CALL cosh(const complex<long double>& z)
164e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott{ return coshT(z); }
165e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#endif
166e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
167e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott//----------------------------------------------------------------------
168e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott// tanh
169e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scotttemplate <class _Tp>
170e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scottstatic complex<_Tp> tanhT(const complex<_Tp>& z, const _Tp& Tp_limit) {
171e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  _Tp re2 = 2.f * z._M_re;
172e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  _Tp im2 = 2.f * z._M_im;
173e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  if (::abs(re2) > Tp_limit)
174e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    return complex<_Tp>((re2 > 0 ? 1.f : -1.f), 0.f);
175e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  else {
176e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    _Tp den = ::cosh(re2) + ::cos(im2);
177e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott    return complex<_Tp>(::sinh(re2) / den, ::sin(im2) / den);
178e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott  }
179e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott}
180e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
181e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott_STLP_DECLSPEC complex<float> _STLP_CALL tanh(const complex<float>& z)
182e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott{ return tanhT(z, float_limit); }
183e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
184e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott_STLP_DECLSPEC complex<double> _STLP_CALL tanh(const complex<double>& z)
185e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott{ return tanhT(z, double_limit); }
186e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
187e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#if !defined (_STLP_NO_LONG_DOUBLE)
188e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott_STLP_DECLSPEC complex<long double> _STLP_CALL tanh(const complex<long double>& z)
189e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott{ return tanhT(z, ldouble_limit); }
190e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott#endif
191e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott
192e46c9386c4f79aa40185f79a19fc5b2a7ef528b3Patrick Scott_STLP_END_NAMESPACE
193