/*
  Copyright (C) 2018 David Robillard <d@drobilla.net>

  This program is free software: you can redistribute it and/or modify it under
  the terms of the GNU General Public License as published by the Free Software
  Foundation, either version 2 of the License, or (at your option) any later
  version.

  This program is distributed in the hope that it will be useful, but WITHOUT
  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
  details.

  You should have received a copy of the GNU General Public License along with
  this program.  If not, see <https://www.gnu.org/licenses/>.
*/

#ifndef BENCH_UTILS_HPP
#define BENCH_UTILS_HPP

#include "test_utils.hpp"

#include <array>
#include <chrono>
#include <cstddef>
#include <iostream>

using Duration = std::chrono::duration<double, std::micro>;

/// Write a TSV row to `os` with `n` as the first column followed by `results`
template <class T, size_t M>
void
write_row(std::ostream& os, const size_t n, const std::array<T, M>& results)
{
	os << n;
	for (const auto t : results) {
		if (t == Duration::zero()) {
			os << "\tNaN";
		} else {
			os << '\t' << t.count();
		}
	}
	os << std::endl;
}

/// Repeatedly run an operation and return the average time
template <class Operation>
Duration
run_bench(const Operation& op)
{
	static constexpr auto bench_duration = std::chrono::milliseconds{10};

	const auto t_start = std::chrono::steady_clock{}.now();
	auto       t_now   = t_start;
	size_t     count   = 0;
	for (; t_now < t_start + bench_duration; ++count) {
		op(count);
		t_now = std::chrono::steady_clock{}.now();
	}

	return (t_now - t_start) / count;
}

#endif