|
- /**
- * \file
- * \brief Utilities header
- *
- * \author
- * Christos Choutouridis AEM:8997
- * <cchoutou@ece.auth.gr>
- */
- #ifndef UTILS_HPP_
- #define UTILS_HPP_
-
- #include <vector>
- #include <iostream>
- #include <chrono>
- #include <unistd.h>
- #include <algorithm>
-
- #include "config.h"
-
-
- /*!
- * A Logger for entire program.
- */
- struct Log {
- struct Endl {} endl; //!< a tag object to to use it as a new line request.
-
- //! We provide logging via << operator
- template<typename T>
- Log &operator<<(T &&t) {
- if (config.verbose) {
- if (line_) {
- std::cout << "[Log]: " << t;
- line_ = false;
- } else
- std::cout << t;
- }
- return *this;
- }
-
- // overload for special end line handling
- Log &operator<<(Endl e) {
- (void) e;
- if (config.verbose) {
- std::cout << '\n';
- line_ = true;
- }
- return *this;
- }
-
- private:
- bool line_{true};
- };
-
- extern Log logger;
-
- /*!
- * A small timing utility based on chrono that supports timing rounds
- * and returning the median of them. Time can accumulate to the measurement
- * for each round.
- */
- struct Timing {
- using Tpoint = std::chrono::steady_clock::time_point;
- using Tduration = std::chrono::microseconds;
- using microseconds = std::chrono::microseconds;
- using milliseconds = std::chrono::milliseconds;
- using seconds = std::chrono::seconds;
-
- //! Setup measurement rounds
- void init(size_t rounds) {
- duration_.resize(rounds);
- for (auto& d : duration_)
- d = Tduration::zero();
- }
-
- //! tool to mark the starting point
- Tpoint start() noexcept { return mark_ = std::chrono::steady_clock::now(); }
-
- //! tool to mark the ending point
- Tpoint stop() noexcept {
- Tpoint now = std::chrono::steady_clock::now();
- duration_[current_] += dt(now, mark_);
- return now;
- }
-
- //! Switch timing slot
- void next() noexcept {
- ++current_;
- current_ %= duration_.size();
- }
-
- Tduration& median() noexcept {
- std::sort(duration_.begin(), duration_.end());
- return duration_[duration_.size()/2];
- }
-
- //! A duration calculation utility
- static Tduration dt(Tpoint t2, Tpoint t1) noexcept {
- return std::chrono::duration_cast<Tduration>(t2 - t1);
- }
-
- //! Tool to print the time interval
- static void print_duration(const Tduration& duration, const char *what) noexcept {
- if (std::chrono::duration_cast<microseconds>(duration).count() < 10000)
- std::cout << "[Timing] " << what << ": "
- << std::to_string(std::chrono::duration_cast<microseconds>(duration).count()) << " [usec]\n";
- else if (std::chrono::duration_cast<milliseconds>(duration).count() < 10000)
- std::cout << "[Timing] " << what << ": "
- << std::to_string(std::chrono::duration_cast<milliseconds>(duration).count()) << " [msec]\n";
- else {
- char stime[26]; // fit ulong
- auto sec = std::chrono::duration_cast<seconds>(duration).count();
- auto msec = (std::chrono::duration_cast<milliseconds>(duration).count() % 1000) / 10; // keep 2 digit
- std::sprintf(stime, "%ld.%1ld", sec, msec);
- std::cout << "[Timing] " << what << ": " << stime << " [sec]\n";
- }
-
- }
-
- private:
- size_t current_{0};
- Tpoint mark_{};
- std::vector<Tduration> duration_{1};
- };
-
- /*!
- * A "high level function"-like utility macro to forward a function call
- * and accumulate the execution time to the corresponding timing object.
- *
- * @param Tim The Timing object [Needs to have methods start() and stop()]
- * @param Func The function name
- * @param ... The arguments to pass to function (the preprocessor way)
- */
- #define timeCall(Tim, Func, ...) \
- Tim.start(); \
- Func(__VA_ARGS__); \
- Tim.stop(); \
-
-
- /*!
- * A utility to check if a number is power of two
- *
- * @tparam Integral The integral type of the number to check
- * @param x The number to check
- * @return True if it is power of 2, false otherwise
- */
- template <typename Integral>
- constexpr inline bool isPowerOfTwo(Integral x) noexcept {
- return (!(x & (x - 1)) && x);
- }
-
-
- #endif /* UTILS_HPP_ */
|