Read-only mirrors. Development, issues and pull requests are on GitHub.

summaryrefslogtreecommitdiffhomepage
path: root/extras/catch_amalgamated.hpp
diff options
context:
space:
mode:
authorMartin Hořeňovský2023-12-11 00:55:40 +0100
committerMartin Hořeňovský2023-12-11 00:55:40 +0100
commit53d0d913a422d356b23dd927547febdf69ee9081 (patch)
treeb2b624bde9ead96c0e448c8d6ba7dcba6e5ebb40 /extras/catch_amalgamated.hpp
parent1648c30ec3ac1aedd1417d31de18801767ab0d72 (diff)
downloadcatch3-3.5.0.tar.gz
v3.5.0v3.5.0
Diffstat (limited to 'extras/catch_amalgamated.hpp')
-rw-r--r--extras/catch_amalgamated.hpp1231
1 files changed, 918 insertions, 313 deletions
diff --git a/extras/catch_amalgamated.hpp b/extras/catch_amalgamated.hpp
index 694fe1e4..bec588d4 100644
--- a/extras/catch_amalgamated.hpp
+++ b/extras/catch_amalgamated.hpp
@@ -1,3 +1,4 @@
+
// Copyright Catch2 Authors
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.txt or copy at
@@ -5,8 +6,8 @@
// SPDX-License-Identifier: BSL-1.0
-// Catch v3.4.0
-// Generated: 2023-07-13 13:23:07.577770
+// Catch v3.5.0
+// Generated: 2023-12-11 00:51:06.770598
// ----------------------------------------------------------
// This file is an amalgamation of multiple different files.
// You probably shouldn't edit it directly.
@@ -240,7 +241,9 @@
////////////////////////////////////////////////////////////////////////////////
// Assume that some platforms do not support getenv.
-#if defined(CATCH_PLATFORM_WINDOWS_UWP) || defined(CATCH_PLATFORM_PLAYSTATION)
+#if defined( CATCH_PLATFORM_WINDOWS_UWP ) || \
+ defined( CATCH_PLATFORM_PLAYSTATION ) || \
+ defined( _GAMING_XBOX )
# define CATCH_INTERNAL_CONFIG_NO_GETENV
#else
# define CATCH_INTERNAL_CONFIG_GETENV
@@ -950,14 +953,35 @@ namespace Detail {
#ifndef CATCH_BENCHMARK_STATS_FWD_HPP_INCLUDED
#define CATCH_BENCHMARK_STATS_FWD_HPP_INCLUDED
+
+
+// Adapted from donated nonius code.
+
+#ifndef CATCH_CLOCK_HPP_INCLUDED
+#define CATCH_CLOCK_HPP_INCLUDED
+
#include <chrono>
namespace Catch {
+ namespace Benchmark {
+ using IDuration = std::chrono::nanoseconds;
+ using FDuration = std::chrono::duration<double, std::nano>;
+
+ template <typename Clock>
+ using TimePoint = typename Clock::time_point;
+
+ using default_clock = std::chrono::steady_clock;
+ } // namespace Benchmark
+} // namespace Catch
+
+#endif // CATCH_CLOCK_HPP_INCLUDED
+
+namespace Catch {
// We cannot forward declare the type with default template argument
// multiple times, so it is split out into a separate header so that
// we can prevent multiple declarations in dependees
- template <typename Duration = std::chrono::duration<double, std::nano>>
+ template <typename Duration = Benchmark::FDuration>
struct BenchmarkStats;
} // end namespace Catch
@@ -1246,17 +1270,12 @@ namespace Catch {
namespace Catch {
namespace Benchmark {
- template <typename Duration>
+ template <typename Type>
struct Estimate {
- Duration point;
- Duration lower_bound;
- Duration upper_bound;
+ Type point;
+ Type lower_bound;
+ Type upper_bound;
double confidence_interval;
-
- template <typename Duration2>
- operator Estimate<Duration2>() const {
- return { point, lower_bound, upper_bound, confidence_interval };
- }
};
} // namespace Benchmark
} // namespace Catch
@@ -1304,32 +1323,17 @@ namespace Catch {
double clockCost;
};
- template <class Duration>
+ // We need to keep template parameter for backwards compatibility,
+ // but we also do not want to use the template paraneter.
+ template <class Dummy>
struct BenchmarkStats {
BenchmarkInfo info;
- std::vector<Duration> samples;
- Benchmark::Estimate<Duration> mean;
- Benchmark::Estimate<Duration> standardDeviation;
+ std::vector<Benchmark::FDuration> samples;
+ Benchmark::Estimate<Benchmark::FDuration> mean;
+ Benchmark::Estimate<Benchmark::FDuration> standardDeviation;
Benchmark::OutlierClassification outliers;
double outlierVariance;
-
- template <typename Duration2>
- operator BenchmarkStats<Duration2>() const {
- std::vector<Duration2> samples2;
- samples2.reserve(samples.size());
- for (auto const& sample : samples) {
- samples2.push_back(Duration2(sample));
- }
- return {
- info,
- CATCH_MOVE(samples2),
- mean,
- standardDeviation,
- outliers,
- outlierVariance,
- };
- }
};
@@ -1340,61 +1344,19 @@ namespace Catch {
// Adapted from donated nonius code.
-#ifndef CATCH_CLOCK_HPP_INCLUDED
-#define CATCH_CLOCK_HPP_INCLUDED
-
-#include <chrono>
-#include <ratio>
-
-namespace Catch {
- namespace Benchmark {
- template <typename Clock>
- using ClockDuration = typename Clock::duration;
- template <typename Clock>
- using FloatDuration = std::chrono::duration<double, typename Clock::period>;
-
- template <typename Clock>
- using TimePoint = typename Clock::time_point;
-
- using default_clock = std::chrono::steady_clock;
-
- template <typename Clock>
- struct now {
- TimePoint<Clock> operator()() const {
- return Clock::now();
- }
- };
-
- using fp_seconds = std::chrono::duration<double, std::ratio<1>>;
- } // namespace Benchmark
-} // namespace Catch
-
-#endif // CATCH_CLOCK_HPP_INCLUDED
-
-
-// Adapted from donated nonius code.
-
#ifndef CATCH_ENVIRONMENT_HPP_INCLUDED
#define CATCH_ENVIRONMENT_HPP_INCLUDED
namespace Catch {
namespace Benchmark {
- template <typename Duration>
struct EnvironmentEstimate {
- Duration mean;
+ FDuration mean;
OutlierClassification outliers;
-
- template <typename Duration2>
- operator EnvironmentEstimate<Duration2>() const {
- return { mean, outliers };
- }
};
- template <typename Clock>
struct Environment {
- using clock_type = Clock;
- EnvironmentEstimate<FloatDuration<Clock>> clock_resolution;
- EnvironmentEstimate<FloatDuration<Clock>> clock_cost;
+ EnvironmentEstimate clock_resolution;
+ EnvironmentEstimate clock_cost;
};
} // namespace Benchmark
} // namespace Catch
@@ -1487,7 +1449,7 @@ namespace Catch {
template <typename Fn, typename... Args>
inline auto invoke_deoptimized(Fn&& fn, Args&&... args) -> std::enable_if_t<std::is_same<void, decltype(fn(args...))>::value> {
- CATCH_FORWARD(fn) (CATCH_FORWARD(args)...);
+ CATCH_FORWARD((fn)) (CATCH_FORWARD(args)...);
}
} // namespace Benchmark
} // namespace Catch
@@ -1553,7 +1515,10 @@ namespace Catch {
void start() override { started = Clock::now(); }
void finish() override { finished = Clock::now(); }
- ClockDuration<Clock> elapsed() const { return finished - started; }
+ IDuration elapsed() const {
+ return std::chrono::duration_cast<std::chrono::nanoseconds>(
+ finished - started );
+ }
TimePoint<Clock> started;
TimePoint<Clock> finished;
@@ -1791,14 +1756,14 @@ namespace Catch {
namespace Catch {
namespace Benchmark {
- template <typename Duration, typename Result>
+ template <typename Result>
struct Timing {
- Duration elapsed;
+ IDuration elapsed;
Result result;
int iterations;
};
- template <typename Clock, typename Func, typename... Args>
- using TimingOf = Timing<ClockDuration<Clock>, Detail::CompleteType_t<FunctionReturnType<Func, Args...>>>;
+ template <typename Func, typename... Args>
+ using TimingOf = Timing<Detail::CompleteType_t<FunctionReturnType<Func, Args...>>>;
} // namespace Benchmark
} // namespace Catch
@@ -1808,7 +1773,7 @@ namespace Catch {
namespace Benchmark {
namespace Detail {
template <typename Clock, typename Fun, typename... Args>
- TimingOf<Clock, Fun, Args...> measure(Fun&& fun, Args&&... args) {
+ TimingOf<Fun, Args...> measure(Fun&& fun, Args&&... args) {
auto start = Clock::now();
auto&& r = Detail::complete_invoke(fun, CATCH_FORWARD(args)...);
auto end = Clock::now();
@@ -1827,11 +1792,11 @@ namespace Catch {
namespace Benchmark {
namespace Detail {
template <typename Clock, typename Fun>
- TimingOf<Clock, Fun, int> measure_one(Fun&& fun, int iters, std::false_type) {
+ TimingOf<Fun, int> measure_one(Fun&& fun, int iters, std::false_type) {
return Detail::measure<Clock>(fun, iters);
}
template <typename Clock, typename Fun>
- TimingOf<Clock, Fun, Chronometer> measure_one(Fun&& fun, int iters, std::true_type) {
+ TimingOf<Fun, Chronometer> measure_one(Fun&& fun, int iters, std::true_type) {
Detail::ChronometerModel<Clock> meter;
auto&& result = Detail::complete_invoke(fun, Chronometer(meter, iters));
@@ -1846,8 +1811,8 @@ namespace Catch {
void throw_optimized_away_error();
template <typename Clock, typename Fun>
- TimingOf<Clock, Fun, run_for_at_least_argument_t<Clock, Fun>>
- run_for_at_least(ClockDuration<Clock> how_long,
+ TimingOf<Fun, run_for_at_least_argument_t<Clock, Fun>>
+ run_for_at_least(IDuration how_long,
const int initial_iterations,
Fun&& fun) {
auto iters = initial_iterations;
@@ -1871,33 +1836,31 @@ namespace Catch {
namespace Catch {
namespace Benchmark {
- template <typename Duration>
struct ExecutionPlan {
int iterations_per_sample;
- Duration estimated_duration;
+ FDuration estimated_duration;
Detail::BenchmarkFunction benchmark;
- Duration warmup_time;
+ FDuration warmup_time;
int warmup_iterations;
- template <typename Duration2>
- operator ExecutionPlan<Duration2>() const {
- return { iterations_per_sample, estimated_duration, benchmark, warmup_time, warmup_iterations };
- }
-
template <typename Clock>
- std::vector<FloatDuration<Clock>> run(const IConfig &cfg, Environment<FloatDuration<Clock>> env) const {
+ std::vector<FDuration> run(const IConfig &cfg, Environment env) const {
// warmup a bit
- Detail::run_for_at_least<Clock>(std::chrono::duration_cast<ClockDuration<Clock>>(warmup_time), warmup_iterations, Detail::repeat(now<Clock>{}));
+ Detail::run_for_at_least<Clock>(
+ std::chrono::duration_cast<IDuration>( warmup_time ),
+ warmup_iterations,
+ Detail::repeat( []() { return Clock::now(); } )
+ );
- std::vector<FloatDuration<Clock>> times;
+ std::vector<FDuration> times;
const auto num_samples = cfg.benchmarkSamples();
times.reserve( num_samples );
for ( size_t i = 0; i < num_samples; ++i ) {
Detail::ChronometerModel<Clock> model;
this->benchmark( Chronometer( model, iterations_per_sample ) );
auto sample_time = model.elapsed() - env.clock_cost.mean;
- if ( sample_time < FloatDuration<Clock>::zero() ) {
- sample_time = FloatDuration<Clock>::zero();
+ if ( sample_time < FDuration::zero() ) {
+ sample_time = FDuration::zero();
}
times.push_back(sample_time / iterations_per_sample);
}
@@ -1923,100 +1886,35 @@ namespace Catch {
#define CATCH_STATS_HPP_INCLUDED
-#include <algorithm>
#include <vector>
-#include <cmath>
namespace Catch {
namespace Benchmark {
namespace Detail {
using sample = std::vector<double>;
- // Used when we know we want == comparison of two doubles
- // to centralize warning suppression
- bool directCompare( double lhs, double rhs );
-
- double weighted_average_quantile(int k, int q, std::vector<double>::iterator first, std::vector<double>::iterator last);
+ double weighted_average_quantile( int k,
+ int q,
+ double* first,
+ double* last );
OutlierClassification
- classify_outliers( std::vector<double>::const_iterator first,
- std::vector<double>::const_iterator last );
-
- double mean( std::vector<double>::const_iterator first,
- std::vector<double>::const_iterator last );
-
- template <typename Estimator>
- sample jackknife(Estimator&& estimator,
- std::vector<double>::iterator first,
- std::vector<double>::iterator last) {
- auto n = static_cast<size_t>(last - first);
- auto second = first;
- ++second;
- sample results;
- results.reserve(n);
-
- for (auto it = first; it != last; ++it) {
- std::iter_swap(it, first);
- results.push_back(estimator(second, last));
- }
+ classify_outliers( double const* first, double const* last );
- return results;
- }
+ double mean( double const* first, double const* last );
- inline double normal_cdf(double x) {
- return std::erfc(-x / std::sqrt(2.0)) / 2.0;
- }
+ double normal_cdf( double x );
double erfc_inv(double x);
double normal_quantile(double p);
- template <typename Estimator>
- Estimate<double> bootstrap( double confidence_level,
- std::vector<double>::iterator first,
- std::vector<double>::iterator last,
- sample const& resample,
- Estimator&& estimator ) {
- auto n_samples = last - first;
-
- double point = estimator(first, last);
- // Degenerate case with a single sample
- if (n_samples == 1) return { point, point, point, confidence_level };
-
- sample jack = jackknife(estimator, first, last);
- double jack_mean = mean(jack.begin(), jack.end());
- double sum_squares = 0, sum_cubes = 0;
- for (double x : jack) {
- auto difference = jack_mean - x;
- auto square = difference * difference;
- auto cube = square * difference;
- sum_squares += square; sum_cubes += cube;
- }
-
- double accel = sum_cubes / (6 * std::pow(sum_squares, 1.5));
- long n = static_cast<long>(resample.size());
- double prob_n = std::count_if(resample.begin(), resample.end(), [point](double x) { return x < point; }) / static_cast<double>(n);
- // degenerate case with uniform samples
- if ( directCompare( prob_n, 0. ) ) {
- return { point, point, point, confidence_level };
- }
-
- double bias = normal_quantile(prob_n);
- double z1 = normal_quantile((1. - confidence_level) / 2.);
-
- auto cumn = [n]( double x ) -> long {
- return std::lround( normal_cdf( x ) * static_cast<double>(n) );
- };
- auto a = [bias, accel](double b) { return bias + b / (1. - accel * b); };
- double b1 = bias + z1;
- double b2 = bias - z1;
- double a1 = a(b1);
- double a2 = a(b2);
- auto lo = static_cast<size_t>((std::max)(cumn(a1), 0l));
- auto hi = static_cast<size_t>((std::min)(cumn(a2), n - 1));
-
- return { point, resample[lo], resample[hi], confidence_level };
- }
+ Estimate<double>
+ bootstrap( double confidence_level,
+ double* first,
+ double* last,
+ sample const& resample,
+ double ( *estimator )( double const*, double const* ) );
struct bootstrap_analysis {
Estimate<double> mean;
@@ -2026,8 +1924,8 @@ namespace Catch {
bootstrap_analysis analyse_samples(double confidence_level,
unsigned int n_resamples,
- std::vector<double>::iterator first,
- std::vector<double>::iterator last);
+ double* first,
+ double* last);
} // namespace Detail
} // namespace Benchmark
} // namespace Catch
@@ -2071,23 +1969,23 @@ namespace Catch {
template <typename Clock>
int warmup() {
- return run_for_at_least<Clock>(std::chrono::duration_cast<ClockDuration<Clock>>(warmup_time), warmup_seed, &resolution<Clock>)
+ return run_for_at_least<Clock>(std::chrono::duration_cast<IDuration>(warmup_time), warmup_seed, &resolution<Clock>)
.iterations;
}
template <typename Clock>
- EnvironmentEstimate<FloatDuration<Clock>> estimate_clock_resolution(int iterations) {
- auto r = run_for_at_least<Clock>(std::chrono::duration_cast<ClockDuration<Clock>>(clock_resolution_estimation_time), iterations, &resolution<Clock>)
+ EnvironmentEstimate estimate_clock_resolution(int iterations) {
+ auto r = run_for_at_least<Clock>(std::chrono::duration_cast<IDuration>(clock_resolution_estimation_time), iterations, &resolution<Clock>)
.result;
return {
- FloatDuration<Clock>(mean(r.begin(), r.end())),
- classify_outliers(r.begin(), r.end()),
+ FDuration(mean(r.data(), r.data() + r.size())),
+ classify_outliers(r.data(), r.data() + r.size()),
};
}
template <typename Clock>
- EnvironmentEstimate<FloatDuration<Clock>> estimate_clock_cost(FloatDuration<Clock> resolution) {
+ EnvironmentEstimate estimate_clock_cost(FDuration resolution) {
auto time_limit = (std::min)(
resolution * clock_cost_estimation_tick_limit,
- FloatDuration<Clock>(clock_cost_estimation_time_limit));
+ FDuration(clock_cost_estimation_time_limit));
auto time_clock = [](int k) {
return Detail::measure<Clock>([k] {
for (int i = 0; i < k; ++i) {
@@ -2098,7 +1996,7 @@ namespace Catch {
};
time_clock(1);
int iters = clock_cost_estimation_iterations;
- auto&& r = run_for_at_least<Clock>(std::chrono::duration_cast<ClockDuration<Clock>>(clock_cost_estimation_time), iters, time_clock);
+ auto&& r = run_for_at_least<Clock>(std::chrono::duration_cast<IDuration>(clock_cost_estimation_time), iters, time_clock);
std::vector<double> times;
int nsamples = static_cast<int>(std::ceil(time_limit / r.elapsed));
times.reserve(static_cast<size_t>(nsamples));
@@ -2108,18 +2006,18 @@ namespace Catch {
.count() ) );
}
return {
- FloatDuration<Clock>(mean(times.begin(), times.end())),
- classify_outliers(times.begin(), times.end()),
+ FDuration(mean(times.data(), times.data() + times.size())),
+ classify_outliers(times.data(), times.data() + times.size()),
};
}
template <typename Clock>
- Environment<FloatDuration<Clock>> measure_environment() {
+ Environment measure_environment() {
#if defined(__clang__)
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wexit-time-destructors"
#endif
- static Catch::Detail::unique_ptr<Environment<FloatDuration<Clock>>> env;
+ static Catch::Detail::unique_ptr<Environment> env;
#if defined(__clang__)
# pragma clang diagnostic pop
#endif
@@ -2131,7 +2029,7 @@ namespace Catch {
auto resolution = Detail::estimate_clock_resolution<Clock>(iters);
auto cost = Detail::estimate_clock_cost<Clock>(resolution.mean);
- env = Catch::Detail::make_unique<Environment<FloatDuration<Clock>>>( Environment<FloatDuration<Clock>>{resolution, cost} );
+ env = Catch::Detail::make_unique<Environment>( Environment{resolution, cost} );
return *env;
}
} // namespace Detail
@@ -2158,94 +2056,25 @@ namespace Catch {
namespace Catch {
namespace Benchmark {
- template <typename Duration>
struct SampleAnalysis {
- std::vector<Duration> samples;
- Estimate<Duration> mean;
- Estimate<Duration> standard_deviation;
+ std::vector<FDuration> samples;
+ Estimate<FDuration> mean;
+ Estimate<FDuration> standard_deviation;
OutlierClassification outliers;
double outlier_variance;
-
- template <typename Duration2>
- operator SampleAnalysis<Duration2>() const {
- std::vector<Duration2> samples2;
- samples2.reserve(samples.size());
- for (auto const& d : samples) {
- samples2.push_back(Duration2(d));
- }
- return {
- CATCH_MOVE(samples2),
- mean,
- standard_deviation,
- outliers,
- outlier_variance,
- };
- }
};
} // namespace Benchmark
} // namespace Catch
#endif // CATCH_SAMPLE_ANALYSIS_HPP_INCLUDED
-#include <vector>
namespace Catch {
+ class IConfig;
+
namespace Benchmark {
namespace Detail {
- template <typename Duration, typename Iterator>
- SampleAnalysis<Duration> analyse(const IConfig &cfg, Environment<Duration>, Iterator first, Iterator last) {
- if (!cfg.benchmarkNoAnalysis()) {
- std::vector<double> samples;
- samples.reserve(static_cast<size_t>(last - first));
- for (auto current = first; current != last; ++current) {
- samples.push_back( current->count() );
- }
-
- auto analysis = Catch::Benchmark::Detail::analyse_samples(cfg.benchmarkConfidenceInterval(), cfg.benchmarkResamples(), samples.begin(), samples.end());
- auto outliers = Catch::Benchmark::Detail::classify_outliers(samples.begin(), samples.end());
-
- auto wrap_estimate = [](Estimate<double> e) {
- return Estimate<Duration> {
- Duration(e.point),
- Duration(e.lower_bound),
- Duration(e.upper_bound),
- e.confidence_interval,
- };
- };
- std::vector<Duration> samples2;
- samples2.reserve(samples.size());
- for (auto s : samples) {
- samples2.push_back( Duration( s ) );
- }
-
- return {
- CATCH_MOVE(samples2),
- wrap_estimate(analysis.mean),
- wrap_estimate(analysis.standard_deviation),
- outliers,
- analysis.outlier_variance,
- };
- } else {
- std::vector<Duration> samples;
- samples.reserve(static_cast<size_t>(last - first));
-
- Duration mean = Duration(0);
- int i = 0;
- for (auto it = first; it < last; ++it, ++i) {
- samples.push_back(Duration(*it));
- mean += Duration(*it);
- }
- mean /= i;
-
- return {
- CATCH_MOVE(samples),
- Estimate<Duration>{mean, mean, mean, 0.0},
- Estimate<Duration>{Duration(0), Duration(0), Duration(0), 0.0},
- OutlierClassification{},
- 0.0
- };
- }
- }
+ SampleAnalysis analyse(const IConfig &cfg, FDuration* first, FDuration* last);
} // namespace Detail
} // namespace Benchmark
} // namespace Catch
@@ -2255,9 +2084,7 @@ namespace Catch {
#include <algorithm>
#include <chrono>
#include <exception>
-#include <functional>
#include <string>
-#include <vector>
#include <cmath>
namespace Catch {
@@ -2271,16 +2098,18 @@ namespace Catch {
: fun(CATCH_MOVE(func)), name(CATCH_MOVE(benchmarkName)) {}
template <typename Clock>
- ExecutionPlan<FloatDuration<Clock>> prepare(const IConfig &cfg, Environment<FloatDuration<Clock>> env) const {
+ ExecutionPlan prepare(const IConfig &cfg, Environment env) const {
auto min_time = env.clock_resolution.mean * Detail::minimum_ticks;
auto run_time = std::max(min_time, std::chrono::duration_cast<decltype(min_time)>(cfg.benchmarkWarmupTime()));
- auto&& test = Detail::run_for_at_least<Clock>(std::chrono::duration_cast<ClockDuration<Clock>>(run_time), 1, fun);
+ auto&& test = Detail::run_for_at_least<Clock>(std::chrono::duration_cast<IDuration>(run_time), 1, fun);
int new_iters = static_cast<int>(std::ceil(min_time * test.iterations / test.elapsed));
- return { new_iters, test.elapsed / test.iterations * new_iters * cfg.benchmarkSamples(), fun, std::chrono::duration_cast<FloatDuration<Clock>>(cfg.benchmarkWarmupTime()), Detail::warmup_iterations };
+ return { new_iters, test.elapsed / test.iterations * new_iters * cfg.benchmarkSamples(), fun, std::chrono::duration_cast<FDuration>(cfg.benchmarkWarmupTime()), Detail::warmup_iterations };
}
template <typename Clock = default_clock>
void run() {
+ static_assert( Clock::is_steady,
+ "Benchmarking clock should be steady" );
auto const* cfg = getCurrentContext().getConfig();
auto env = Detail::measure_environment<Clock>();
@@ -2307,8 +2136,8 @@ namespace Catch {
return plan.template run<Clock>(*cfg, env);
});
- auto analysis = Detail::analyse(*cfg, env, samples.begin(), samples.end());
- BenchmarkStats<FloatDuration<Clock>> stats{ CATCH_MOVE(info), CATCH_MOVE(analysis.samples), analysis.mean, analysis.standard_deviation, analysis.outliers, analysis.outlier_variance };
+ auto analysis = Detail::analyse(*cfg, samples.data(), samples.data() + samples.size());
+ BenchmarkStats<> stats{ CATCH_MOVE(info), CATCH_MOVE(analysis.samples), analysis.mean, analysis.standard_deviation, analysis.outliers, analysis.outlier_variance };
getResultCapture().benchmarkEnded(stats);
} CATCH_CATCH_ANON (TestFailureException const&) {
getResultCapture().benchmarkFailed("Benchmark failed due to failed assertion"_sr);
@@ -2984,6 +2813,12 @@ namespace Catch {
}
}
};
+ template <>
+ struct StringMaker<std::nullopt_t> {
+ static std::string convert(const std::nullopt_t&) {
+ return "{ }";
+ }
+ };
}
#endif // CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER
@@ -4166,6 +4001,29 @@ namespace Catch {
+
+/** \file
+ * Wrapper for the CATCH_CONFIG_PREFIX_MESSAGES configuration option
+ *
+ * CATCH_CONFIG_PREFIX_ALL can be used to avoid clashes with other macros
+ * by prepending CATCH_. This may not be desirable if the only clashes are with
+ * logger macros such as INFO and WARN. In this cases
+ * CATCH_CONFIG_PREFIX_MESSAGES can be used to only prefix a small subset
+ * of relevant macros.
+ *
+ */
+
+#ifndef CATCH_CONFIG_PREFIX_MESSAGES_HPP_INCLUDED
+#define CATCH_CONFIG_PREFIX_MESSAGES_HPP_INCLUDED
+
+
+#if defined(CATCH_CONFIG_PREFIX_ALL) && !defined(CATCH_CONFIG_PREFIX_MESSAGES)
+ #define CATCH_CONFIG_PREFIX_MESSAGES
+#endif
+
+#endif // CATCH_CONFIG_PREFIX_MESSAGES_HPP_INCLUDED
+
+
#ifndef CATCH_STREAM_END_STOP_HPP_INCLUDED
#define CATCH_STREAM_END_STOP_HPP_INCLUDED
@@ -4321,28 +4179,28 @@ namespace Catch {
Catch::getResultCapture().emplaceUnscopedMessage( Catch::MessageBuilder( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log )
-#if defined(CATCH_CONFIG_PREFIX_ALL) && !defined(CATCH_CONFIG_DISABLE)
+#if defined(CATCH_CONFIG_PREFIX_MESSAGES) && !defined(CATCH_CONFIG_DISABLE)
#define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( "CATCH_INFO", msg )
#define CATCH_UNSCOPED_INFO( msg ) INTERNAL_CATCH_UNSCOPED_INFO( "CATCH_UNSCOPED_INFO", msg )
#define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( "CATCH_WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg )
#define CATCH_CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "CATCH_CAPTURE", __VA_ARGS__ )
-#elif defined(CATCH_CONFIG_PREFIX_ALL) && defined(CATCH_CONFIG_DISABLE)
+#elif defined(CATCH_CONFIG_PREFIX_MESSAGES) && defined(CATCH_CONFIG_DISABLE)
#define CATCH_INFO( msg ) (void)(0)
#define CATCH_UNSCOPED_INFO( msg ) (void)(0)
#define CATCH_WARN( msg ) (void)(0)
#define CATCH_CAPTURE( ... ) (void)(0)
-#elif !defined(CATCH_CONFIG_PREFIX_ALL) && !defined(CATCH_CONFIG_DISABLE)
+#elif !defined(CATCH_CONFIG_PREFIX_MESSAGES) && !defined(CATCH_CONFIG_DISABLE)
#define INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg )
#define UNSCOPED_INFO( msg ) INTERNAL_CATCH_UNSCOPED_INFO( "UNSCOPED_INFO", msg )
#define WARN( msg ) INTERNAL_CATCH_MSG( "WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg )
#define CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "CAPTURE", __VA_ARGS__ )
-#elif !defined(CATCH_CONFIG_PREFIX_ALL) && defined(CATCH_CONFIG_DISABLE)
+#elif !defined(CATCH_CONFIG_PREFIX_MESSAGES) && defined(CATCH_CONFIG_DISABLE)
#define INFO( msg ) (void)(0)
#define UNSCOPED_INFO( msg ) (void)(0)
@@ -5784,7 +5642,7 @@ namespace Catch {
#else // CATCH_CONFIG_FAST_COMPILE
#define INTERNAL_CATCH_TRY try
-#define INTERNAL_CATCH_CATCH( handler ) catch(...) { handler.handleUnexpectedInflightException(); }
+#define INTERNAL_CATCH_CATCH( handler ) catch(...) { (handler).handleUnexpectedInflightException(); }
#endif
@@ -6023,7 +5881,7 @@ namespace Catch {
CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS \
- if ( [[maybe_unused]] int catchInternalPreviousSectionHint = \
+ if ( [[maybe_unused]] const int catchInternalPreviousSectionHint = \
catchInternalSectionHint, \
catchInternalSectionHint = Catch::Detail::GetNewSectionHint(); \
catchInternalPreviousSectionHint == __LINE__ ) \
@@ -6033,7 +5891,7 @@ namespace Catch {
CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS \
- if ( [[maybe_unused]] int catchInternalPreviousSectionHint = \
+ if ( [[maybe_unused]] const int catchInternalPreviousSectionHint = \
catchInternalSectionHint, \
catchInternalSectionHint = Catch::Detail::GetNewSectionHint(); \
catchInternalPreviousSectionHint == __LINE__ ) \
@@ -6175,7 +6033,7 @@ static int catchInternalSectionHint = 0;
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
static const Catch::Detail::DummyUse INTERNAL_CATCH_UNIQUE_NAME( \
- dummyUser )( &fname ); \
+ dummyUser )( &(fname) ); \
CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS \
static void fname( [[maybe_unused]] int catchInternalSectionHint ) \
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
@@ -7374,7 +7232,7 @@ namespace Catch {
#define CATCH_VERSION_MACROS_HPP_INCLUDED
#define CATCH_VERSION_MAJOR 3
-#define CATCH_VERSION_MINOR 4
+#define CATCH_VERSION_MINOR 5
#define CATCH_VERSION_PATCH 0
#endif // CATCH_VERSION_MACROS_HPP_INCLUDED
@@ -8037,7 +7895,550 @@ namespace Catch {
#endif // CATCH_RANDOM_NUMBER_GENERATOR_HPP_INCLUDED
-#include <random>
+
+
+#ifndef CATCH_UNIFORM_INTEGER_DISTRIBUTION_HPP_INCLUDED
+#define CATCH_UNIFORM_INTEGER_DISTRIBUTION_HPP_INCLUDED
+
+
+
+
+#ifndef CATCH_RANDOM_INTEGER_HELPERS_HPP_INCLUDED
+#define CATCH_RANDOM_INTEGER_HELPERS_HPP_INCLUDED
+
+#include <climits>
+#include <cstddef>
+#include <cstdint>
+#include <type_traits>
+
+namespace Catch {
+ namespace Detail {
+
+ template <std::size_t>
+ struct SizedUnsignedType;
+#define SizedUnsignedTypeHelper( TYPE ) \
+ template <> \
+ struct SizedUnsignedType<sizeof( TYPE )> { \
+ using type = TYPE; \
+ }
+
+ SizedUnsignedTypeHelper( std::uint8_t );
+ SizedUnsignedTypeHelper( std::uint16_t );
+ SizedUnsignedTypeHelper( std::uint32_t );
+ SizedUnsignedTypeHelper( std::uint64_t );
+#undef SizedUnsignedTypeHelper
+
+ template <std::size_t sz>
+ using SizedUnsignedType_t = typename SizedUnsignedType<sz>::type;
+
+ template <typename T>
+ using DoubleWidthUnsignedType_t = SizedUnsignedType_t<2 * sizeof( T )>;
+
+ template <typename T>
+ struct ExtendedMultResult {
+ T upper;
+ T lower;
+ friend bool operator==( ExtendedMultResult const& lhs,
+ ExtendedMultResult const& rhs ) {
+ return lhs.upper == rhs.upper && lhs.lower == rhs.lower;
+ }
+ };
+
+ // Returns 128 bit result of multiplying lhs and rhs
+ constexpr ExtendedMultResult<std::uint64_t>