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