/// \brief This file is a header-only "library" of useful tools that are often needed when developping in C++.
///
/// The file contains the following tools (non-exhaustive list) :
/// Macros :
/// - `PRINT_VAR`, `PRINT_VEC`, and `PRINT_STR` macros to print the name of variables as well as the variables themselves.
/// - `RAND_A_B`, and `RAND_0_1`, to generate double precision floating point random numbers uniformly spread over an interval (using stdlib's rand()).
/// - `MIN` and `MAX` macros to return the min or max of two values (note that both arguments are evaluated twice).
///
/// Template functions :
/// - `min` and `max` to return the min or max of two values (they are evaluated only once).
/// - `sureAbs` to return the absolute value of a numeric type (that is never going to cast a floating point number into a integer like ::abs often does).
/// - `clamp(x, a, b)` to constrain a value `x` to an interval [a, b].
/// - `operator<<(std::ostream& os, const std::vector<T> & objs)` to print the contents of an std::vector to an ostream.
/// - `operator<<(std::ostream& os, const std::list<T> & objs)` to print the contents of an std::list to an ostream.
///
/// Not really template functions :
/// - `rand_xorwow` and `rand_parkmiller` to generate uniformly distributed pseudo-random numbers. Very fast. Very nice.
///
/// Classes :
/// - `Chronometer` to measure execution times, with convenient macros that hide the inner workings (see documentation of `Chronometer` for more info).
/// - `Profiler` to measure execution times of individual lines, with convenient macros that hide the inner workings (see documentation of `Profiler` for more info).
///
/// Some tools can be deactivated by defining the following defines BEFORE including `utils.hpp` :
/// - UTILS_NO_RAND : Deactivates the `rand_xorwow` and `rand_parkmiller` functions. Removes the inclusion of <cstdint>.
/// - UTILS_NO_CHRONO : Deactivates the `Chronometer` class. Removes the inclusion of the following standard headers : <iostream> <chrono> <ratio> <ctime>.
/// - UTILS_NO_PROFILER : Deactivates the `Profiler` class. Removes the inclusion of the following standard headers : <iostream> <iomanip> <chrono> <ratio> <ctime> <cmath> <algorithm> <vector>.
/// - UTILS_NO_OSTREAM_OPERATOR : Deactivates the `operator<<` template function for BOTH `std::vector` and `std::list`. In order to deactivate only one of the two, use `UTILS_NO_OSTREAM_OPERATOR_LIST` or `UTILS_NO_OSTREAM_OPERATOR_VECTOR`.
/// - UTILS_NO_OSTREAM_OPERATOR_LIST : Deactivates the `operator<<` template function for `std::list` ONLY.
/// - UTILS_NO_OSTREAM_OPERATOR_VECTOR : Deactivates the `operator<<` template function for `std::vector` ONLY.
#define TIMER(str) Chronometer __chrono((str)); ///< Convenience macro to create a Chronometer object that will measure the execution time of its scope.
/// \brief Chronometer class. Used to measure the execution time of its scope. Uses C++11 <chrono>.
///
/// The chronometer can be disabled by defining `UTILS_NO_CHRONO` before including the header. All the chronometer macros will be disabled safely and can be left in the code.
///
/// It is recommended to use the macros to use the Chronometer class.
/// Measures the time elapsed between the creation of the object and its destruction, and prints the result in std::cout. If displayname = "", the name stored in the object is used.
std::cout<<newname->c_str()<<"\t: "<<GetTime()<<" s (+/- "<<GetResolution()<<" s)"<<std::endl;// use of c_str() so that there is no ambiguity with the generic operator<<
// Define UTILS_NO_PROFILER to deactivate the profiler.
#ifndef UTILS_NO_PROFILER
#include<iostream>
#include<iomanip>
#include<cmath>
#include<vector>
#include<algorithm>
#include<chrono>
#include<ctime>
/// Maximum number of lines to store. If the file you want to profile has more lines than this value, change the value of this define before including the header.
#ifndef UTILS_PROFILER_NMAX
#define UTILS_PROFILER_NMAX 1000
#endif
#define P_LINE_INIT() Profiler _line_profiler(__FILE__); ///< Initializes the profiler object.
#define P_LINE_BEGIN() _line_profiler.Reset(); ///< Resets the timer of the profiler object.
#define P_LINE() _line_profiler.ProfileLine(__LINE__); ///< Measures the time elapsed since the last timer reset.
#define P_LINE_DISPLAY() _line_profiler.DisplayData(); ///< Prints the profiler results to the console.
/// \brief Profiler class. This class profiles a code line by line. It is intrusive : you need to modify your code in order to profile it.
///
/// Note that the presence of the profiler prevents the compiler from optimizing parts of the code, resulting in a much slower execution.
/// The profiler also adds overhead. In the example below, the profiled code is about 40 times slower when the profiler is active.
///
/// The profiler stores the measured execution time of each line in a static array stored on the stack. The size of this array is `UTILS_PROFILER_NMAX`, with a default value of 1000.
/// If the file you want to profile has more lines than this value, change the value of this define before including the header.
///
/// In order to use the profiler, it is recommended to use the provided macros : `P_LINE_INIT(), P_LINE_BEGIN(), P_LINE(), and P_LINE_DISPLAY()`.
///
/// The profiler can be disabled by defining `UTILS_NO_PROFILER` before including the header. The profiler macros can be left in the code without impacting its performance.
///
/// Here is an example of use :
/// \code{.cpp}
/// P_LINE_INIT() // Initializes the profiler object
/// {TIMER("Some code"); P_LINE()// Uses a regular timer to time the whole execution.
/// constexpr int N = 1000000; P_LINE()// Every P_LINE() call measures the time elapsed since the last reset.
/// float *a1 = new float[N]; P_LINE()// Every P_LINE() call also automatically resets the timer after measuring the time.
/// float *a2 = new float[N]; P_LINE()
///
/// for (size_t i = 0; i < N; i++) { P_LINE()// Placing the P_LINE() like so allows for the measurement of the condition checking and increment.
/// a1[i] = i; P_LINE()
/// a2[i] = N-i; P_LINE()
/// }
///
/// for (size_t i = 0; i < N; i++) { P_LINE()
/// float v = std::sqrt(a1[i]*a1[i] + a2[i]*a2[i]); P_LINE()
/// a1[i] = v; P_LINE()
/// }
///
/// /* Code that does not matter for profiling */
///
/// P_LINE_BEGIN() // Resets the timer of the profiler.
/// delete[] a1; P_LINE()// Measures only the time of this line (instead of everything from the last P_LINE() call).
/// delete[] a2; P_LINE()
/// }
///
/// // display results of the profiler
/// {TIMER("P_LINE_DISPLAY()");
/// P_LINE_DISPLAY()
/// }
/// \endcode
///
/// Here is a possible output of the profiler :
/// \code
/// Some code : 0.199525752 s (+/- 1e-09 s)
/// Profiler results :
/// Total time of profiled lines = 102050953 ns (0.1020509530000000 s)
/// Profiler results sorted by ascending line number (times in ns) :
/// main.cpp:15 134 ( 0.0001 %)
/// main.cpp:16 30 ( 0.0000 %)
/// main.cpp:17 4129 ( 0.0040 %)
/// main.cpp:18 2063 ( 0.0020 %)
/// main.cpp:20 15958766 ( 15.6380 %)
/// main.cpp:21 17706218 ( 17.3504 %)
/// main.cpp:22 17500810 ( 17.1491 %)
/// main.cpp:25 15480408 ( 15.1693 %)
/// main.cpp:26 19006015 ( 18.6240 %)
/// main.cpp:27 16052417 ( 15.7298 %)
/// main.cpp:30 223831 ( 0.2193 %)
/// main.cpp:31 116132 ( 0.1138 %)
///
/// Profiler results sorted by desending line time (times in ns) :
/// main.cpp:26 19006015 ( 18.6240 %)
/// main.cpp:21 17706218 ( 17.3504 %)
/// main.cpp:22 17500810 ( 17.1491 %)
/// main.cpp:27 16052417 ( 15.7298 %)
/// main.cpp:20 15958766 ( 15.6380 %)
/// main.cpp:25 15480408 ( 15.1693 %)
/// main.cpp:30 223831 ( 0.2193 %)
/// main.cpp:31 116132 ( 0.1138 %)
/// main.cpp:17 4129 ( 0.0040 %)
/// main.cpp:18 2063 ( 0.0020 %)
/// main.cpp:15 134 ( 0.0001 %)
/// main.cpp:16 30 ( 0.0000 %)
/// P_LINE_DISPLAY() : 8.2959e-05 s (+/- 1e-09 s)
/// \endcode
template<intT=1>
classProfiler
{
protected:
std::stringfile_name;///< File name to be displayed in the report.