1 // Copyright 2016-2021 Francesco Biscani (bluescarni@gmail.com)
2 //
3 // This file is part of the mp++ library.
4 //
5 // This Source Code Form is subject to the terms of the Mozilla
6 // Public License v. 2.0. If a copy of the MPL was not distributed
7 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
8
9 #include <algorithm>
10 #include <cstdint>
11 #include <random>
12 #include <utility>
13 #include <vector>
14
15 #if defined(MPPP_BENCHMARK_BOOST)
16
17 #include <boost/multiprecision/cpp_int.hpp>
18 #include <boost/multiprecision/gmp.hpp>
19
20 #endif
21
22 #if defined(MPPP_BENCHMARK_FLINT)
23
24 #include <flint/flint.h>
25 #include <flint/fmpzxx.h>
26
27 #endif
28
29 #include <fmt/core.h>
30 #include <fmt/ostream.h>
31
32 #include <mp++/config.hpp>
33 #include <mp++/integer.hpp>
34
35 #if defined(MPPP_BENCHMARK_BOOST)
36
37 #include <mp++/detail/gmp.hpp>
38
39 #endif
40
41 #include "utils.hpp"
42
43 namespace
44 {
45
46 #if defined(MPPP_BENCHMARK_BOOST)
47
48 using cpp_int = boost::multiprecision::number<boost::multiprecision::cpp_int_backend<>, boost::multiprecision::et_on>;
49 using mpz_int = boost::multiprecision::number<boost::multiprecision::gmp_int, boost::multiprecision::et_off>;
50
51 #endif
52
53 std::mt19937 rng;
54
55 constexpr auto size = 30000000ul;
56
57 template <typename T>
get_init_vectors()58 std::tuple<std::vector<T>, std::vector<T>, std::vector<T>> get_init_vectors()
59 {
60 rng.seed(0);
61 std::uniform_int_distribution<unsigned> dist(1u, 7u);
62 std::vector<T> v1(size), v2(size), v3(size);
63 std::generate(v1.begin(), v1.end(), [&dist]() { return T(dist(rng) * dist(rng)); });
64 std::generate(v2.begin(), v2.end(), [&dist]() { return T(dist(rng)); });
65 return std::make_tuple(std::move(v1), std::move(v2), std::move(v3));
66 }
67
68 const auto benchmark_name = mppp_benchmark_name();
69
70 } // namespace
71
main()72 int main()
73 {
74 fmt::print("Benchmark name: {}\n", benchmark_name);
75
76 // Warm up.
77 mppp_benchmark::warmup();
78
79 // Prepare the benchmark result data.
80 mppp_benchmark::data_t bdata;
81
82 {
83 auto p = get_init_vectors<mppp::integer<1>>();
84 constexpr auto name = "mppp::integer<1>";
85
86 mppp::integer<1> ret(0);
87
88 mppp_benchmark::simple_timer st;
89
90 for (auto i = 0ul; i < size; ++i) {
91 tdiv_q(std::get<2>(p)[i], std::get<0>(p)[i], std::get<1>(p)[i]);
92 ret += std::get<2>(p)[i];
93 }
94
95 const auto runtime = st.elapsed();
96 bdata.emplace_back(name, runtime);
97 fmt::print(mppp_benchmark::res_print_format, name, runtime, ret);
98 }
99
100 {
101 auto p = get_init_vectors<std::uint_least64_t>();
102 constexpr auto name = "std::uint64_t";
103
104 std::uint_least64_t ret = 0;
105
106 mppp_benchmark::simple_timer st;
107
108 for (auto i = 0ul; i < size; ++i) {
109 std::get<2>(p)[i] = std::get<0>(p)[i] / std::get<1>(p)[i];
110 ret += std::get<2>(p)[i];
111 }
112
113 const auto runtime = st.elapsed();
114 bdata.emplace_back(name, runtime);
115 fmt::print(mppp_benchmark::res_print_format, name, runtime, ret);
116 }
117
118 #if defined(MPPP_HAVE_GCC_INT128)
119 {
120 auto p = get_init_vectors<__uint128_t>();
121 constexpr auto name = "__uint128_t";
122
123 __uint128_t ret = 0;
124
125 mppp_benchmark::simple_timer st;
126
127 for (auto i = 0ul; i < size; ++i) {
128 std::get<2>(p)[i] = std::get<0>(p)[i] / std::get<1>(p)[i];
129 ret += std::get<2>(p)[i];
130 }
131
132 const auto runtime = st.elapsed();
133 bdata.emplace_back(name, runtime);
134 fmt::print(mppp_benchmark::res_print_format, name, runtime, ret);
135 }
136 #endif
137
138 #if defined(MPPP_BENCHMARK_BOOST)
139 {
140 auto p = get_init_vectors<cpp_int>();
141 constexpr auto name = "boost::cpp_int";
142
143 cpp_int ret(0);
144
145 mppp_benchmark::simple_timer st;
146
147 for (auto i = 0ul; i < size; ++i) {
148 std::get<2>(p)[i] = std::get<0>(p)[i] / std::get<1>(p)[i];
149 ret += std::get<2>(p)[i];
150 }
151
152 const auto runtime = st.elapsed();
153 bdata.emplace_back(name, runtime);
154 fmt::print(mppp_benchmark::res_print_format, name, runtime, ret);
155 }
156
157 {
158 auto p = get_init_vectors<mpz_int>();
159 constexpr auto name = "boost::gmp_int";
160
161 mpz_int ret(0);
162
163 mppp_benchmark::simple_timer st;
164
165 for (auto i = 0ul; i < size; ++i) {
166 mpz_tdiv_q(std::get<2>(p)[i].backend().data(), std::get<0>(p)[i].backend().data(),
167 std::get<1>(p)[i].backend().data());
168 mpz_add(ret.backend().data(), ret.backend().data(), std::get<2>(p)[i].backend().data());
169 }
170
171 const auto runtime = st.elapsed();
172 bdata.emplace_back(name, runtime);
173 fmt::print(mppp_benchmark::res_print_format, name, runtime, ret);
174 }
175 #endif
176
177 #if defined(MPPP_BENCHMARK_FLINT)
178 {
179 auto p = get_init_vectors<flint::fmpzxx>();
180 constexpr auto name = "flint::fmpzxx";
181
182 flint::fmpzxx ret(0);
183
184 mppp_benchmark::simple_timer st;
185
186 for (auto i = 0ul; i < size; ++i) {
187 ::fmpz_tdiv_q(std::get<2>(p)[i]._data().inner, std::get<0>(p)[i]._data().inner,
188 std::get<1>(p)[i]._data().inner);
189 ::fmpz_add(ret._data().inner, ret._data().inner, std::get<2>(p)[i]._data().inner);
190 }
191
192 const auto runtime = st.elapsed();
193 bdata.emplace_back(name, runtime);
194 fmt::print(mppp_benchmark::res_print_format, name, runtime, ret);
195 }
196 #endif
197
198 // Write out the .py and .rst files.
199 mppp_benchmark::write_out(bdata, benchmark_name);
200 }
201