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