// Copyright 2020 John Maddock. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt #include #include #include #include #include #include #include #include #include #include template T generate_random(unsigned bits_wanted) { static boost::random::mt19937 gen; typedef boost::random::mt19937::result_type random_type; T max_val; unsigned digits; if (std::numeric_limits::is_bounded && (bits_wanted == (unsigned)std::numeric_limits::digits)) { max_val = (std::numeric_limits::max)(); digits = std::numeric_limits::digits; } else { max_val = T(1) << bits_wanted; digits = bits_wanted; } unsigned bits_per_r_val = std::numeric_limits::digits - 1; while ((random_type(1) << bits_per_r_val) > (gen.max)()) --bits_per_r_val; unsigned terms_needed = digits / bits_per_r_val + 1; T val = 0; for (unsigned i = 0; i < terms_needed; ++i) { val *= (gen.max)(); val += gen(); } val %= max_val; return val; } template const std::vector >& get_matrix_data(unsigned bits); template <> const std::vector >& get_matrix_data(unsigned bits) { static std::map > > data; if (data[bits].size() == 0) { for (unsigned i = 0; i < 100; ++i) { std::vector matrix; for (unsigned j = 0; j < 9; ++j) { boost::multiprecision::cpp_int a(generate_random(bits)), b(generate_random(bits)); matrix.push_back(boost::multiprecision::cpp_rational(a, b)); } data[bits].push_back(matrix); } } return data[bits]; } template const std::vector >& get_matrix_data(unsigned bits) { static std::map > > data; if (data[bits].empty()) { const std::vector >& d = get_matrix_data(bits); for (unsigned i = 0; i < 100; ++i) { std::vector matrix; for (unsigned j = 0; j < 9; ++j) { matrix.push_back(T(d[i][j].str())); } data[bits].push_back(matrix); } } return data[bits]; } template T determinant(const std::vector& data) { const T m01 = data[0] * data[4] - data[3] * data[1]; const T m02 = data[0] * data[7] - data[6] * data[1]; const T m12 = data[3] * data[7] - data[6] * data[4]; return m01 * data[8] - m02 * data[5] + m12 * data[2]; } template static void BM_determinant(benchmark::State& state) { int bits = state.range(0); const std::vector >& data = get_matrix_data(bits); for (auto _ : state) { for(unsigned i = 0; i < data.size(); ++i) benchmark::DoNotOptimize(determinant(data[i])); } } constexpr unsigned lower_range = 512; constexpr unsigned upper_range = 1 << 15; BENCHMARK_TEMPLATE(BM_determinant, boost::multiprecision::cpp_rational)->RangeMultiplier(2)->Range(lower_range, upper_range)->Unit(benchmark::kMillisecond); BENCHMARK_TEMPLATE(BM_determinant, boost::multiprecision::mpq_rational)->RangeMultiplier(2)->Range(lower_range, upper_range)->Unit(benchmark::kMillisecond); BENCHMARK_TEMPLATE(BM_determinant, mpq_class)->RangeMultiplier(2)->Range(lower_range, upper_range)->Unit(benchmark::kMillisecond); BENCHMARK_MAIN();