|
1 /* |
|
2 * © Portions copyright (c) 2006-2007 Nokia Corporation. All rights reserved. |
|
3 * |
|
4 * Copyright (c) 1999 |
|
5 * Silicon Graphics Computer Systems, Inc. |
|
6 * |
|
7 * Copyright (c) 1999 |
|
8 * Boris Fomitchev |
|
9 * |
|
10 * This material is provided "as is", with absolutely no warranty expressed |
|
11 * or implied. Any use is at your own risk. |
|
12 * |
|
13 * Permission to use or copy this software for any purpose is hereby granted |
|
14 * without fee, provided the above notices are retained on all copies. |
|
15 * Permission to modify the code and to distribute modified code is granted, |
|
16 * provided the above notices are retained, and a notice that the code was |
|
17 * modified is included with the above copyright notice. |
|
18 * |
|
19 */ |
|
20 # include "stlport_prefix.h" |
|
21 |
|
22 |
|
23 // Trigonometric and hyperbolic functions for complex<float>, |
|
24 // complex<double>, and complex<long double> |
|
25 |
|
26 |
|
27 #include "complex_impl.h" |
|
28 |
|
29 #include <cfloat> |
|
30 #include <cmath> |
|
31 |
|
32 #if defined(__LIBSTD_CPP_SYMBIAN32_WSD__) || defined(_STLP_LIBSTD_CPP_NO_STATIC_VAR_) |
|
33 #include "libstdcppwsd.h" |
|
34 # endif |
|
35 |
|
36 _STLP_BEGIN_NAMESPACE |
|
37 |
|
38 |
|
39 //---------------------------------------------------------------------- |
|
40 // helpers |
|
41 |
|
42 #ifdef __sgi |
|
43 static const union { unsigned int i; float f; } float_ulimit = { 0x42b2d4fc }; |
|
44 static const float float_limit = float_ulimit.f; |
|
45 static union { |
|
46 struct { unsigned int h; unsigned int l; } w; |
|
47 double d; |
|
48 } double_ulimit = { 0x408633ce, 0x8fb9f87d }; |
|
49 static const double double_limit = double_ulimit.d; |
|
50 static union { |
|
51 struct { unsigned int h[2]; unsigned int l[2]; } w; |
|
52 long double ld; |
|
53 } ldouble_ulimit = {0x408633ce, 0x8fb9f87e, 0xbd23b659, 0x4e9bd8b1}; |
|
54 # ifndef _STLP_NO_LONG_DOUBLE |
|
55 static const long double ldouble_limit = ldouble_ulimit.ld; |
|
56 # endif |
|
57 #else |
|
58 #if defined(__LIBSTD_CPP_SYMBIAN32_WSD__) || defined(_STLP_LIBSTD_CPP_NO_STATIC_VAR_) |
|
59 void complex_trig_limit_init() |
|
60 { |
|
61 get_complex_trig_float_limit() = _STLP_LOGF(FLT_MAX); |
|
62 get_complex_trig_double_limit() = _STLP_DO_LOG(double)(DBL_MAX); |
|
63 } |
|
64 # else |
|
65 static const float float_limit = _STLP_LOGF(FLT_MAX); |
|
66 static const double double_limit = _STLP_DO_LOG(double)(DBL_MAX); |
|
67 # endif //__LIBSTD_CPP_SYMBIAN32_WSD__ |
|
68 # ifndef _STLP_NO_LONG_DOUBLE |
|
69 static const long double ldouble_limit = _STLP_LOGL(LDBL_MAX); |
|
70 # endif |
|
71 #endif |
|
72 |
|
73 |
|
74 //---------------------------------------------------------------------- |
|
75 // sin |
|
76 |
|
77 _STLP_EXP_DECLSPEC complex<float> _STLP_CALL sin(const complex<float>& z) { |
|
78 return complex<float>(_STLP_SINF(z._M_re) * _STLP_COSHF(z._M_im), |
|
79 _STLP_COSF(z._M_re) * _STLP_SINHF(z._M_im)); |
|
80 } |
|
81 |
|
82 _STLP_EXP_DECLSPEC complex<double> _STLP_CALL sin(const complex<double>& z) { |
|
83 return complex<double>(_STLP_SIN(z._M_re) * _STLP_COSH(z._M_im), |
|
84 _STLP_COS(z._M_re) * _STLP_SINH(z._M_im)); |
|
85 } |
|
86 |
|
87 #ifndef _STLP_NO_LONG_DOUBLE |
|
88 _STLP_EXP_DECLSPEC complex<long double> _STLP_CALL sin(const complex<long double>& z) { |
|
89 return complex<long double>(_STLP_SINL(z._M_re) * _STLP_COSHL(z._M_im), |
|
90 _STLP_COSL(z._M_re) * _STLP_SINHL(z._M_im)); |
|
91 } |
|
92 #endif |
|
93 |
|
94 //---------------------------------------------------------------------- |
|
95 // cos |
|
96 |
|
97 _STLP_EXP_DECLSPEC complex<float> _STLP_CALL cos(const complex<float>& z) { |
|
98 return complex<float>(_STLP_COSF(z._M_re) * _STLP_COSHF(z._M_im), |
|
99 -_STLP_SINF(z._M_re) * _STLP_SINHF(z._M_im)); |
|
100 } |
|
101 |
|
102 _STLP_EXP_DECLSPEC complex<double> _STLP_CALL cos(const complex<double>& z) { |
|
103 return complex<double>(_STLP_COS(z._M_re) * _STLP_COSH(z._M_im), |
|
104 -_STLP_SIN(z._M_re) * _STLP_SINH(z._M_im)); |
|
105 } |
|
106 |
|
107 #ifndef _STLP_NO_LONG_DOUBLE |
|
108 _STLP_EXP_DECLSPEC complex<long double> _STLP_CALL cos(const complex<long double>& z) { |
|
109 return complex<long double>(_STLP_COSL(z._M_re) * _STLP_COSHL(z._M_im), |
|
110 -_STLP_SINL(z._M_re) * _STLP_SINHL(z._M_im)); |
|
111 } |
|
112 # endif |
|
113 |
|
114 //---------------------------------------------------------------------- |
|
115 // tan |
|
116 |
|
117 _STLP_EXP_DECLSPEC complex<float> _STLP_CALL tan(const complex<float>& z) { |
|
118 float re2 = 2.f * z._M_re; |
|
119 float im2 = 2.f * z._M_im; |
|
120 |
|
121 #if defined(__LIBSTD_CPP_SYMBIAN32_WSD__) || defined(_STLP_LIBSTD_CPP_NO_STATIC_VAR_) |
|
122 if (_STLP_ABSF(im2) > get_complex_trig_float_limit()) |
|
123 # else |
|
124 if (_STLP_ABSF(im2) > float_limit) |
|
125 # endif |
|
126 return complex<float>(0.f, (im2 > 0 ? 1.f : -1.f)); |
|
127 else { |
|
128 float den = _STLP_COSF(re2) + _STLP_COSHF(im2); |
|
129 return complex<float>(_STLP_SINF(re2) / den, _STLP_SINHF(im2) / den); |
|
130 } |
|
131 } |
|
132 |
|
133 _STLP_EXP_DECLSPEC complex<double> _STLP_CALL tan(const complex<double>& z) { |
|
134 double re2 = 2. * z._M_re; |
|
135 double im2 = 2. * z._M_im; |
|
136 |
|
137 #if defined(__LIBSTD_CPP_SYMBIAN32_WSD__) || defined(_STLP_LIBSTD_CPP_NO_STATIC_VAR_) |
|
138 if (fabs(float(im2)) > get_complex_trig_double_limit()) |
|
139 # else |
|
140 if (fabs(float(im2)) > double_limit) |
|
141 # endif //__LIBSTD_CPP_SYMBIAN32_WSD__ |
|
142 return complex<double>(0., (im2 > 0 ? 1. : -1.)); |
|
143 else { |
|
144 double den = _STLP_COS(re2) + _STLP_COSH(im2); |
|
145 return complex<double>(_STLP_SIN(re2) / den, _STLP_SINH(im2) / den); |
|
146 } |
|
147 } |
|
148 |
|
149 #ifndef _STLP_NO_LONG_DOUBLE |
|
150 _STLP_EXP_DECLSPEC complex<long double> _STLP_CALL tan(const complex<long double>& z) { |
|
151 long double re2 = 2.l * z._M_re; |
|
152 long double im2 = 2.l * z._M_im; |
|
153 if (_STLP_ABSL(im2) > ldouble_limit) |
|
154 return complex<long double>(0.l, (im2 > 0 ? 1.l : -1.l)); |
|
155 else { |
|
156 long double den = _STLP_COSL(re2) + _STLP_COSHL(im2); |
|
157 return complex<long double>(_STLP_SINL(re2) / den, _STLP_SINHL(im2) / den); |
|
158 } |
|
159 } |
|
160 |
|
161 # endif |
|
162 |
|
163 //---------------------------------------------------------------------- |
|
164 // sinh |
|
165 |
|
166 _STLP_EXP_DECLSPEC complex<float> _STLP_CALL sinh(const complex<float>& z) { |
|
167 return complex<float>(_STLP_SINHF(z._M_re) * _STLP_COSF(z._M_im), |
|
168 _STLP_COSHF(z._M_re) * _STLP_SINF(z._M_im)); |
|
169 } |
|
170 |
|
171 _STLP_EXP_DECLSPEC complex<double> _STLP_CALL sinh(const complex<double>& z) { |
|
172 return complex<double>(_STLP_SINH(z._M_re) * _STLP_COS(z._M_im), |
|
173 _STLP_COSH(z._M_re) * _STLP_SIN(z._M_im)); |
|
174 } |
|
175 |
|
176 #ifndef _STLP_NO_LONG_DOUBLE |
|
177 _STLP_EXP_DECLSPEC complex<long double> _STLP_CALL sinh(const complex<long double>& z) { |
|
178 return complex<long double>(_STLP_SINHL(z._M_re) * _STLP_COSL(z._M_im), |
|
179 _STLP_COSHL(z._M_re) * _STLP_SINL(z._M_im)); |
|
180 } |
|
181 #endif |
|
182 |
|
183 //---------------------------------------------------------------------- |
|
184 // cosh |
|
185 |
|
186 _STLP_EXP_DECLSPEC complex<float> _STLP_CALL cosh(const complex<float>& z) { |
|
187 return complex<float>(_STLP_COSHF(z._M_re) * _STLP_COSF(z._M_im), |
|
188 _STLP_SINHF(z._M_re) * _STLP_SINF(z._M_im)); |
|
189 } |
|
190 |
|
191 _STLP_EXP_DECLSPEC complex<double> _STLP_CALL cosh(const complex<double>& z) { |
|
192 return complex<double>(_STLP_COSH(z._M_re) * _STLP_COS(z._M_im), |
|
193 _STLP_SINH(z._M_re) * _STLP_SIN(z._M_im)); |
|
194 } |
|
195 |
|
196 #ifndef _STLP_NO_LONG_DOUBLE |
|
197 _STLP_EXP_DECLSPEC complex<long double> _STLP_CALL cosh(const complex<long double>& z) { |
|
198 return complex<long double>(_STLP_COSHL(z._M_re) * _STLP_COSL(z._M_im), |
|
199 _STLP_SINHL(z._M_re) * _STLP_SINL(z._M_im)); |
|
200 } |
|
201 #endif |
|
202 |
|
203 //---------------------------------------------------------------------- |
|
204 // tanh |
|
205 |
|
206 _STLP_EXP_DECLSPEC complex<float> _STLP_CALL tanh(const complex<float>& z) { |
|
207 float re2 = 2.f * z._M_re; |
|
208 float im2 = 2.f * z._M_im; |
|
209 #if defined(__LIBSTD_CPP_SYMBIAN32_WSD__) || defined(_STLP_LIBSTD_CPP_NO_STATIC_VAR_) |
|
210 if (_STLP_ABSF(re2) > get_complex_trig_float_limit()) |
|
211 # else |
|
212 if (_STLP_ABSF(re2) > float_limit) |
|
213 # endif //__LIBSTD_CPP_SYMBIAN32_WSD__ |
|
214 return complex<float>((re2 > 0 ? 1.f : -1.f), 0.f); |
|
215 else { |
|
216 float den = _STLP_COSHF(re2) + _STLP_COSF(im2); |
|
217 return complex<float>(_STLP_SINHF(re2) / den, _STLP_SINF(im2) / den); |
|
218 } |
|
219 } |
|
220 |
|
221 _STLP_EXP_DECLSPEC complex<double> _STLP_CALL tanh(const complex<double>& z) { |
|
222 double re2 = 2. * z._M_re; |
|
223 double im2 = 2. * z._M_im; |
|
224 |
|
225 #if defined(__LIBSTD_CPP_SYMBIAN32_WSD__) || defined(_STLP_LIBSTD_CPP_NO_STATIC_VAR_) |
|
226 if (fabs(float(re2)) > get_complex_trig_double_limit()) |
|
227 # else |
|
228 if (fabs(float(re2)) > double_limit) |
|
229 # endif //__LIBSTD_CPP_SYMBIAN32_WSD__ |
|
230 return complex<double>((re2 > 0 ? 1. : -1.), 0.); |
|
231 else { |
|
232 double den = _STLP_COSH(re2) + _STLP_COS(im2); |
|
233 return complex<double>(_STLP_SINH(re2) / den, _STLP_SIN(im2) / den); |
|
234 } |
|
235 } |
|
236 |
|
237 #ifndef _STLP_NO_LONG_DOUBLE |
|
238 _STLP_EXP_DECLSPEC complex<long double> _STLP_CALL tanh(const complex<long double>& z) { |
|
239 long double re2 = 2.l * z._M_re; |
|
240 long double im2 = 2.l * z._M_im; |
|
241 if (_STLP_ABSL(re2) > ldouble_limit) |
|
242 return complex<long double>((re2 > 0 ? 1.l : -1.l), 0.l); |
|
243 else { |
|
244 long double den = _STLP_COSHL(re2) + _STLP_COSL(im2); |
|
245 return complex<long double>(_STLP_SINHL(re2) / den, _STLP_SINL(im2) / den); |
|
246 } |
|
247 } |
|
248 #endif |
|
249 _STLP_END_NAMESPACE |