| 188 | // Run `n_trials` of `reps` repetitions of `fn`, return mean and stddev of ns/iter. |
| 189 | template <typename F> |
| 190 | TrialStats bench(F&& fn, std::size_t reps, std::size_t n_trials) { |
| 191 | std::vector<double> ns_per_iter; |
| 192 | ns_per_iter.reserve(n_trials); |
| 193 | volatile double sink = 0.0; |
| 194 | for (std::size_t t = 0; t < n_trials; ++t) { |
| 195 | const auto t0 = std::chrono::steady_clock::now(); |
| 196 | for (std::size_t r = 0; r < reps; ++r) { |
| 197 | sink = sink + fn(); |
| 198 | } |
| 199 | const auto t1 = std::chrono::steady_clock::now(); |
| 200 | const double dt_ns = std::chrono::duration<double, std::nano>(t1 - t0).count(); |
| 201 | ns_per_iter.push_back(dt_ns / static_cast<double>(reps)); |
| 202 | } |
| 203 | (void)sink; |
| 204 | double sum = 0.0; |
| 205 | for (double x : ns_per_iter) |
| 206 | sum += x; |
| 207 | const double mean = sum / static_cast<double>(n_trials); |
| 208 | double sq = 0.0; |
| 209 | for (double x : ns_per_iter) |
| 210 | sq += (x - mean) * (x - mean); |
| 211 | const double stddev = (n_trials > 1) ? std::sqrt(sq / static_cast<double>(n_trials - 1)) : 0.0; |
| 212 | return TrialStats{mean, stddev}; |
| 213 | } |
| 214 | |
| 215 | // Pick a representative single-phase (T, p) state for each benchmark fluid, run the |
| 216 | // AbstractState through update so tau/delta are well-defined, then return log(tau) |
no outgoing calls
no test coverage detected