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