mirror of
				https://github.com/saitohirga/WSJT-X.git
				synced 2025-11-04 05:50:31 -05:00 
			
		
		
		
	
		
			
	
	
		
			116 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
		
		
			
		
	
	
			116 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| 
								 | 
							
								//  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
							 |