#pragma once #include #include #include #include #include #include #include #include #include #include namespace fplus { using ExecutionTime = double; // in seconds // Holds a value of type T plus an execution time template class timed : public std::pair { using base_pair = std::pair; public: timed() : base_pair() {} timed(const T& val, ExecutionTime t = 0.) : base_pair(val, t) {} // Execution time in seconds (returns a double) ExecutionTime time_in_s() const { return base_pair::second; } // Execution time as a std::chrono::duration std::chrono::duration> duration_in_s() const { return std::chrono::duration>(time_in_s()); } // Inner value const T& get() const { return base_pair::first; } T& get() { return base_pair::first; } }; // API search type: show_timed : Timed a -> String // fwd bind count: 0 // show_timed((42,1)) -> "42 (1000ms)" template std::string show_timed(const fplus::timed& v) { std::string result = fplus::show(v.get()) + " (" + fplus::show(v.time_in_s() * 1000.) + "ms)"; return result; } namespace internal { template class timed_function_impl { public: explicit timed_function_impl(Fn fn) : _fn(fn) {}; template auto operator()(Args... args) { return _timed_result(args...); } private: template auto _timed_result(Args... args) { fplus::stopwatch timer; auto r = _fn(args...); auto r_t = fplus::timed(r, timer.elapsed()); return r_t; } Fn _fn; }; } // API search type: make_timed_function : ((a -> b)) -> (a -> Timed b) // fwd bind count: 0 // Transforms a function into a timed / benchmarked version of the same function. // - // Example: // - // using Ints = std::vector; // Ints ascending_numbers = fplus::numbers(0, 1000); // Ints shuffled_numbers = fplus::shuffle(std::mt19937::default_seed, ascending_numbers); // auto sort_func = [](const Ints& values) { return fplus::sort(values); }; // auto sort_bench = fplus::make_timed_function(sort_func); // auto sorted_numbers = sort_bench(shuffled_numbers); // assert(sorted_numbers.get() == ascending_numbers); // sorted_numbers.get() <=> actual output // assert(sorted_numbers.time_in_s() < 0.1); // // sorted_numbers.time_in_s() <=> execution time template auto make_timed_function(Fn f) { return internal::timed_function_impl(f); } namespace internal { template class timed_void_function_impl { public: explicit timed_void_function_impl(Fn fn) : _fn(fn) {}; template auto operator()(Args... args) { return _timed_result(args...); } private: template auto _timed_result(Args... args) { fplus::stopwatch timer; _fn(args...); return timer.elapsed(); } Fn _fn; }; } // API search type: make_timed_void_function : ((a -> Void)) -> (a -> Double) // fwd bind count: 0 // Transforms a void function into a timed / benchmarked version of the same function. // - // Example: // - // void foo() { std::this_thread::sleep_for(std::chrono::milliseconds(1000)); } // ... // auto foo_bench = make_timed_void_function(foo); // auto r = foo_bench(); // double run_time = foo_bench(); // in seconds template auto make_timed_void_function(Fn f) { return internal::timed_void_function_impl(f); } }