mirror of
https://github.com/catchorg/Catch2.git
synced 2024-11-26 07:16:10 +01:00
Clean up iterator usage in benchmarks
Specifically we turned `mean`, `classify_outliers`, `jackknife`, into concrete functions that take only `const_iterator` from vecs, instead of generic iterators over anything. I also changed `resample` to take `const_iterator` instead of plain `iterator`, and similar for `standard_deviation`, and `analyse_samples`.
This commit is contained in:
parent
f3c678c0ab
commit
7d07efc92b
@ -26,7 +26,10 @@ namespace {
|
|||||||
using Catch::Benchmark::Detail::sample;
|
using Catch::Benchmark::Detail::sample;
|
||||||
|
|
||||||
template <typename URng, typename Estimator>
|
template <typename URng, typename Estimator>
|
||||||
sample resample(URng& rng, unsigned int resamples, std::vector<double>::iterator first, std::vector<double>::iterator last, Estimator& estimator) {
|
static sample resample(URng& rng, unsigned int resamples,
|
||||||
|
std::vector<double>::const_iterator first,
|
||||||
|
std::vector<double>::const_iterator last,
|
||||||
|
Estimator& estimator) {
|
||||||
auto n = static_cast<size_t>(last - first);
|
auto n = static_cast<size_t>(last - first);
|
||||||
std::uniform_int_distribution<decltype(n)> dist(0, n - 1);
|
std::uniform_int_distribution<decltype(n)> dist(0, n - 1);
|
||||||
|
|
||||||
@ -118,7 +121,8 @@ using Catch::Benchmark::Detail::sample;
|
|||||||
return p * x;
|
return p * x;
|
||||||
}
|
}
|
||||||
|
|
||||||
double standard_deviation(std::vector<double>::iterator first, std::vector<double>::iterator last) {
|
double standard_deviation(std::vector<double>::const_iterator first,
|
||||||
|
std::vector<double>::const_iterator last) {
|
||||||
auto m = Catch::Benchmark::Detail::mean(first, last);
|
auto m = Catch::Benchmark::Detail::mean(first, last);
|
||||||
double variance = std::accumulate( first,
|
double variance = std::accumulate( first,
|
||||||
last,
|
last,
|
||||||
@ -161,6 +165,47 @@ namespace Catch {
|
|||||||
return xj + g * (xj1 - xj);
|
return xj + g * (xj1 - xj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OutlierClassification
|
||||||
|
classify_outliers( std::vector<double>::const_iterator first,
|
||||||
|
std::vector<double>::const_iterator last ) {
|
||||||
|
std::vector<double> copy( first, last );
|
||||||
|
|
||||||
|
auto q1 = weighted_average_quantile( 1, 4, copy.begin(), copy.end() );
|
||||||
|
auto q3 = weighted_average_quantile( 3, 4, copy.begin(), copy.end() );
|
||||||
|
auto iqr = q3 - q1;
|
||||||
|
auto los = q1 - ( iqr * 3. );
|
||||||
|
auto lom = q1 - ( iqr * 1.5 );
|
||||||
|
auto him = q3 + ( iqr * 1.5 );
|
||||||
|
auto his = q3 + ( iqr * 3. );
|
||||||
|
|
||||||
|
OutlierClassification o;
|
||||||
|
for ( ; first != last; ++first ) {
|
||||||
|
const double t = *first;
|
||||||
|
if ( t < los ) {
|
||||||
|
++o.low_severe;
|
||||||
|
} else if ( t < lom ) {
|
||||||
|
++o.low_mild;
|
||||||
|
} else if ( t > his ) {
|
||||||
|
++o.high_severe;
|
||||||
|
} else if ( t > him ) {
|
||||||
|
++o.high_mild;
|
||||||
|
}
|
||||||
|
++o.samples_seen;
|
||||||
|
}
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
|
||||||
|
double mean( std::vector<double>::const_iterator first,
|
||||||
|
std::vector<double>::const_iterator last ) {
|
||||||
|
auto count = last - first;
|
||||||
|
double sum = 0.;
|
||||||
|
while (first != last) {
|
||||||
|
sum += *first;
|
||||||
|
++first;
|
||||||
|
}
|
||||||
|
return sum / static_cast<double>(count);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
double erfc_inv(double x) {
|
double erfc_inv(double x) {
|
||||||
return erf_inv(1.0 - x);
|
return erf_inv(1.0 - x);
|
||||||
@ -210,7 +255,10 @@ namespace Catch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bootstrap_analysis analyse_samples(double confidence_level, unsigned int n_resamples, std::vector<double>::iterator first, std::vector<double>::iterator last) {
|
bootstrap_analysis analyse_samples(double confidence_level,
|
||||||
|
unsigned int n_resamples,
|
||||||
|
std::vector<double>::iterator first,
|
||||||
|
std::vector<double>::iterator last) {
|
||||||
CATCH_INTERNAL_START_WARNINGS_SUPPRESSION
|
CATCH_INTERNAL_START_WARNINGS_SUPPRESSION
|
||||||
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS
|
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS
|
||||||
static std::random_device entropy;
|
static std::random_device entropy;
|
||||||
@ -218,11 +266,12 @@ namespace Catch {
|
|||||||
|
|
||||||
auto n = static_cast<int>(last - first); // seriously, one can't use integral types without hell in C++
|
auto n = static_cast<int>(last - first); // seriously, one can't use integral types without hell in C++
|
||||||
|
|
||||||
auto mean = &Detail::mean<std::vector<double>::iterator>;
|
auto mean = &Detail::mean;
|
||||||
auto stddev = &standard_deviation;
|
auto stddev = &standard_deviation;
|
||||||
|
|
||||||
#if defined(CATCH_CONFIG_USE_ASYNC)
|
#if defined(CATCH_CONFIG_USE_ASYNC)
|
||||||
auto Estimate = [=](double(*f)(std::vector<double>::iterator, std::vector<double>::iterator)) {
|
auto Estimate = [=](double(*f)(std::vector<double>::const_iterator,
|
||||||
|
std::vector<double>::const_iterator)) {
|
||||||
auto seed = entropy();
|
auto seed = entropy();
|
||||||
return std::async(std::launch::async, [=] {
|
return std::async(std::launch::async, [=] {
|
||||||
std::mt19937 rng(seed);
|
std::mt19937 rng(seed);
|
||||||
@ -237,7 +286,8 @@ namespace Catch {
|
|||||||
auto mean_estimate = mean_future.get();
|
auto mean_estimate = mean_future.get();
|
||||||
auto stddev_estimate = stddev_future.get();
|
auto stddev_estimate = stddev_future.get();
|
||||||
#else
|
#else
|
||||||
auto Estimate = [=](double(*f)(std::vector<double>::iterator, std::vector<double>::iterator)) {
|
auto Estimate = [=](double(*f)(std::vector<double>::const_iterator,
|
||||||
|
std::vector<double>::const_iterator)) {
|
||||||
auto seed = entropy();
|
auto seed = entropy();
|
||||||
std::mt19937 rng(seed);
|
std::mt19937 rng(seed);
|
||||||
auto resampled = resample(rng, n_resamples, first, last, f);
|
auto resampled = resample(rng, n_resamples, first, last, f);
|
||||||
|
@ -30,39 +30,17 @@ namespace Catch {
|
|||||||
|
|
||||||
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, std::vector<double>::iterator first, std::vector<double>::iterator last);
|
||||||
|
|
||||||
template <typename Iterator>
|
OutlierClassification
|
||||||
OutlierClassification classify_outliers(Iterator first, Iterator last) {
|
classify_outliers( std::vector<double>::const_iterator first,
|
||||||
std::vector<double> copy(first, last);
|
std::vector<double>::const_iterator last );
|
||||||
|
|
||||||
auto q1 = weighted_average_quantile(1, 4, copy.begin(), copy.end());
|
double mean( std::vector<double>::const_iterator first,
|
||||||
auto q3 = weighted_average_quantile(3, 4, copy.begin(), copy.end());
|
std::vector<double>::const_iterator last );
|
||||||
auto iqr = q3 - q1;
|
|
||||||
auto los = q1 - (iqr * 3.);
|
|
||||||
auto lom = q1 - (iqr * 1.5);
|
|
||||||
auto him = q3 + (iqr * 1.5);
|
|
||||||
auto his = q3 + (iqr * 3.);
|
|
||||||
|
|
||||||
OutlierClassification o;
|
template <typename Estimator>
|
||||||
for (; first != last; ++first) {
|
sample jackknife(Estimator&& estimator,
|
||||||
auto&& t = *first;
|
std::vector<double>::iterator first,
|
||||||
if (t < los) ++o.low_severe;
|
std::vector<double>::iterator last) {
|
||||||
else if (t < lom) ++o.low_mild;
|
|
||||||
else if (t > his) ++o.high_severe;
|
|
||||||
else if (t > him) ++o.high_mild;
|
|
||||||
++o.samples_seen;
|
|
||||||
}
|
|
||||||
return o;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Iterator>
|
|
||||||
double mean(Iterator first, Iterator last) {
|
|
||||||
auto count = last - first;
|
|
||||||
double sum = std::accumulate(first, last, 0.);
|
|
||||||
return sum / static_cast<double>(count);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Estimator, typename Iterator>
|
|
||||||
sample jackknife(Estimator&& estimator, Iterator first, Iterator last) {
|
|
||||||
auto n = static_cast<size_t>(last - first);
|
auto n = static_cast<size_t>(last - first);
|
||||||
auto second = first;
|
auto second = first;
|
||||||
++second;
|
++second;
|
||||||
@ -85,8 +63,12 @@ namespace Catch {
|
|||||||
|
|
||||||
double normal_quantile(double p);
|
double normal_quantile(double p);
|
||||||
|
|
||||||
template <typename Iterator, typename Estimator>
|
template <typename Estimator>
|
||||||
Estimate<double> bootstrap(double confidence_level, Iterator first, Iterator last, sample const& resample, Estimator&& 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;
|
auto n_samples = last - first;
|
||||||
|
|
||||||
double point = estimator(first, last);
|
double point = estimator(first, last);
|
||||||
@ -136,7 +118,10 @@ namespace Catch {
|
|||||||
double outlier_variance;
|
double outlier_variance;
|
||||||
};
|
};
|
||||||
|
|
||||||
bootstrap_analysis analyse_samples(double confidence_level, unsigned int n_resamples, std::vector<double>::iterator first, std::vector<double>::iterator last);
|
bootstrap_analysis analyse_samples(double confidence_level,
|
||||||
|
unsigned int n_resamples,
|
||||||
|
std::vector<double>::iterator first,
|
||||||
|
std::vector<double>::iterator last);
|
||||||
} // namespace Detail
|
} // namespace Detail
|
||||||
} // namespace Benchmark
|
} // namespace Benchmark
|
||||||
} // namespace Catch
|
} // namespace Catch
|
||||||
|
Loading…
Reference in New Issue
Block a user