Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-18 09:09:34

0001 // Copyright (c) 2017-2025, University of Cincinnati, developed by Henry Schreiner
0002 // under NSF AWARD 1414736 and by the respective contributors.
0003 // All rights reserved.
0004 //
0005 // SPDX-License-Identifier: BSD-3-Clause
0006 
0007 #pragma once
0008 
0009 // IWYU pragma: private, include "CLI/CLI.hpp"
0010 
0011 // On GCC < 4.8, the following define is often missing. Due to the
0012 // fact that this library only uses sleep_for, this should be safe
0013 #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 5 && __GNUC_MINOR__ < 8
0014 #define _GLIBCXX_USE_NANOSLEEP
0015 #endif
0016 
0017 #include <cmath>
0018 
0019 #include <array>
0020 #include <chrono>
0021 #include <cstdio>
0022 #include <functional>
0023 #include <iostream>
0024 #include <string>
0025 #include <utility>
0026 
0027 namespace CLI {
0028 
0029 /// This is a simple timer with pretty printing. Creating the timer starts counting.
0030 class Timer {
0031   protected:
0032     /// This is a typedef to make clocks easier to use
0033     using clock = std::chrono::steady_clock;
0034 
0035     /// This typedef is for points in time
0036     using time_point = std::chrono::time_point<clock>;
0037 
0038     /// This is the type of a printing function, you can make your own
0039     using time_print_t = std::function<std::string(std::string, std::string)>;
0040 
0041     /// This is the title of the timer
0042     std::string title_;
0043 
0044     /// This is the function that is used to format most of the timing message
0045     time_print_t time_print_;
0046 
0047     /// This is the starting point (when the timer was created)
0048     time_point start_;
0049 
0050     /// This is the number of times cycles (print divides by this number)
0051     std::size_t cycles{1};
0052 
0053   public:
0054     /// Standard print function, this one is set by default
0055     static std::string Simple(std::string title, std::string time) { return title + ": " + time; }
0056 
0057     /// This is a fancy print function with --- headers
0058     static std::string Big(std::string title, std::string time) {
0059         return std::string("-----------------------------------------\n") + "| " + title + " | Time = " + time + "\n" +
0060                "-----------------------------------------";
0061     }
0062 
0063   public:
0064     /// Standard constructor, can set title and print function
0065     explicit Timer(std::string title = "Timer", time_print_t time_print = Simple)
0066         : title_(std::move(title)), time_print_(std::move(time_print)), start_(clock::now()) {}
0067 
0068     /// Time a function by running it multiple times. Target time is the len to target.
0069     std::string time_it(std::function<void()> f, double target_time = 1) {
0070         time_point start = start_;
0071         double total_time = NAN;
0072 
0073         start_ = clock::now();
0074         std::size_t n = 0;
0075         do {
0076             f();
0077             std::chrono::duration<double> elapsed = clock::now() - start_;
0078             total_time = elapsed.count();
0079         } while(n++ < 100u && total_time < target_time);
0080 
0081         std::string out = make_time_str(total_time / static_cast<double>(n)) + " for " + std::to_string(n) + " tries";
0082         start_ = start;
0083         return out;
0084     }
0085 
0086     /// This formats the numerical value for the time string
0087     std::string make_time_str() const {  // NOLINT(modernize-use-nodiscard)
0088         time_point stop = clock::now();
0089         std::chrono::duration<double> elapsed = stop - start_;
0090         double time = elapsed.count() / static_cast<double>(cycles);
0091         return make_time_str(time);
0092     }
0093 
0094     // LCOV_EXCL_START
0095     /// This prints out a time string from a time
0096     std::string make_time_str(double time) const {  // NOLINT(modernize-use-nodiscard)
0097         auto print_it = [](double x, std::string unit) {
0098             const unsigned int buffer_length = 50;
0099             std::array<char, buffer_length> buffer;
0100             std::snprintf(buffer.data(), buffer_length, "%.5g", x);
0101             return buffer.data() + std::string(" ") + unit;
0102         };
0103 
0104         if(time < .000001)
0105             return print_it(time * 1000000000, "ns");
0106         if(time < .001)
0107             return print_it(time * 1000000, "us");
0108         if(time < 1)
0109             return print_it(time * 1000, "ms");
0110         return print_it(time, "s");
0111     }
0112     // LCOV_EXCL_STOP
0113 
0114     /// This is the main function, it creates a string
0115     std::string to_string() const { return time_print_(title_, make_time_str()); }  // NOLINT(modernize-use-nodiscard)
0116 
0117     /// Division sets the number of cycles to divide by (no graphical change)
0118     Timer &operator/(std::size_t val) {
0119         cycles = val;
0120         return *this;
0121     }
0122 };
0123 
0124 /// This class prints out the time upon destruction
0125 class AutoTimer : public Timer {
0126   public:
0127     /// Reimplementing the constructor is required in GCC 4.7
0128     explicit AutoTimer(std::string title = "Timer", time_print_t time_print = Simple) : Timer(title, time_print) {}
0129     // GCC 4.7 does not support using inheriting constructors.
0130 
0131     /// This destructor prints the string
0132     ~AutoTimer() { std::cout << to_string() << '\n'; }
0133 };
0134 
0135 }  // namespace CLI
0136 
0137 /// This prints out the time if shifted into a std::cout like stream.
0138 inline std::ostream &operator<<(std::ostream &in, const CLI::Timer &timer) { return in << timer.to_string(); }