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