handle_test_result.hpp 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. // (C) Copyright John Maddock 2006-7.
  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_HANDLE_TEST_RESULT
  6. #define BOOST_MATH_HANDLE_TEST_RESULT
  7. #include <boost/math/tools/stats.hpp>
  8. #include <boost/math/tools/test.hpp>
  9. #include <boost/math/tools/precision.hpp>
  10. #include <boost/regex.hpp>
  11. #include <boost/test/test_tools.hpp>
  12. #include <iostream>
  13. #include <iomanip>
  14. #if defined(BOOST_INTEL)
  15. # pragma warning(disable:239)
  16. # pragma warning(disable:264)
  17. #endif
  18. //
  19. // Every client of this header has to define this function,
  20. // and initialise the table of expected results:
  21. //
  22. void expected_results();
  23. typedef std::pair<boost::regex, std::pair<boost::uintmax_t, boost::uintmax_t> > expected_data_type;
  24. typedef std::list<expected_data_type> list_type;
  25. inline list_type&
  26. get_expected_data()
  27. {
  28. static list_type data;
  29. return data;
  30. }
  31. inline void add_expected_result(
  32. const char* compiler,
  33. const char* library,
  34. const char* platform,
  35. const char* type_name,
  36. const char* test_name,
  37. const char* group_name,
  38. boost::uintmax_t max_peek_error,
  39. boost::uintmax_t max_mean_error)
  40. {
  41. std::string re("(?:");
  42. re += compiler;
  43. re += ")";
  44. re += "\\|";
  45. re += "(?:";
  46. re += library;
  47. re += ")";
  48. re += "\\|";
  49. re += "(?:";
  50. re += platform;
  51. re += ")";
  52. re += "\\|";
  53. re += "(?:";
  54. re += type_name;
  55. re += ")";
  56. re += "\\|";
  57. re += "(?:";
  58. re += test_name;
  59. re += ")";
  60. re += "\\|";
  61. re += "(?:";
  62. re += group_name;
  63. re += ")";
  64. get_expected_data().push_back(
  65. std::make_pair(boost::regex(re, boost::regex::perl | boost::regex::icase),
  66. std::make_pair(max_peek_error, max_mean_error)));
  67. }
  68. inline std::string build_test_name(const char* type_name, const char* test_name, const char* group_name)
  69. {
  70. std::string result(BOOST_COMPILER);
  71. result += "|";
  72. result += BOOST_STDLIB;
  73. result += "|";
  74. result += BOOST_PLATFORM;
  75. result += "|";
  76. result += type_name;
  77. result += "|";
  78. result += group_name;
  79. result += "|";
  80. result += test_name;
  81. return result;
  82. }
  83. inline const std::pair<boost::uintmax_t, boost::uintmax_t>&
  84. get_max_errors(const char* type_name, const char* test_name, const char* group_name)
  85. {
  86. static const std::pair<boost::uintmax_t, boost::uintmax_t> defaults(1, 1);
  87. std::string name = build_test_name(type_name, test_name, group_name);
  88. list_type& l = get_expected_data();
  89. list_type::const_iterator a(l.begin()), b(l.end());
  90. while(a != b)
  91. {
  92. if(regex_match(name, a->first))
  93. {
  94. #if 0
  95. std::cout << name << std::endl;
  96. std::cout << a->first.str() << std::endl;
  97. #endif
  98. return a->second;
  99. }
  100. ++a;
  101. }
  102. return defaults;
  103. }
  104. template <class T, class Seq>
  105. void handle_test_result(const boost::math::tools::test_result<T>& result,
  106. const Seq& worst, int row,
  107. const char* type_name,
  108. const char* test_name,
  109. const char* group_name)
  110. {
  111. #ifdef BOOST_MSVC
  112. #pragma warning(push)
  113. #pragma warning(disable:4127)
  114. #endif
  115. using namespace std; // To aid selection of the right pow.
  116. T eps = boost::math::tools::epsilon<T>();
  117. std::cout << std::setprecision(4);
  118. T max_error_found = (result.max)()/eps;
  119. T mean_error_found = result.rms()/eps;
  120. //
  121. // Begin by printing the main tag line with the results:
  122. //
  123. std::cout << test_name << "<" << type_name << "> Max = " << max_error_found
  124. << " RMS Mean=" << mean_error_found;
  125. //
  126. // If the max error is non-zero, give the row of the table that
  127. // produced the worst error:
  128. //
  129. if((result.max)() != 0)
  130. {
  131. std::cout << "\n worst case at row: "
  132. << row << "\n { ";
  133. if(std::numeric_limits<T>::digits10)
  134. {
  135. std::cout << std::setprecision(std::numeric_limits<T>::digits10 + 2);
  136. }
  137. else
  138. {
  139. std::cout << std::setprecision(std::numeric_limits<long double>::digits10 + 2);
  140. }
  141. for(unsigned i = 0; i < worst.size(); ++i)
  142. {
  143. if(i)
  144. std::cout << ", ";
  145. #if defined(__SGI_STL_PORT)
  146. std::cout << boost::math::tools::real_cast<double>(worst[i]);
  147. #else
  148. std::cout << worst[i];
  149. #endif
  150. }
  151. std::cout << " }";
  152. }
  153. std::cout << std::endl;
  154. //
  155. // Now verify that the results are within our expected bounds:
  156. //
  157. std::pair<boost::uintmax_t, boost::uintmax_t> const& bounds = get_max_errors(type_name, test_name, group_name);
  158. if(bounds.first < max_error_found)
  159. {
  160. std::cerr << "Peak error greater than expected value of " << bounds.first << std::endl;
  161. BOOST_CHECK(bounds.first >= max_error_found);
  162. }
  163. if(bounds.second < mean_error_found)
  164. {
  165. std::cerr << "Mean error greater than expected value of " << bounds.second << std::endl;
  166. BOOST_CHECK(bounds.second >= mean_error_found);
  167. }
  168. std::cout << std::endl;
  169. #ifdef BOOST_MSVC
  170. #pragma warning(pop)
  171. #endif
  172. }
  173. template <class T, class Seq>
  174. void print_test_result(const boost::math::tools::test_result<T>& result,
  175. const Seq& worst, int row, const char* name, const char* test)
  176. {
  177. using namespace std; // To aid selection of the right pow.
  178. T eps = boost::math::tools::epsilon<T>();
  179. std::cout << std::setprecision(4);
  180. T max_error_found = (result.max)()/eps;
  181. T mean_error_found = result.rms()/eps;
  182. //
  183. // Begin by printing the main tag line with the results:
  184. //
  185. std::cout << test << "(" << name << ") Max = " << max_error_found
  186. << " RMS Mean=" << mean_error_found;
  187. //
  188. // If the max error is non-zero, give the row of the table that
  189. // produced the worst error:
  190. //
  191. if((result.max)() != 0)
  192. {
  193. std::cout << "\n worst case at row: "
  194. << row << "\n { ";
  195. for(unsigned i = 0; i < worst.size(); ++i)
  196. {
  197. if(i)
  198. std::cout << ", ";
  199. std::cout << worst[i];
  200. }
  201. std::cout << " }";
  202. }
  203. std::cout << std::endl;
  204. }
  205. #endif // BOOST_MATH_HANDLE_TEST_RESULT