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