hypot_test.cpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  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. #include <pch_light.hpp>
  6. #define BOOST_MATH_OVERFLOW_ERROR_POLICY ignore_error
  7. #define BOOST_TEST_MAIN
  8. #include <boost/test/unit_test.hpp>
  9. #include <boost/test/tools/floating_point_comparison.hpp>
  10. #include <boost/math/special_functions/math_fwd.hpp>
  11. #include <cmath>
  12. #ifdef BOOST_NO_STDC_NAMESPACE
  13. namespace std{ using ::sqrt; }
  14. #endif
  15. //
  16. // test_boundaries:
  17. // This is an accuracy test, sets the two arguments to hypot to just
  18. // above or just below various boundary conditions, and checks the accuracy
  19. // of the result. The values computed at double precision will use a
  20. // different computation method to those computed at float precision:
  21. // as long as these compute the same values then everything's OK.
  22. //
  23. // Tolerance is 2*epsilon, expressed here as a persentage:
  24. //
  25. static const float tolerance = 200 * (std::numeric_limits<float>::epsilon)();
  26. const float boundaries[] = {
  27. 0,
  28. 1,
  29. 2,
  30. (std::numeric_limits<float>::max)()/2,
  31. (std::numeric_limits<float>::min)(),
  32. std::numeric_limits<float>::epsilon(),
  33. std::sqrt((std::numeric_limits<float>::max)()) / 2,
  34. std::sqrt((std::numeric_limits<float>::min)()),
  35. std::sqrt((std::numeric_limits<float>::max)()) / 4,
  36. std::sqrt((std::numeric_limits<float>::min)()) * 2,
  37. };
  38. void do_test_boundaries(float x, float y)
  39. {
  40. float expected = static_cast<float>((boost::math::hypot)(
  41. #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
  42. static_cast<long double>(x),
  43. static_cast<long double>(y)));
  44. #else
  45. static_cast<double>(x),
  46. static_cast<double>(y)));
  47. #endif
  48. float found = (boost::math::hypot)(x, y);
  49. BOOST_CHECK_CLOSE(expected, found, tolerance);
  50. }
  51. void test_boundaries(float x, float y)
  52. {
  53. do_test_boundaries(x, y);
  54. do_test_boundaries(-x, y);
  55. do_test_boundaries(-x, -y);
  56. do_test_boundaries(x, -y);
  57. }
  58. void test_boundaries(float x)
  59. {
  60. for(unsigned i = 0; i < sizeof(boundaries)/sizeof(float); ++i)
  61. {
  62. test_boundaries(x, boundaries[i]);
  63. test_boundaries(x, boundaries[i] + std::numeric_limits<float>::epsilon()*boundaries[i]);
  64. test_boundaries(x, boundaries[i] - std::numeric_limits<float>::epsilon()*boundaries[i]);
  65. }
  66. }
  67. void test_boundaries()
  68. {
  69. for(unsigned i = 0; i < sizeof(boundaries)/sizeof(float); ++i)
  70. {
  71. test_boundaries(boundaries[i]);
  72. test_boundaries(boundaries[i] + std::numeric_limits<float>::epsilon()*boundaries[i]);
  73. test_boundaries(boundaries[i] - std::numeric_limits<float>::epsilon()*boundaries[i]);
  74. }
  75. }
  76. void test_spots()
  77. {
  78. static const float zero = 0;
  79. for(unsigned i = 0; i < sizeof(boundaries)/sizeof(float); ++i)
  80. {
  81. BOOST_CHECK_EQUAL(boost::math::hypot(boundaries[i], zero), std::fabs(boundaries[i]));
  82. BOOST_CHECK_EQUAL(boost::math::hypot(-boundaries[i], zero), std::fabs(-boundaries[i]));
  83. BOOST_CHECK_EQUAL(boost::math::hypot(boundaries[i], -zero), std::fabs(boundaries[i]));
  84. BOOST_CHECK_EQUAL(boost::math::hypot(-boundaries[i], -zero), std::fabs(-boundaries[i]));
  85. for(unsigned j = 0; j < sizeof(boundaries)/sizeof(float); ++j)
  86. {
  87. BOOST_CHECK_EQUAL(boost::math::hypot(boundaries[i], boundaries[j]), boost::math::hypot(boundaries[j], boundaries[i]));
  88. BOOST_CHECK_EQUAL(boost::math::hypot(boundaries[i], boundaries[j]), boost::math::hypot(boundaries[i], -boundaries[j]));
  89. BOOST_CHECK_EQUAL(boost::math::hypot(-boundaries[i], -boundaries[j]), boost::math::hypot(-boundaries[j], -boundaries[i]));
  90. BOOST_CHECK_EQUAL(boost::math::hypot(-boundaries[i], -boundaries[j]), boost::math::hypot(-boundaries[i], boundaries[j]));
  91. }
  92. }
  93. if((std::numeric_limits<float>::has_infinity) && (std::numeric_limits<float>::has_quiet_NaN))
  94. {
  95. static const float nan = std::numeric_limits<float>::quiet_NaN();
  96. static const float inf = std::numeric_limits<float>::infinity();
  97. BOOST_CHECK_EQUAL(boost::math::hypot(inf, nan), inf);
  98. BOOST_CHECK_EQUAL(boost::math::hypot(-inf, nan), inf);
  99. BOOST_CHECK_EQUAL(boost::math::hypot(nan, inf), inf);
  100. BOOST_CHECK_EQUAL(boost::math::hypot(nan, -inf), inf);
  101. for(unsigned j = 0; j < sizeof(boundaries)/sizeof(float); ++j)
  102. {
  103. BOOST_CHECK_EQUAL(boost::math::hypot(boundaries[j], inf), inf);
  104. BOOST_CHECK_EQUAL(boost::math::hypot(-boundaries[j], inf), inf);
  105. BOOST_CHECK_EQUAL(boost::math::hypot(inf, boundaries[j]), inf);
  106. BOOST_CHECK_EQUAL(boost::math::hypot(inf, -boundaries[j]), inf);
  107. BOOST_CHECK_EQUAL(boost::math::hypot(boundaries[j], -inf), inf);
  108. BOOST_CHECK_EQUAL(boost::math::hypot(-boundaries[j], -inf), inf);
  109. BOOST_CHECK_EQUAL(boost::math::hypot(-inf, boundaries[j]), inf);
  110. BOOST_CHECK_EQUAL(boost::math::hypot(-inf, -boundaries[j]), inf);
  111. }
  112. }
  113. }
  114. BOOST_AUTO_TEST_CASE( test_main )
  115. {
  116. BOOST_MATH_CONTROL_FP;
  117. test_boundaries();
  118. test_spots();
  119. }