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 (__sgi) 33 static const union { unsigned int i; float f; } float_ulimit = { 0x42b2d4fc }; 34 static const float float_limit = float_ulimit.f; 35 static union { 36 struct { unsigned int h; unsigned int l; } w; 37 double d; 38 } double_ulimit = { 0x408633ce, 0x8fb9f87d }; 39 static const double double_limit = double_ulimit.d; 40 static union { 41 struct { unsigned int h[2]; unsigned int l[2]; } w; 42 long double ld; 43 } ldouble_ulimit = {0x408633ce, 0x8fb9f87e, 0xbd23b659, 0x4e9bd8b1}; 44 # if !defined (_STLP_NO_LONG_DOUBLE) 45 # define ldouble_limit ldouble_ulimit.ld 46 # endif 47 #else 48 # if defined (M_LN2) && defined (FLT_MAX_EXP) 49 static const float float_limit = float(M_LN2 * FLT_MAX_EXP); 50 static const double double_limit = M_LN2 * DBL_MAX_EXP; 51 # else 52 static const float float_limit = ::log(FLT_MAX); 53 static const double double_limit = ::log(DBL_MAX); 54 # endif 55 # if !defined (_STLP_NO_LONG_DOUBLE) 56 # if defined (M_LN2l) 57 # define ldouble_limit (M_LN2l * LDBL_MAX_EXP) 58 # else 59 # define ldouble_limit ::log(LDBL_MAX) 60 # endif 61 # endif 62 #endif 63 64 65 //---------------------------------------------------------------------- 66 // sin 67 template <class _Tp> 68 static complex<_Tp> sinT(const complex<_Tp>& z) { 69 return complex<_Tp>(::sin(z._M_re) * ::cosh(z._M_im), 70 ::cos(z._M_re) * ::sinh(z._M_im)); 71 } 72 73 _STLP_DECLSPEC complex<float> _STLP_CALL sin(const complex<float>& z) 74 { return sinT(z); } 75 76 _STLP_DECLSPEC complex<double> _STLP_CALL sin(const complex<double>& z) 77 { return sinT(z); } 78 79 #if !defined (_STLP_NO_LONG_DOUBLE) 80 _STLP_DECLSPEC complex<long double> _STLP_CALL sin(const complex<long double>& z) 81 { return sinT(z); } 82 #endif 83 84 //---------------------------------------------------------------------- 85 // cos 86 template <class _Tp> 87 static complex<_Tp> cosT(const complex<_Tp>& z) { 88 return complex<_Tp>(::cos(z._M_re) * ::cosh(z._M_im), 89 -::sin(z._M_re) * ::sinh(z._M_im)); 90 } 91 92 _STLP_DECLSPEC complex<float> _STLP_CALL cos(const complex<float>& z) 93 { return cosT(z); } 94 95 _STLP_DECLSPEC complex<double> _STLP_CALL cos(const complex<double>& z) 96 { return cosT(z); } 97 98 #if !defined (_STLP_NO_LONG_DOUBLE) 99 _STLP_DECLSPEC complex<long double> _STLP_CALL cos(const complex<long double>& z) 100 { return cosT(z); } 101 #endif 102 103 //---------------------------------------------------------------------- 104 // tan 105 template <class _Tp> 106 static complex<_Tp> tanT(const complex<_Tp>& z, const _Tp& Tp_limit) { 107 _Tp re2 = 2.f * z._M_re; 108 _Tp im2 = 2.f * z._M_im; 109 110 if (::abs(im2) > Tp_limit) 111 return complex<_Tp>(0.f, (im2 > 0 ? 1.f : -1.f)); 112 else { 113 _Tp den = ::cos(re2) + ::cosh(im2); 114 return complex<_Tp>(::sin(re2) / den, ::sinh(im2) / den); 115 } 116 } 117 118 _STLP_DECLSPEC complex<float> _STLP_CALL tan(const complex<float>& z) 119 { return tanT(z, float_limit); } 120 121 _STLP_DECLSPEC complex<double> _STLP_CALL tan(const complex<double>& z) 122 { return tanT(z, double_limit); } 123 124 #if !defined (_STLP_NO_LONG_DOUBLE) 125 _STLP_DECLSPEC complex<long double> _STLP_CALL tan(const complex<long double>& z) 126 { return tanT(z, ldouble_limit); } 127 #endif 128 129 //---------------------------------------------------------------------- 130 // sinh 131 template <class _Tp> 132 static complex<_Tp> sinhT(const complex<_Tp>& z) { 133 return complex<_Tp>(::sinh(z._M_re) * ::cos(z._M_im), 134 ::cosh(z._M_re) * ::sin(z._M_im)); 135 } 136 137 _STLP_DECLSPEC complex<float> _STLP_CALL sinh(const complex<float>& z) 138 { return sinhT(z); } 139 140 _STLP_DECLSPEC complex<double> _STLP_CALL sinh(const complex<double>& z) 141 { return sinhT(z); } 142 143 #if !defined (_STLP_NO_LONG_DOUBLE) 144 _STLP_DECLSPEC complex<long double> _STLP_CALL sinh(const complex<long double>& z) 145 { return sinhT(z); } 146 #endif 147 148 //---------------------------------------------------------------------- 149 // cosh 150 template <class _Tp> 151 static complex<_Tp> coshT(const complex<_Tp>& z) { 152 return complex<_Tp>(::cosh(z._M_re) * ::cos(z._M_im), 153 ::sinh(z._M_re) * ::sin(z._M_im)); 154 } 155 156 _STLP_DECLSPEC complex<float> _STLP_CALL cosh(const complex<float>& z) 157 { return coshT(z); } 158 159 _STLP_DECLSPEC complex<double> _STLP_CALL cosh(const complex<double>& z) 160 { return coshT(z); } 161 162 #if !defined (_STLP_NO_LONG_DOUBLE) 163 _STLP_DECLSPEC complex<long double> _STLP_CALL cosh(const complex<long double>& z) 164 { return coshT(z); } 165 #endif 166 167 //---------------------------------------------------------------------- 168 // tanh 169 template <class _Tp> 170 static complex<_Tp> tanhT(const complex<_Tp>& z, const _Tp& Tp_limit) { 171 _Tp re2 = 2.f * z._M_re; 172 _Tp im2 = 2.f * z._M_im; 173 if (::abs(re2) > Tp_limit) 174 return complex<_Tp>((re2 > 0 ? 1.f : -1.f), 0.f); 175 else { 176 _Tp den = ::cosh(re2) + ::cos(im2); 177 return complex<_Tp>(::sinh(re2) / den, ::sin(im2) / den); 178 } 179 } 180 181 _STLP_DECLSPEC complex<float> _STLP_CALL tanh(const complex<float>& z) 182 { return tanhT(z, float_limit); } 183 184 _STLP_DECLSPEC complex<double> _STLP_CALL tanh(const complex<double>& z) 185 { return tanhT(z, double_limit); } 186 187 #if !defined (_STLP_NO_LONG_DOUBLE) 188 _STLP_DECLSPEC complex<long double> _STLP_CALL tanh(const complex<long double>& z) 189 { return tanhT(z, ldouble_limit); } 190 #endif 191 192 _STLP_END_NAMESPACE 193