atanh.hpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. // boost atanh.hpp header file
  2. // (C) Copyright Hubert Holin 2001.
  3. // (C) Copyright John Maddock 2008.
  4. // Distributed under the Boost Software License, Version 1.0. (See
  5. // accompanying file LICENSE_1_0.txt or copy at
  6. // http://www.boost.org/LICENSE_1_0.txt)
  7. // See http://www.boost.org for updates, documentation, and revision history.
  8. #ifndef BOOST_ATANH_HPP
  9. #define BOOST_ATANH_HPP
  10. #ifdef _MSC_VER
  11. #pragma once
  12. #endif
  13. #include <boost/config/no_tr1/cmath.hpp>
  14. #include <boost/config.hpp>
  15. #include <boost/math/tools/precision.hpp>
  16. #include <boost/math/policies/error_handling.hpp>
  17. #include <boost/math/special_functions/math_fwd.hpp>
  18. #include <boost/math/special_functions/log1p.hpp>
  19. // This is the inverse of the hyperbolic tangent function.
  20. namespace boost
  21. {
  22. namespace math
  23. {
  24. namespace detail
  25. {
  26. #if defined(__GNUC__) && (__GNUC__ < 3)
  27. // gcc 2.x ignores function scope using declarations,
  28. // put them in the scope of the enclosing namespace instead:
  29. using ::std::abs;
  30. using ::std::sqrt;
  31. using ::std::log;
  32. using ::std::numeric_limits;
  33. #endif
  34. // This is the main fare
  35. template<typename T, typename Policy>
  36. inline T atanh_imp(const T x, const Policy& pol)
  37. {
  38. BOOST_MATH_STD_USING
  39. static const char* function = "boost::math::atanh<%1%>(%1%)";
  40. if(x < -1)
  41. {
  42. return policies::raise_domain_error<T>(
  43. function,
  44. "atanh requires x >= -1, but got x = %1%.", x, pol);
  45. }
  46. else if(x > 1)
  47. {
  48. return policies::raise_domain_error<T>(
  49. function,
  50. "atanh requires x <= 1, but got x = %1%.", x, pol);
  51. }
  52. else if(x < -1 + tools::epsilon<T>())
  53. {
  54. // -Infinity:
  55. return -policies::raise_overflow_error<T>(function, 0, pol);
  56. }
  57. else if(x > 1 - tools::epsilon<T>())
  58. {
  59. // Infinity:
  60. return policies::raise_overflow_error<T>(function, 0, pol);
  61. }
  62. else if(abs(x) >= tools::forth_root_epsilon<T>())
  63. {
  64. // http://functions.wolfram.com/ElementaryFunctions/ArcTanh/02/
  65. if(abs(x) < 0.5f)
  66. return (boost::math::log1p(x, pol) - boost::math::log1p(-x, pol)) / 2;
  67. return(log( (1 + x) / (1 - x) ) / 2);
  68. }
  69. else
  70. {
  71. // http://functions.wolfram.com/ElementaryFunctions/ArcTanh/06/01/03/01/
  72. // approximation by taylor series in x at 0 up to order 2
  73. T result = x;
  74. if (abs(x) >= tools::root_epsilon<T>())
  75. {
  76. T x3 = x*x*x;
  77. // approximation by taylor series in x at 0 up to order 4
  78. result += x3/static_cast<T>(3);
  79. }
  80. return(result);
  81. }
  82. }
  83. }
  84. template<typename T, typename Policy>
  85. inline typename tools::promote_args<T>::type atanh(T x, const Policy&)
  86. {
  87. typedef typename tools::promote_args<T>::type result_type;
  88. typedef typename policies::evaluation<result_type, Policy>::type value_type;
  89. typedef typename policies::normalise<
  90. Policy,
  91. policies::promote_float<false>,
  92. policies::promote_double<false>,
  93. policies::discrete_quantile<>,
  94. policies::assert_undefined<> >::type forwarding_policy;
  95. return policies::checked_narrowing_cast<result_type, forwarding_policy>(
  96. detail::atanh_imp(static_cast<value_type>(x), forwarding_policy()),
  97. "boost::math::atanh<%1%>(%1%)");
  98. }
  99. template<typename T>
  100. inline typename tools::promote_args<T>::type atanh(T x)
  101. {
  102. return boost::math::atanh(x, policies::policy<>());
  103. }
  104. }
  105. }
  106. #endif /* BOOST_ATANH_HPP */