// (C) Copyright Nick Thompson 2020. // Use, modification and distribution are subject to the // Boost Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #include #include #include #include #include #include #include #include #include using boost::multiprecision::number; using boost::multiprecision::mpfr_float_backend; using boost::multiprecision::float128; using boost::multiprecision::cpp_bin_float_50; using boost::multiprecision::cpp_bin_float_100; using boost::math::tools::cohen_acceleration; using boost::math::constants::pi; template class G { public: G(){ k_ = 0; } Real operator()() { k_ += 1; return 1/(k_*k_); } private: Real k_; }; template void CohenAcceleration(benchmark::State& state) { using std::abs; Real x = pi()*pi()/12; for (auto _ : state) { auto g = G(); x = cohen_acceleration(g); benchmark::DoNotOptimize(x); } if (abs(x - pi()*pi()/12) > 16*std::numeric_limits::epsilon()) { std::cerr << std::setprecision(std::numeric_limits::max_digits10); std::cerr << "Cohen acceleration computed " << x << " on type " << boost::core::demangle(typeid(Real).name()) << "\n"; std::cerr << "But expected value is " << pi()*pi()/12 << "\n"; } } BENCHMARK_TEMPLATE(CohenAcceleration, float); BENCHMARK_TEMPLATE(CohenAcceleration, double); BENCHMARK_TEMPLATE(CohenAcceleration, long double); BENCHMARK_TEMPLATE(CohenAcceleration, float128); BENCHMARK_TEMPLATE(CohenAcceleration, cpp_bin_float_50); BENCHMARK_TEMPLATE(CohenAcceleration, cpp_bin_float_100); BENCHMARK_TEMPLATE(CohenAcceleration, number>); BENCHMARK_TEMPLATE(CohenAcceleration, number>); BENCHMARK_TEMPLATE(CohenAcceleration, number>); BENCHMARK_TEMPLATE(CohenAcceleration, number>); BENCHMARK_TEMPLATE(CohenAcceleration, number>); template void NaiveSum(benchmark::State& state) { using std::abs; Real x = pi()*pi()/12; for (auto _ : state) { auto g = G(); Real term = g(); x = term; bool even = false; while (term > std::numeric_limits::epsilon()/2) { term = g(); if (even) { x += term; even = false; } else { x -= term; even = true; } } benchmark::DoNotOptimize(x); } // The accuracy tests don't pass because the sum is ill-conditioned: /*if (abs(x - pi()*pi()/12) > 16*std::numeric_limits::epsilon()) { std::cerr << std::setprecision(std::numeric_limits::max_digits10); std::cerr << "Cohen acceleration computed " << x << " on type " << boost::core::demangle(typeid(Real).name()) << "\n"; std::cerr << "But expected value is " << pi()*pi()/12 << "\n"; }*/ } BENCHMARK_TEMPLATE(NaiveSum, float); BENCHMARK_TEMPLATE(NaiveSum, double); BENCHMARK_TEMPLATE(NaiveSum, long double); BENCHMARK_TEMPLATE(NaiveSum, float128); BENCHMARK_TEMPLATE(NaiveSum, cpp_bin_float_50); BENCHMARK_TEMPLATE(NaiveSum, cpp_bin_float_100); BENCHMARK_TEMPLATE(NaiveSum, number>); BENCHMARK_TEMPLATE(NaiveSum, number>); BENCHMARK_TEMPLATE(NaiveSum, number>); BENCHMARK_TEMPLATE(NaiveSum, number>); BENCHMARK_TEMPLATE(NaiveSum, number>); BENCHMARK_MAIN();