atanh_test.hpp 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. // unit test file atanh.hpp for the special functions test suite
  2. // (C) Copyright Hubert Holin 2003.
  3. // Distributed under the Boost Software License, Version 1.0. (See
  4. // accompanying file LICENSE_1_0.txt or copy at
  5. // http://www.boost.org/LICENSE_1_0.txt)
  6. #include <functional>
  7. #include <iomanip>
  8. //#include <iostream>
  9. #define BOOST_TEST_MAiN
  10. #include <boost/math/special_functions/atanh.hpp>
  11. #include <boost/test/unit_test.hpp>
  12. template<typename T>
  13. T atanh_error_evaluator(T x)
  14. {
  15. using ::std::abs;
  16. using ::std::tanh;
  17. using ::std::cosh;
  18. using ::std::numeric_limits;
  19. using ::boost::math::atanh;
  20. static T const epsilon = numeric_limits<float>::epsilon();
  21. T y = tanh(x);
  22. T z = atanh(y);
  23. T absolute_error = abs(z-x);
  24. T relative_error = absolute_error/(cosh(x)*cosh(x));
  25. T scaled_error = relative_error/epsilon;
  26. return(scaled_error);
  27. }
  28. BOOST_TEST_CASE_TEMPLATE_FUNCTION(atanh_test, T)
  29. {
  30. using ::std::abs;
  31. using ::std::tanh;
  32. using ::std::log;
  33. using ::std::numeric_limits;
  34. using ::boost::math::atanh;
  35. BOOST_TEST_MESSAGE("Testing atanh in the real domain for "
  36. << string_type_name<T>::_() << ".");
  37. BOOST_CHECK_PREDICATE(::std::less_equal<T>(),
  38. (abs(atanh<T>(static_cast<T>(0))))
  39. (numeric_limits<T>::epsilon()));
  40. BOOST_CHECK_PREDICATE(::std::less_equal<T>(),
  41. (abs(atanh<T>(static_cast<T>(3)/5) - log(static_cast<T>(2))))
  42. (numeric_limits<T>::epsilon()));
  43. BOOST_CHECK_PREDICATE(::std::less_equal<T>(),
  44. (abs(atanh<T>(static_cast<T>(-3)/5) + log(static_cast<T>(2))))
  45. (numeric_limits<T>::epsilon()));
  46. for (int i = 0; i <= 100; i++)
  47. {
  48. T x = static_cast<T>(i-50)/static_cast<T>(5);
  49. T y = tanh(x);
  50. if (
  51. (abs(y-static_cast<T>(1)) >= numeric_limits<T>::epsilon())&&
  52. (abs(y+static_cast<T>(1)) >= numeric_limits<T>::epsilon())
  53. )
  54. {
  55. BOOST_CHECK_PREDICATE(::std::less_equal<T>(),
  56. (atanh_error_evaluator(x))
  57. (static_cast<T>(4)));
  58. }
  59. }
  60. //
  61. // Error handling checks:
  62. //
  63. BOOST_MATH_CHECK_THROW(atanh(T(-1)), std::overflow_error);
  64. BOOST_MATH_CHECK_THROW(atanh(T(1)), std::overflow_error);
  65. BOOST_MATH_CHECK_THROW(atanh(T(-2)), std::domain_error);
  66. BOOST_MATH_CHECK_THROW(atanh(T(2)), std::domain_error);
  67. }
  68. void atanh_manual_check()
  69. {
  70. using ::std::abs;
  71. using ::std::tanh;
  72. using ::std::numeric_limits;
  73. BOOST_TEST_MESSAGE(" ");
  74. BOOST_TEST_MESSAGE("atanh");
  75. for (int i = 0; i <= 100; i++)
  76. {
  77. float xf = static_cast<float>(i-50)/static_cast<float>(5);
  78. double xd = static_cast<double>(i-50)/static_cast<double>(5);
  79. long double xl =
  80. static_cast<long double>(i-50)/static_cast<long double>(5);
  81. float yf = tanh(xf);
  82. double yd = tanh(xd);
  83. (void) &yd; // avoid "unused variable" warning
  84. long double yl = tanh(xl);
  85. (void) &yl; // avoid "unused variable" warning
  86. if (
  87. std::numeric_limits<float>::has_infinity &&
  88. std::numeric_limits<double>::has_infinity &&
  89. std::numeric_limits<long double>::has_infinity
  90. )
  91. {
  92. #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
  93. BOOST_TEST_MESSAGE( ::std::setw(15)
  94. << atanh_error_evaluator(xf)
  95. << ::std::setw(15)
  96. << atanh_error_evaluator(xd)
  97. << ::std::setw(15)
  98. << atanh_error_evaluator(xl));
  99. #else
  100. BOOST_TEST_MESSAGE( ::std::setw(15)
  101. << atanh_error_evaluator(xf)
  102. << ::std::setw(15)
  103. << atanh_error_evaluator(xd));
  104. #endif
  105. }
  106. else
  107. {
  108. if (
  109. (abs(yf-static_cast<float>(1)) <
  110. numeric_limits<float>::epsilon())||
  111. (abs(yf+static_cast<float>(1)) <
  112. numeric_limits<float>::epsilon())||
  113. (abs(yf-static_cast<double>(1)) <
  114. numeric_limits<double>::epsilon())||
  115. (abs(yf+static_cast<double>(1)) <
  116. numeric_limits<double>::epsilon())||
  117. (abs(yf-static_cast<long double>(1)) <
  118. numeric_limits<long double>::epsilon())||
  119. (abs(yf+static_cast<long double>(1)) <
  120. numeric_limits<long double>::epsilon())
  121. )
  122. {
  123. BOOST_TEST_MESSAGE("Platform's numerics may lack precision.");
  124. }
  125. else
  126. {
  127. #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
  128. BOOST_TEST_MESSAGE( ::std::setw(15)
  129. << atanh_error_evaluator(xf)
  130. << ::std::setw(15)
  131. << atanh_error_evaluator(xd)
  132. << ::std::setw(15)
  133. << atanh_error_evaluator(xl));
  134. #else
  135. BOOST_TEST_MESSAGE( ::std::setw(15)
  136. << atanh_error_evaluator(xf)
  137. << ::std::setw(15)
  138. << atanh_error_evaluator(xd));
  139. #endif
  140. }
  141. }
  142. }
  143. BOOST_TEST_MESSAGE(" ");
  144. }