test_difference.cpp 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. // (C) Copyright John Maddock 2015.
  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 <boost/math/concepts/real_concept.hpp>
  6. #define BOOST_TEST_MAIN
  7. #include <boost/test/unit_test.hpp>
  8. #include <boost/test/tools/floating_point_comparison.hpp>
  9. #include <boost/math/special_functions/next.hpp>
  10. #include <boost/math/special_functions/ulp.hpp>
  11. #include <boost/math/special_functions/relative_difference.hpp>
  12. #include <iostream>
  13. #include <iomanip>
  14. template <class T>
  15. void test_value(const T& val, const char* name)
  16. {
  17. using namespace boost::math;
  18. using std::fabs;
  19. T next = float_next(val);
  20. T prev = float_prior(val);
  21. if((boost::math::isinf)(next))
  22. {
  23. BOOST_CHECK_EQUAL(relative_difference(val, next), tools::max_value<T>());
  24. return;
  25. }
  26. if((boost::math::isinf)(prev))
  27. {
  28. BOOST_CHECK_EQUAL(relative_difference(val, prev), tools::max_value<T>());
  29. return;
  30. }
  31. BOOST_CHECK_EQUAL(relative_difference(val, next), relative_difference(next, val));
  32. BOOST_CHECK_EQUAL(epsilon_difference(val, next), epsilon_difference(next, val));
  33. BOOST_CHECK_LE(relative_difference(val, next), boost::math::tools::epsilon<T>());
  34. BOOST_CHECK_LE(epsilon_difference(val, next), T(1));
  35. if((fabs(val) > tools::min_value<T>()) || (fabs(next) > tools::min_value<T>()))
  36. {
  37. BOOST_CHECK_GT(relative_difference(val, next), T(0));
  38. BOOST_CHECK_GT(epsilon_difference(val, next), T(0));
  39. }
  40. else
  41. {
  42. BOOST_CHECK_EQUAL(relative_difference(val, next), T(0));
  43. BOOST_CHECK_EQUAL(epsilon_difference(val, next), T(0));
  44. }
  45. BOOST_CHECK_EQUAL(relative_difference(val, prev), relative_difference(prev, val));
  46. BOOST_CHECK_EQUAL(epsilon_difference(val, prev), epsilon_difference(prev, val));
  47. if((fabs(val) > tools::min_value<T>()) || (fabs(prev) > tools::min_value<T>()))
  48. {
  49. BOOST_CHECK_GT(relative_difference(val, prev), T(0));
  50. BOOST_CHECK_GT(epsilon_difference(val, prev), T(0));
  51. }
  52. else
  53. {
  54. BOOST_CHECK_EQUAL(relative_difference(val, prev), T(0));
  55. BOOST_CHECK_EQUAL(epsilon_difference(val, prev), T(0));
  56. }
  57. }
  58. template <class T>
  59. void test_values(const T& val, const char* name)
  60. {
  61. static const T a = static_cast<T>(1.3456724e22);
  62. static const T b = static_cast<T>(1.3456724e-22);
  63. static const T z = 0;
  64. static const T one = 1;
  65. static const T two = 2;
  66. std::cout << "Testing type " << name << std::endl;
  67. T den = (std::numeric_limits<T>::min)() / 4;
  68. if(den != 0)
  69. {
  70. std::cout << "Denormals are active\n";
  71. }
  72. else
  73. {
  74. std::cout << "Denormals are flushed to zero.\n";
  75. }
  76. test_value(a, name);
  77. test_value(-a, name);
  78. test_value(b, name);
  79. test_value(-b, name);
  80. test_value(boost::math::tools::epsilon<T>(), name);
  81. test_value(-boost::math::tools::epsilon<T>(), name);
  82. test_value(boost::math::tools::min_value<T>(), name);
  83. test_value(-boost::math::tools::min_value<T>(), name);
  84. if (std::numeric_limits<T>::is_specialized && (std::numeric_limits<T>::has_denorm == std::denorm_present) && ((std::numeric_limits<T>::min)() / 2 != 0))
  85. {
  86. test_value(z, name);
  87. test_value(-z, name);
  88. }
  89. test_value(one, name);
  90. test_value(-one, name);
  91. test_value(two, name);
  92. test_value(-two, name);
  93. static const int primes[] = {
  94. 11, 13, 17, 19, 23, 29,
  95. 31, 37, 41, 43, 47, 53, 59, 61, 67, 71,
  96. 73, 79, 83, 89, 97, 101, 103, 107, 109, 113,
  97. 127, 131, 137, 139, 149, 151, 157, 163, 167, 173,
  98. 179, 181, 191, 193, 197, 199, 211, 223, 227, 229,
  99. 233, 239, 241, 251, 257, 263, 269, 271, 277, 281,
  100. 283, 293, 307, 311, 313, 317, 331, 337, 347, 349,
  101. 353, 359, 367, 373, 379, 383, 389, 397, 401, 409,
  102. 419, 421, 431, 433, 439, 443, 449, 457, 461, 463,
  103. };
  104. for(unsigned i = 0; i < sizeof(primes) / sizeof(primes[0]); ++i)
  105. {
  106. for(unsigned j = 0; j < sizeof(primes) / sizeof(primes[0]); ++j)
  107. {
  108. test_value(T(primes[i]) / T(primes[j]), name);
  109. test_value(-T(primes[i]) / T(primes[j]), name);
  110. }
  111. }
  112. using namespace boost::math;
  113. BOOST_CHECK_EQUAL(relative_difference(tools::min_value<T>(), -tools::min_value<T>()), tools::max_value<T>());
  114. BOOST_CHECK_EQUAL(epsilon_difference(tools::min_value<T>(), -tools::min_value<T>()), tools::max_value<T>());
  115. if(std::numeric_limits<T>::has_infinity)
  116. {
  117. BOOST_CHECK_EQUAL(relative_difference(std::numeric_limits<T>::infinity(), std::numeric_limits<T>::infinity()), T(0));
  118. BOOST_CHECK_EQUAL(epsilon_difference(std::numeric_limits<T>::infinity(), std::numeric_limits<T>::infinity()), T(0));
  119. BOOST_CHECK_EQUAL(relative_difference(std::numeric_limits<T>::infinity(), tools::max_value<T>()), tools::max_value<T>());
  120. BOOST_CHECK_EQUAL(epsilon_difference(std::numeric_limits<T>::infinity(), tools::max_value<T>()), tools::max_value<T>());
  121. BOOST_CHECK_EQUAL(relative_difference(std::numeric_limits<T>::infinity(), tools::max_value<T>() / 2), tools::max_value<T>());
  122. BOOST_CHECK_EQUAL(epsilon_difference(std::numeric_limits<T>::infinity(), tools::max_value<T>() / 2), tools::max_value<T>());
  123. BOOST_CHECK_EQUAL(relative_difference(tools::max_value<T>(), std::numeric_limits<T>::infinity()), tools::max_value<T>());
  124. BOOST_CHECK_EQUAL(epsilon_difference(tools::max_value<T>(), std::numeric_limits<T>::infinity()), tools::max_value<T>());
  125. BOOST_CHECK_EQUAL(relative_difference(tools::max_value<T>() / 2, std::numeric_limits<T>::infinity()), tools::max_value<T>());
  126. BOOST_CHECK_EQUAL(epsilon_difference(tools::max_value<T>() / 2, std::numeric_limits<T>::infinity()), tools::max_value<T>());
  127. }
  128. if(std::numeric_limits<T>::has_quiet_NaN)
  129. {
  130. BOOST_CHECK_EQUAL(relative_difference(std::numeric_limits<T>::quiet_NaN(), std::numeric_limits<T>::quiet_NaN()), tools::max_value<T>());
  131. BOOST_CHECK_EQUAL(epsilon_difference(std::numeric_limits<T>::quiet_NaN(), std::numeric_limits<T>::quiet_NaN()), tools::max_value<T>());
  132. BOOST_CHECK_EQUAL(relative_difference(std::numeric_limits<T>::quiet_NaN(), T(2)), tools::max_value<T>());
  133. BOOST_CHECK_EQUAL(epsilon_difference(std::numeric_limits<T>::quiet_NaN(), T(2)), tools::max_value<T>());
  134. BOOST_CHECK_EQUAL(relative_difference(T(2), std::numeric_limits<T>::quiet_NaN()), tools::max_value<T>());
  135. BOOST_CHECK_EQUAL(epsilon_difference(T(2), std::numeric_limits<T>::quiet_NaN()), tools::max_value<T>());
  136. }
  137. }
  138. BOOST_AUTO_TEST_CASE( test_main )
  139. {
  140. test_values(1.0f, "float");
  141. test_values(1.0, "double");
  142. #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
  143. test_values(1.0L, "long double");
  144. test_values(boost::math::concepts::real_concept(0), "real_concept");
  145. #endif
  146. }