complex_trig.cpp 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  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. // Trigonometric and hyperbolic functions for complex<float>,
  20. // complex<double>, and complex<long double>
  21. #include <complex>
  22. #include <cfloat>
  23. #include <cmath>
  24. _STLP_BEGIN_NAMESPACE
  25. //----------------------------------------------------------------------
  26. // helpers
  27. #if defined (__sgi)
  28. static const union { unsigned int i; float f; } float_ulimit = { 0x42b2d4fc };
  29. static const float float_limit = float_ulimit.f;
  30. static union {
  31. struct { unsigned int h; unsigned int l; } w;
  32. double d;
  33. } double_ulimit = { 0x408633ce, 0x8fb9f87d };
  34. static const double double_limit = double_ulimit.d;
  35. static union {
  36. struct { unsigned int h[2]; unsigned int l[2]; } w;
  37. long double ld;
  38. } ldouble_ulimit = {0x408633ce, 0x8fb9f87e, 0xbd23b659, 0x4e9bd8b1};
  39. # if !defined (_STLP_NO_LONG_DOUBLE)
  40. static const long double ldouble_limit = ldouble_ulimit.ld;
  41. # endif
  42. #else
  43. # if defined (M_LN2) && defined (FLT_MAX_EXP)
  44. static const float float_limit = float(M_LN2 * FLT_MAX_EXP);
  45. static const double double_limit = M_LN2 * DBL_MAX_EXP;
  46. # else
  47. static const float float_limit = ::log(FLT_MAX);
  48. static const double double_limit = ::log(DBL_MAX);
  49. # endif
  50. # if !defined (_STLP_NO_LONG_DOUBLE)
  51. # if defined (M_LN2l)
  52. static const long double ldouble_limit = M_LN2l * LDBL_MAX_EXP;
  53. # else
  54. static const long double ldouble_limit = ::log(LDBL_MAX);
  55. # endif
  56. # endif
  57. #endif
  58. //----------------------------------------------------------------------
  59. // sin
  60. template <class _Tp>
  61. static complex<_Tp> sinT(const complex<_Tp>& z) {
  62. return complex<_Tp>(::sin(z._M_re) * ::cosh(z._M_im),
  63. ::cos(z._M_re) * ::sinh(z._M_im));
  64. }
  65. _STLP_DECLSPEC complex<float> _STLP_CALL sin(const complex<float>& z)
  66. { return sinT(z); }
  67. _STLP_DECLSPEC complex<double> _STLP_CALL sin(const complex<double>& z)
  68. { return sinT(z); }
  69. #if !defined (_STLP_NO_LONG_DOUBLE)
  70. _STLP_DECLSPEC complex<long double> _STLP_CALL sin(const complex<long double>& z)
  71. { return sinT(z); }
  72. #endif
  73. //----------------------------------------------------------------------
  74. // cos
  75. template <class _Tp>
  76. static complex<_Tp> cosT(const complex<_Tp>& z) {
  77. return complex<_Tp>(::cos(z._M_re) * ::cosh(z._M_im),
  78. -::sin(z._M_re) * ::sinh(z._M_im));
  79. }
  80. _STLP_DECLSPEC complex<float> _STLP_CALL cos(const complex<float>& z)
  81. { return cosT(z); }
  82. _STLP_DECLSPEC complex<double> _STLP_CALL cos(const complex<double>& z)
  83. { return cosT(z); }
  84. #if !defined (_STLP_NO_LONG_DOUBLE)
  85. _STLP_DECLSPEC complex<long double> _STLP_CALL cos(const complex<long double>& z)
  86. { return cosT(z); }
  87. #endif
  88. //----------------------------------------------------------------------
  89. // tan
  90. template <class _Tp>
  91. static complex<_Tp> tanT(const complex<_Tp>& z, const _Tp& Tp_limit) {
  92. _Tp re2 = 2.f * z._M_re;
  93. _Tp im2 = 2.f * z._M_im;
  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. _STLP_DECLSPEC complex<float> _STLP_CALL tan(const complex<float>& z)
  102. { return tanT(z, float_limit); }
  103. _STLP_DECLSPEC complex<double> _STLP_CALL tan(const complex<double>& z)
  104. { return tanT(z, double_limit); }
  105. #if !defined (_STLP_NO_LONG_DOUBLE)
  106. _STLP_DECLSPEC complex<long double> _STLP_CALL tan(const complex<long double>& z)
  107. { return tanT(z, ldouble_limit); }
  108. #endif
  109. //----------------------------------------------------------------------
  110. // sinh
  111. template <class _Tp>
  112. static complex<_Tp> sinhT(const complex<_Tp>& z) {
  113. return complex<_Tp>(::sinh(z._M_re) * ::cos(z._M_im),
  114. ::cosh(z._M_re) * ::sin(z._M_im));
  115. }
  116. _STLP_DECLSPEC complex<float> _STLP_CALL sinh(const complex<float>& z)
  117. { return sinhT(z); }
  118. _STLP_DECLSPEC complex<double> _STLP_CALL sinh(const complex<double>& z)
  119. { return sinhT(z); }
  120. #if !defined (_STLP_NO_LONG_DOUBLE)
  121. _STLP_DECLSPEC complex<long double> _STLP_CALL sinh(const complex<long double>& z)
  122. { return sinhT(z); }
  123. #endif
  124. //----------------------------------------------------------------------
  125. // cosh
  126. template <class _Tp>
  127. static complex<_Tp> coshT(const complex<_Tp>& z) {
  128. return complex<_Tp>(::cosh(z._M_re) * ::cos(z._M_im),
  129. ::sinh(z._M_re) * ::sin(z._M_im));
  130. }
  131. _STLP_DECLSPEC complex<float> _STLP_CALL cosh(const complex<float>& z)
  132. { return coshT(z); }
  133. _STLP_DECLSPEC complex<double> _STLP_CALL cosh(const complex<double>& z)
  134. { return coshT(z); }
  135. #if !defined (_STLP_NO_LONG_DOUBLE)
  136. _STLP_DECLSPEC complex<long double> _STLP_CALL cosh(const complex<long double>& z)
  137. { return coshT(z); }
  138. #endif
  139. //----------------------------------------------------------------------
  140. // tanh
  141. template <class _Tp>
  142. static complex<_Tp> tanhT(const complex<_Tp>& z, const _Tp& Tp_limit) {
  143. _Tp re2 = 2.f * z._M_re;
  144. _Tp im2 = 2.f * z._M_im;
  145. if (::abs(re2) > Tp_limit)
  146. return complex<_Tp>((re2 > 0 ? 1.f : -1.f), 0.f);
  147. else {
  148. _Tp den = ::cosh(re2) + ::cos(im2);
  149. return complex<_Tp>(::sinh(re2) / den, ::sin(im2) / den);
  150. }
  151. }
  152. _STLP_DECLSPEC complex<float> _STLP_CALL tanh(const complex<float>& z)
  153. { return tanhT(z, float_limit); }
  154. _STLP_DECLSPEC complex<double> _STLP_CALL tanh(const complex<double>& z)
  155. { return tanhT(z, double_limit); }
  156. #if !defined (_STLP_NO_LONG_DOUBLE)
  157. _STLP_DECLSPEC complex<long double> _STLP_CALL tanh(const complex<long double>& z)
  158. { return tanhT(z, ldouble_limit); }
  159. #endif
  160. _STLP_END_NAMESPACE