sl@0: /* sl@0: * Copyright (c) 1999 sl@0: * Silicon Graphics Computer Systems, Inc. sl@0: * sl@0: * Copyright (c) 1999 sl@0: * Boris Fomitchev sl@0: * sl@0: * This material is provided "as is", with absolutely no warranty expressed sl@0: * or implied. Any use is at your own risk. sl@0: * sl@0: * Permission to use or copy this software for any purpose is hereby granted sl@0: * without fee, provided the above notices are retained on all copies. sl@0: * Permission to modify the code and to distribute modified code is granted, sl@0: * provided the above notices are retained, and a notice that the code was sl@0: * modified is included with the above copyright notice. sl@0: * sl@0: */ sl@0: #include "stlport_prefix.h" sl@0: sl@0: sl@0: // Trigonometric and hyperbolic functions for complex, sl@0: // complex, and complex sl@0: #include sl@0: #include sl@0: #include sl@0: sl@0: _STLP_BEGIN_NAMESPACE sl@0: sl@0: sl@0: //---------------------------------------------------------------------- sl@0: // helpers sl@0: #if defined (__sgi) sl@0: static const union { unsigned int i; float f; } float_ulimit = { 0x42b2d4fc }; sl@0: static const float float_limit = float_ulimit.f; sl@0: static union { sl@0: struct { unsigned int h; unsigned int l; } w; sl@0: double d; sl@0: } double_ulimit = { 0x408633ce, 0x8fb9f87d }; sl@0: static const double double_limit = double_ulimit.d; sl@0: static union { sl@0: struct { unsigned int h[2]; unsigned int l[2]; } w; sl@0: long double ld; sl@0: } ldouble_ulimit = {0x408633ce, 0x8fb9f87e, 0xbd23b659, 0x4e9bd8b1}; sl@0: # if !defined (_STLP_NO_LONG_DOUBLE) sl@0: static const long double ldouble_limit = ldouble_ulimit.ld; sl@0: # endif sl@0: #else sl@0: # if defined (M_LN2) && defined (FLT_MAX_EXP) sl@0: static const float float_limit = float(M_LN2 * FLT_MAX_EXP); sl@0: static const double double_limit = M_LN2 * DBL_MAX_EXP; sl@0: # else sl@0: static const float float_limit = ::log(FLT_MAX); sl@0: static const double double_limit = ::log(DBL_MAX); sl@0: # endif sl@0: # if !defined (_STLP_NO_LONG_DOUBLE) sl@0: # if defined (M_LN2l) sl@0: static const long double ldouble_limit = M_LN2l * LDBL_MAX_EXP; sl@0: # else sl@0: static const long double ldouble_limit = ::log(LDBL_MAX); sl@0: # endif sl@0: # endif sl@0: #endif sl@0: sl@0: sl@0: //---------------------------------------------------------------------- sl@0: // sin sl@0: template sl@0: static complex<_Tp> sinT(const complex<_Tp>& z) { sl@0: return complex<_Tp>(::sin(z._M_re) * ::cosh(z._M_im), sl@0: ::cos(z._M_re) * ::sinh(z._M_im)); sl@0: } sl@0: sl@0: _STLP_DECLSPEC complex _STLP_CALL sin(const complex& z) sl@0: { return sinT(z); } sl@0: sl@0: _STLP_DECLSPEC complex _STLP_CALL sin(const complex& z) sl@0: { return sinT(z); } sl@0: sl@0: #if !defined (_STLP_NO_LONG_DOUBLE) sl@0: _STLP_DECLSPEC complex _STLP_CALL sin(const complex& z) sl@0: { return sinT(z); } sl@0: #endif sl@0: sl@0: //---------------------------------------------------------------------- sl@0: // cos sl@0: template sl@0: static complex<_Tp> cosT(const complex<_Tp>& z) { sl@0: return complex<_Tp>(::cos(z._M_re) * ::cosh(z._M_im), sl@0: -::sin(z._M_re) * ::sinh(z._M_im)); sl@0: } sl@0: sl@0: _STLP_DECLSPEC complex _STLP_CALL cos(const complex& z) sl@0: { return cosT(z); } sl@0: sl@0: _STLP_DECLSPEC complex _STLP_CALL cos(const complex& z) sl@0: { return cosT(z); } sl@0: sl@0: #if !defined (_STLP_NO_LONG_DOUBLE) sl@0: _STLP_DECLSPEC complex _STLP_CALL cos(const complex& z) sl@0: { return cosT(z); } sl@0: #endif sl@0: sl@0: //---------------------------------------------------------------------- sl@0: // tan sl@0: template sl@0: static complex<_Tp> tanT(const complex<_Tp>& z, const _Tp& Tp_limit) { sl@0: _Tp re2 = 2.f * z._M_re; sl@0: _Tp im2 = 2.f * z._M_im; sl@0: sl@0: if (::abs(im2) > Tp_limit) sl@0: return complex<_Tp>(0.f, (im2 > 0 ? 1.f : -1.f)); sl@0: else { sl@0: _Tp den = ::cos(re2) + ::cosh(im2); sl@0: return complex<_Tp>(::sin(re2) / den, ::sinh(im2) / den); sl@0: } sl@0: } sl@0: sl@0: _STLP_DECLSPEC complex _STLP_CALL tan(const complex& z) sl@0: { return tanT(z, float_limit); } sl@0: sl@0: _STLP_DECLSPEC complex _STLP_CALL tan(const complex& z) sl@0: { return tanT(z, double_limit); } sl@0: sl@0: #if !defined (_STLP_NO_LONG_DOUBLE) sl@0: _STLP_DECLSPEC complex _STLP_CALL tan(const complex& z) sl@0: { return tanT(z, ldouble_limit); } sl@0: #endif sl@0: sl@0: //---------------------------------------------------------------------- sl@0: // sinh sl@0: template sl@0: static complex<_Tp> sinhT(const complex<_Tp>& z) { sl@0: return complex<_Tp>(::sinh(z._M_re) * ::cos(z._M_im), sl@0: ::cosh(z._M_re) * ::sin(z._M_im)); sl@0: } sl@0: sl@0: _STLP_DECLSPEC complex _STLP_CALL sinh(const complex& z) sl@0: { return sinhT(z); } sl@0: sl@0: _STLP_DECLSPEC complex _STLP_CALL sinh(const complex& z) sl@0: { return sinhT(z); } sl@0: sl@0: #if !defined (_STLP_NO_LONG_DOUBLE) sl@0: _STLP_DECLSPEC complex _STLP_CALL sinh(const complex& z) sl@0: { return sinhT(z); } sl@0: #endif sl@0: sl@0: //---------------------------------------------------------------------- sl@0: // cosh sl@0: template sl@0: static complex<_Tp> coshT(const complex<_Tp>& z) { sl@0: return complex<_Tp>(::cosh(z._M_re) * ::cos(z._M_im), sl@0: ::sinh(z._M_re) * ::sin(z._M_im)); sl@0: } sl@0: sl@0: _STLP_DECLSPEC complex _STLP_CALL cosh(const complex& z) sl@0: { return coshT(z); } sl@0: sl@0: _STLP_DECLSPEC complex _STLP_CALL cosh(const complex& z) sl@0: { return coshT(z); } sl@0: sl@0: #if !defined (_STLP_NO_LONG_DOUBLE) sl@0: _STLP_DECLSPEC complex _STLP_CALL cosh(const complex& z) sl@0: { return coshT(z); } sl@0: #endif sl@0: sl@0: //---------------------------------------------------------------------- sl@0: // tanh sl@0: template sl@0: static complex<_Tp> tanhT(const complex<_Tp>& z, const _Tp& Tp_limit) { sl@0: _Tp re2 = 2.f * z._M_re; sl@0: _Tp im2 = 2.f * z._M_im; sl@0: if (::abs(re2) > Tp_limit) sl@0: return complex<_Tp>((re2 > 0 ? 1.f : -1.f), 0.f); sl@0: else { sl@0: _Tp den = ::cosh(re2) + ::cos(im2); sl@0: return complex<_Tp>(::sinh(re2) / den, ::sin(im2) / den); sl@0: } sl@0: } sl@0: sl@0: _STLP_DECLSPEC complex _STLP_CALL tanh(const complex& z) sl@0: { return tanhT(z, float_limit); } sl@0: sl@0: _STLP_DECLSPEC complex _STLP_CALL tanh(const complex& z) sl@0: { return tanhT(z, double_limit); } sl@0: sl@0: #if !defined (_STLP_NO_LONG_DOUBLE) sl@0: _STLP_DECLSPEC complex _STLP_CALL tanh(const complex& z) sl@0: { return tanhT(z, ldouble_limit); } sl@0: #endif sl@0: sl@0: _STLP_END_NAMESPACE