atanh.hpp 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. // (C) Copyright John Maddock 2005.
  2. // Use, modification and distribution are subject to the
  3. // Boost Software License, Version 1.0. (See accompanying file
  4. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. #ifndef BOOST_MATH_COMPLEX_ATANH_INCLUDED
  6. #define BOOST_MATH_COMPLEX_ATANH_INCLUDED
  7. #ifndef BOOST_MATH_COMPLEX_DETAILS_INCLUDED
  8. # include <boost/math/complex/details.hpp>
  9. #endif
  10. #ifndef BOOST_MATH_LOG1P_INCLUDED
  11. # include <boost/math/special_functions/log1p.hpp>
  12. #endif
  13. #include <boost/assert.hpp>
  14. #ifdef BOOST_NO_STDC_NAMESPACE
  15. namespace std{ using ::sqrt; using ::fabs; using ::acos; using ::asin; using ::atan; using ::atan2; }
  16. #endif
  17. namespace boost{ namespace math{
  18. template<class T>
  19. std::complex<T> atanh(const std::complex<T>& z)
  20. {
  21. //
  22. // References:
  23. //
  24. // Eric W. Weisstein. "Inverse Hyperbolic Tangent."
  25. // From MathWorld--A Wolfram Web Resource.
  26. // http://mathworld.wolfram.com/InverseHyperbolicTangent.html
  27. //
  28. // Also: The Wolfram Functions Site,
  29. // http://functions.wolfram.com/ElementaryFunctions/ArcTanh/
  30. //
  31. // Also "Abramowitz and Stegun. Handbook of Mathematical Functions."
  32. // at : http://jove.prohosting.com/~skripty/toc.htm
  33. //
  34. // See also: https://svn.boost.org/trac/boost/ticket/7291
  35. //
  36. static const T pi = boost::math::constants::pi<T>();
  37. static const T half_pi = pi / 2;
  38. static const T one = static_cast<T>(1.0L);
  39. static const T two = static_cast<T>(2.0L);
  40. static const T four = static_cast<T>(4.0L);
  41. static const T zero = static_cast<T>(0);
  42. static const T log_two = boost::math::constants::ln_two<T>();
  43. #ifdef BOOST_MSVC
  44. #pragma warning(push)
  45. #pragma warning(disable:4127)
  46. #endif
  47. T x = std::fabs(z.real());
  48. T y = std::fabs(z.imag());
  49. T real, imag; // our results
  50. T safe_upper = detail::safe_max(two);
  51. T safe_lower = detail::safe_min(static_cast<T>(2));
  52. //
  53. // Begin by handling the special cases specified in C99:
  54. //
  55. if((boost::math::isnan)(x))
  56. {
  57. if((boost::math::isnan)(y))
  58. return std::complex<T>(x, x);
  59. else if((boost::math::isinf)(y))
  60. return std::complex<T>(0, ((boost::math::signbit)(z.imag()) ? -half_pi : half_pi));
  61. else
  62. return std::complex<T>(x, x);
  63. }
  64. else if((boost::math::isnan)(y))
  65. {
  66. if(x == 0)
  67. return std::complex<T>(x, y);
  68. if((boost::math::isinf)(x))
  69. return std::complex<T>(0, y);
  70. else
  71. return std::complex<T>(y, y);
  72. }
  73. else if((x > safe_lower) && (x < safe_upper) && (y > safe_lower) && (y < safe_upper))
  74. {
  75. T yy = y*y;
  76. T mxm1 = one - x;
  77. ///
  78. // The real part is given by:
  79. //
  80. // real(atanh(z)) == log1p(4*x / ((x-1)*(x-1) + y^2))
  81. //
  82. real = boost::math::log1p(four * x / (mxm1*mxm1 + yy));
  83. real /= four;
  84. if((boost::math::signbit)(z.real()))
  85. real = (boost::math::changesign)(real);
  86. imag = std::atan2((y * two), (mxm1*(one+x) - yy));
  87. imag /= two;
  88. if(z.imag() < 0)
  89. imag = (boost::math::changesign)(imag);
  90. }
  91. else
  92. {
  93. //
  94. // This section handles exception cases that would normally cause
  95. // underflow or overflow in the main formulas.
  96. //
  97. // Begin by working out the real part, we need to approximate
  98. // real = boost::math::log1p(4x / ((x-1)^2 + y^2))
  99. // without either overflow or underflow in the squared terms.
  100. //
  101. T mxm1 = one - x;
  102. if(x >= safe_upper)
  103. {
  104. // x-1 = x to machine precision:
  105. if((boost::math::isinf)(x) || (boost::math::isinf)(y))
  106. {
  107. real = 0;
  108. }
  109. else if(y >= safe_upper)
  110. {
  111. // Big x and y: divide through by x*y:
  112. real = boost::math::log1p((four/y) / (x/y + y/x));
  113. }
  114. else if(y > one)
  115. {
  116. // Big x: divide through by x:
  117. real = boost::math::log1p(four / (x + y*y/x));
  118. }
  119. else
  120. {
  121. // Big x small y, as above but neglect y^2/x:
  122. real = boost::math::log1p(four/x);
  123. }
  124. }
  125. else if(y >= safe_upper)
  126. {
  127. if(x > one)
  128. {
  129. // Big y, medium x, divide through by y:
  130. real = boost::math::log1p((four*x/y) / (y + mxm1*mxm1/y));
  131. }
  132. else
  133. {
  134. // Small or medium x, large y:
  135. real = four*x/y/y;
  136. }
  137. }
  138. else if (x != one)
  139. {
  140. // y is small, calculate divisor carefully:
  141. T div = mxm1*mxm1;
  142. if(y > safe_lower)
  143. div += y*y;
  144. real = boost::math::log1p(four*x/div);
  145. }
  146. else
  147. real = boost::math::changesign(two * (std::log(y) - log_two));
  148. real /= four;
  149. if((boost::math::signbit)(z.real()))
  150. real = (boost::math::changesign)(real);
  151. //
  152. // Now handle imaginary part, this is much easier,
  153. // if x or y are large, then the formula:
  154. // atan2(2y, (1-x)*(1+x) - y^2)
  155. // evaluates to +-(PI - theta) where theta is negligible compared to PI.
  156. //
  157. if((x >= safe_upper) || (y >= safe_upper))
  158. {
  159. imag = pi;
  160. }
  161. else if(x <= safe_lower)
  162. {
  163. //
  164. // If both x and y are small then atan(2y),
  165. // otherwise just x^2 is negligible in the divisor:
  166. //
  167. if(y <= safe_lower)
  168. imag = std::atan2(two*y, one);
  169. else
  170. {
  171. if((y == zero) && (x == zero))
  172. imag = 0;
  173. else
  174. imag = std::atan2(two*y, one - y*y);
  175. }
  176. }
  177. else
  178. {
  179. //
  180. // y^2 is negligible:
  181. //
  182. if((y == zero) && (x == one))
  183. imag = 0;
  184. else
  185. imag = std::atan2(two*y, mxm1*(one+x));
  186. }
  187. imag /= two;
  188. if((boost::math::signbit)(z.imag()))
  189. imag = (boost::math::changesign)(imag);
  190. }
  191. return std::complex<T>(real, imag);
  192. #ifdef BOOST_MSVC
  193. #pragma warning(pop)
  194. #endif
  195. }
  196. } } // namespaces
  197. #endif // BOOST_MATH_COMPLEX_ATANH_INCLUDED