-
Notifications
You must be signed in to change notification settings - Fork 4
/
divceil.cpp
149 lines (130 loc) · 5.11 KB
/
divceil.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#include <utility/io/read.hpp>
#include <burst/integer/divceil.hpp>
#include <boost/program_options.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/tuple/tuple_io.hpp>
#include <chrono>
#include <cstdint>
#include <iostream>
#include <numeric>
#include <unordered_map>
#include <vector>
template <typename Container, typename Integer>
void test_divceil (const Container & values, Integer divisor, std::size_t attempt_count)
{
using namespace std::chrono;
using value_type = typename Container::value_type;
const auto start_time = steady_clock::now();
auto total = value_type{0};
for (std::size_t iteration = 0; iteration < attempt_count; ++iteration)
{
auto r =
std::accumulate(values.begin(), values.end(), value_type{0},
[divisor] (auto a, auto b)
{
return a + burst::divceil(b, divisor);
});
// Убогий ГЦЦ не может осилить оператор `+=`.
total = static_cast<value_type>(total + r);
}
const auto total_time = steady_clock::now() - start_time;
std::clog << total << std::endl;
const auto time = duration_cast<duration<double>>(total_time).count();
std::cout << "Время: " << time << std::endl;
}
template <typename Integer1, typename Integer2>
void test_all (std::int64_t divisor, std::size_t attempt_count)
{
std::vector<Integer1> values;
utility::read(std::cin, values);
test_divceil(values, static_cast<Integer2>(divisor), attempt_count);
}
using test_call_type = void (*) (std::int64_t, std::size_t);
template <typename Integer>
test_call_type dispatch_divisor (const std::string & divisor_type)
{
static const auto test_calls =
std::unordered_map<std::string, test_call_type>
{
{"uint8", &test_all<Integer, std::uint8_t>},
{"uint16", &test_all<Integer, std::uint16_t>},
{"uint32", &test_all<Integer, std::uint32_t>},
{"uint64", &test_all<Integer, std::uint64_t>},
{"int8", &test_all<Integer, std::int8_t>},
{"int16", &test_all<Integer, std::int16_t>},
{"int32", &test_all<Integer, std::int32_t>},
{"int64", &test_all<Integer, std::int64_t>}
};
auto call = test_calls.find(divisor_type);
if (call != test_calls.end())
{
return call->second;
}
else
{
throw boost::program_options::error(u8"Неверная разрядность делителя: " + divisor_type);
}
}
test_call_type get_call (const std::string & integer_type, const std::string & divisor_type)
{
using divisor_dispatcher = test_call_type (*) (const std::string &);
static const auto dispatchers =
std::unordered_map<std::string, divisor_dispatcher>
{
{"uint8", &dispatch_divisor<std::uint8_t>},
{"uint16", &dispatch_divisor<std::uint16_t>},
{"uint32", &dispatch_divisor<std::uint32_t>},
{"uint64", &dispatch_divisor<std::uint64_t>},
{"int8", &dispatch_divisor<std::int8_t>},
{"int16", &dispatch_divisor<std::int16_t>},
{"int32", &dispatch_divisor<std::int32_t>},
{"int64", &dispatch_divisor<std::int64_t>}
};
auto dispatcher = dispatchers.find(integer_type);
if (dispatcher != dispatchers.end())
{
return dispatcher->second(divisor_type);
}
else
{
throw boost::program_options::error(u8"Неверная разрядность сортируемых чисел: " + integer_type);
}
}
int main (int argc, const char * argv[])
{
namespace bpo = boost::program_options;
bpo::options_description description("Опции");
description.add_options()
("help,h", "Подсказка.")
("attempts", bpo::value<std::size_t>()->default_value(1000),
"Количество испытаний.")
("integer", bpo::value<std::string>()->default_value("int32"),
"Тип сортируемых чисел.\n"
"Допустимые значения: uint8, uint16, uint32, uint64, int8, int16, int32, int64")
("divisor", bpo::value<boost::tuple<std::string, std::int64_t>>()->default_value(boost::make_tuple("int32", 100)),
"Тип делителя.\n"
"Допустимые значения: uint8, uint16, uint32, uint64, int8, int16, int32, int64");
try
{
bpo::variables_map vm;
bpo::store(bpo::parse_command_line(argc, argv, description), vm);
bpo::notify(vm);
if (vm.count("help"))
{
std::cout << description << std::endl;
}
else
{
auto attempts = vm["attempts"].as<std::size_t>();
auto integer_type = vm["integer"].as<std::string>();
auto divisor = vm["divisor"].as<boost::tuple<std::string, std::int64_t>>();
auto test = get_call(integer_type, boost::get<0>(divisor));
test(boost::get<1>(divisor), attempts);
}
}
catch (bpo::error & e)
{
std::cout << e.what() << std::endl;
std::cout << description << std::endl;
}
}