123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115 |
- // Copyright John Maddock 2015.
- // Use, modification and distribution are subject to the
- // Boost Software License, Version 1.0. (See accompanying file
- // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
- #ifndef PERFORMANCE_HPP
- #define PERFORMANCE_HPP
- #include <boost/math/special_functions/relative_difference.hpp>
- #include <boost/array.hpp>
- #include <boost/chrono.hpp>
- #include <boost/regex.hpp>
- template <class Array>
- void add_data(const Array& a)
- {
- //
- // This function is called multiple times to merge multiple data sets into one big table:
- //
- for(typename Array::const_iterator i = a.begin(); i != a.end(); ++i)
- {
- data.push_back(std::vector<double>());
- for(typename Array::value_type::const_iterator j = i->begin(); j != i->end(); ++j)
- {
- data.back().push_back(*j);
- }
- }
- }
- template <class Func, class Result>
- void screen_data(Func f, Result r)
- {
- //
- // If any of the implementations being tested produces garbage for one of our
- // test cases (or else if we test a domain they don't support), then we remove that
- // row from the table. This allows us to only test a common supported sub-set for performance:
- //
- for(std::vector<std::vector<double> >::size_type row = 0; row < data.size(); ++row)
- {
- try
- {
- double computed = f(data[row]);
- double expected = r(data[row]);
- double err = boost::math::relative_difference(computed, expected);
- if(err > 1e-7)
- {
- std::cout << "Erasing row: ";
- for(unsigned i = 0; i < data[row].size(); ++i)
- {
- std::cout << data[row][i] << " ";
- }
- std::cout << "Error was " << err << std::endl;
- data.erase(data.begin() + row);
- --row;
- }
- }
- catch(const std::exception& e)
- {
- std::cout << "Erasing row: ";
- for(unsigned i = 0; i < data[row].size(); ++i)
- {
- std::cout << data[row][i] << " ";
- }
- std::cout << "due to thrown exception: " << e.what() << std::endl;
- data.erase(data.begin() + row);
- --row;
- }
- }
- }
- template <class Clock>
- struct stopwatch
- {
- typedef typename Clock::duration duration;
- stopwatch()
- {
- m_start = Clock::now();
- }
- duration elapsed()
- {
- return Clock::now() - m_start;
- }
- void reset()
- {
- m_start = Clock::now();
- }
- private:
- typename Clock::time_point m_start;
- };
- double sum = 0;
- template <class Func>
- double exec_timed_test(Func f)
- {
- double t = 0;
- unsigned repeats = 1;
- do{
- stopwatch<boost::chrono::high_resolution_clock> w;
- for(unsigned count = 0; count < repeats; ++count)
- {
- for(std::vector<std::vector<double> >::const_iterator i = data.begin(); i != data.end(); ++i)
- sum += f(*i);
- }
- t = boost::chrono::duration_cast<boost::chrono::duration<double>>(w.elapsed()).count();
- if(t < 0.5)
- repeats *= 2;
- } while(t < 0.5);
- return t / (repeats * data.size());
- }
- #endif // PERFORMANCE_HPP
|