2019-03-28 16:38:50 +01:00
# ifndef DEF_utils
# define DEF_utils
# include <ostream>
2019-03-30 11:48:51 +01:00
# include <utility>
2019-03-28 16:38:50 +01:00
# define PRINT_VAR(x) std::cout << #x << "\t= " << (x) << "\n"
# define PRINT_VEC(x); {std::cout << #x << "\t= "; \
for ( unsigned int i_print_vec = 0 ; i_print_vec < ( x ) . size ( ) ; i_print_vec + + ) \
std : : cout < < ( x ) [ i_print_vec ] < < " \t " ; \
std : : cout < < " \n " ; }
2019-03-30 11:48:51 +01:00
# define PRINT_STR(x) std::cout << (x) << "\n"
template < typename T , typename T2 > auto min ( const T & a , const T2 & b ) - > decltype ( a | b ) { return ( a < b ) ? T ( a ) : T ( b ) ; }
template < typename T , typename T2 > auto max ( const T & a , const T2 & b ) - > decltype ( a | b ) { return ( a < b ) ? T ( b ) : T ( a ) ; }
2019-03-28 16:38:50 +01:00
2019-04-01 16:18:34 +02:00
/// To be sure that floating point numbers won't be casted to integers in ::abs()...
template < typename T > T sureAbs ( const T & x ) { return ( x < T ( 0 ) ) ? - x : x ; }
2019-04-24 12:13:56 +02:00
2019-04-25 10:59:42 +02:00
/*
2019-04-24 12:13:56 +02:00
/// Generic operator<< for ostream, (to print std::vector, etd::list, std::map, etc). Can generate conflicts with specialized operator<< overloads.
2019-03-28 16:38:50 +01:00
template < typename T , template < class , class . . . > class C , class . . . Args >
std : : ostream & operator < < ( std : : ostream & os , const C < T , Args . . . > & objs )
{
for ( auto const & obj : objs )
os < < obj < < ' ' ;
return os ;
2019-04-24 12:13:56 +02:00
} //*/
/// define UTILS_NO_CHRONO to deactivate chronometer
# ifndef UTILS_NO_CHRONO
# include <iostream>
# include <chrono>
# include <ratio>
# include <ctime>
2019-03-28 16:38:50 +01:00
2019-04-24 12:13:56 +02:00
/// Convenience macro to create a Chronometer object that will measure the execution time of its scope.
# define TIMER(str) Chronometer __chrono((str))
2019-04-25 10:59:42 +02:00
/// Convenience macro to create a Chronometer object that will measure the execution time of its scope, with a for-loop enveloping the code to time.
///
/// Usage : TIMER_FOR("My timer", N, /* The code will be executed N times ! */)
# define TIMER_FOR(str, N, code) {Chronometer __chrono((str)); for(size_t i_TIMER_FOR = 0 ; i_TIMER_FOR < N ; i_TIMER_FOR++) {code} }
2019-04-24 12:13:56 +02:00
/// \class Chronometer class. Used to measure the execution time of its scope.
///
/// Usage :
2019-04-25 10:59:42 +02:00
/// \code{.cpp}
/// {
/// TIMER("My timer");
/// /* some code to be profiled */
/// }// <--- the chronometer measures the time between the call to its constructor and the call to its destructor.
/// \endcode
2019-04-24 12:13:56 +02:00
///
/// Possible output :
///
/// My timer : 0.12317568 s (+/- 1e-09 s)
///
2019-04-25 10:59:42 +02:00
/// Alternate usage :
/// \code{.cpp}
/// {
/// Chronometer chronom("", false);
/// /* some code to time */
/// chronom.MeasureTimeElapsed();// prints how much time elapsed since the creation of the object
/// /* some code to time */
/// chronom.MeasureTimeElapsed();// prints how much time elapsed since the creation of the object
/// chronom.Reset();// resets the timer to 0
/// /* some code to time */
/// chronom.MeasureTimeElapsed();// prints how much time elapsed since the last reset
/// } // no message is displayed because displayAtDestruction_ is set to false
/// \endcode
///
2019-04-24 12:13:56 +02:00
template < int T = 1 >
struct Chronometer
2019-03-30 11:48:51 +01:00
{
2019-04-24 12:13:56 +02:00
std : : string name ;
std : : chrono : : high_resolution_clock : : time_point t0 ;
2019-04-25 10:59:42 +02:00
bool displayAtDestruction ;
2019-04-24 12:13:56 +02:00
/// Creates the Chronometer object with the provided name and stores the time.
2019-04-25 10:59:42 +02:00
///
/// \param name_ : Name to display
/// \param displayAtDestruction_ : if true, a message is printed to the console during the destruction of the object.
Chronometer ( const std : : string & name_ = " " , bool displayAtDestruction_ = true )
2019-04-24 12:13:56 +02:00
: name ( name_ ) ,
2019-04-25 10:59:42 +02:00
t0 ( std : : chrono : : high_resolution_clock : : now ( ) ) ,
displayAtDestruction ( displayAtDestruction_ )
2019-04-24 12:13:56 +02:00
{ }
/// Measures the time elapsed between the creation of the object and its destruction, and prints the result in std::cout.
2019-04-25 10:59:42 +02:00
~ Chronometer ( ) { if ( displayAtDestruction ) { MeasureTimeElapsed ( ) ; } }
2019-04-24 12:13:56 +02:00
/// Resets the timer. Allows the measurement of the execution time of several sub-intervals in the current scope.
void Reset ( ) { t0 = std : : chrono : : high_resolution_clock : : now ( ) ; }
2019-04-25 10:59:42 +02:00
double GetTime ( ) const
2019-04-24 12:13:56 +02:00
{
std : : chrono : : high_resolution_clock : : time_point t1 = std : : chrono : : high_resolution_clock : : now ( ) ;
std : : chrono : : duration < double > time_span = std : : chrono : : duration_cast < std : : chrono : : duration < double > > ( t1 - t0 ) ;
2019-04-25 10:59:42 +02:00
return time_span . count ( ) ;
}
double GetResolution ( ) const
{
2019-04-24 12:13:56 +02:00
auto resolution_ratio = std : : chrono : : high_resolution_clock : : period ( ) ;
2019-04-25 10:59:42 +02:00
return double ( resolution_ratio . num ) / resolution_ratio . den ;
}
2019-04-24 12:13:56 +02:00
2019-04-25 10:59:42 +02:00
/// Measures the time elapsed between the creation of the object and its destruction, and prints the result in std::cout.
void MeasureTimeElapsed ( ) const
{
// measure time since object creation and print it in the console
2019-04-24 12:13:56 +02:00
std : : cout . precision ( 16 ) ;
2019-04-25 10:59:42 +02:00
std : : cout < < name . c_str ( ) < < " \t : " < < GetTime ( ) < < " s (+/- " < < GetResolution ( ) < < " s) " < < std : : endl ; // use of c_str() so that there is no ambiguity with the generic operator<<
2019-04-24 12:13:56 +02:00
}
2019-03-30 11:48:51 +01:00
} ;
2019-04-24 12:13:56 +02:00
# else // chronometer
# define TIMER(str)
2019-04-25 10:59:42 +02:00
# define TIMER_FOR(str, N, code) { for(size_t i_TIMER_FOR = 0 ; i_TIMER_FOR < N ; i_TIMER_FOR++) {code} }
2019-04-24 12:13:56 +02:00
# endif // chronometer
2019-03-28 16:38:50 +01:00
# endif