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 <numeric>
12 #include <random>
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++/integer.hpp>
33 
34 #if defined(MPPP_BENCHMARK_BOOST)
35 
36 #include <mp++/detail/gmp.hpp>
37 
38 #endif
39 
40 #include "utils.hpp"
41 
42 namespace
43 {
44 
45 #if defined(MPPP_BENCHMARK_BOOST)
46 
47 using cpp_int = boost::multiprecision::number<boost::multiprecision::cpp_int_backend<>, boost::multiprecision::et_on>;
48 using mpz_int = boost::multiprecision::number<boost::multiprecision::gmp_int, boost::multiprecision::et_off>;
49 
50 #endif
51 
52 std::mt19937 rng;
53 
54 constexpr auto size = 30000000ul;
55 
56 template <typename T>
get_init_vector()57 std::vector<T> get_init_vector()
58 {
59     rng.seed(0);
60     std::uniform_int_distribution<unsigned> dist(0u, 10000u);
61     std::vector<T> retval(size);
62     std::generate(retval.begin(), retval.end(), [&dist]() { return T(dist(rng)); });
63     return retval;
64 }
65 
66 const auto benchmark_name = mppp_benchmark_name();
67 
68 } // namespace
69 
main()70 int main()
71 {
72     fmt::print("Benchmark name: {}\n", benchmark_name);
73 
74     // Warm up.
75     mppp_benchmark::warmup();
76 
77     // Prepare the benchmark result data.
78     mppp_benchmark::data_t bdata;
79 
80     {
81         auto v = get_init_vector<mppp::integer<2>>();
82         constexpr auto name = "mppp::integer<2>";
83 
84         std::vector<unsigned> c_out(size);
85 
86         mppp_benchmark::simple_timer st;
87 
88         std::transform(v.begin(), v.end(), c_out.begin(),
89                        [](const mppp::integer<2> &n) { return static_cast<unsigned>(n); });
90 
91         const auto runtime = st.elapsed();
92         bdata.emplace_back(name, runtime);
93         fmt::print(mppp_benchmark::res_print_format, name, runtime, std::accumulate(c_out.begin(), c_out.end(), 0ul));
94     }
95 
96 #if defined(MPPP_BENCHMARK_BOOST)
97     {
98         auto v = get_init_vector<cpp_int>();
99         constexpr auto name = "boost::cpp_int";
100 
101         std::vector<unsigned> c_out(size);
102 
103         mppp_benchmark::simple_timer st;
104 
105         std::transform(v.begin(), v.end(), c_out.begin(), [](const cpp_int &n) { return static_cast<unsigned>(n); });
106 
107         const auto runtime = st.elapsed();
108         bdata.emplace_back(name, runtime);
109         fmt::print(mppp_benchmark::res_print_format, name, runtime, std::accumulate(c_out.begin(), c_out.end(), 0ul));
110     }
111 
112     {
113         auto v = get_init_vector<mpz_int>();
114         constexpr auto name = "boost::gmp_int";
115 
116         std::vector<unsigned> c_out(size);
117 
118         mppp_benchmark::simple_timer st;
119 
120         std::transform(v.begin(), v.end(), c_out.begin(),
121                        [](const mpz_int &n) { return static_cast<unsigned>(mpz_get_ui(n.backend().data())); });
122 
123         const auto runtime = st.elapsed();
124         bdata.emplace_back(name, runtime);
125         fmt::print(mppp_benchmark::res_print_format, name, runtime, std::accumulate(c_out.begin(), c_out.end(), 0ul));
126     }
127 #endif
128 
129 #if defined(MPPP_BENCHMARK_FLINT)
130     {
131         auto v = get_init_vector<flint::fmpzxx>();
132         constexpr auto name = "flint::fmpzxx";
133 
134         std::vector<unsigned> c_out(size);
135 
136         mppp_benchmark::simple_timer st;
137 
138         std::transform(v.begin(), v.end(), c_out.begin(),
139                        [](const flint::fmpzxx &n) { return static_cast<unsigned>(::fmpz_get_ui(n._data().inner)); });
140 
141         const auto runtime = st.elapsed();
142         bdata.emplace_back(name, runtime);
143         fmt::print(mppp_benchmark::res_print_format, name, runtime, std::accumulate(c_out.begin(), c_out.end(), 0ul));
144     }
145 #endif
146 
147     // Write out the .py and .rst files.
148     mppp_benchmark::write_out(bdata, benchmark_name);
149 }
150