11template <
typename T, std::
size_t N>
21 const auto goal = [&] {
28 for (
const auto& v : c) {
29 std::cout << v <<
", ";
35 static_assert(
sort_test(input),
"insertion_sort should be constexpr");
38 SECTION(
"insertion_sort") {
39 auto input_copy = input;
41 CHECK(input_copy == goal);
44 "insertion_sort for array<int> should be noexcept");
46 SECTION(
"insertion_sort_copy") {
47 std::remove_const<
decltype(input)>::type output;
50 CHECK(output == goal);
53 output.begin(), output.end())),
54 "insertion_sort_copy for array<int> should be noexcept");
56 SECTION(
"adaptive_insertion_sort_copy") {
57 std::remove_const<
decltype(input)>::type output;
59 output.begin(), output.end());
60 CHECK(output == goal);
62 SECTION(
"insertion_sort is stable") {
63 std::minstd_rand rng{std::random_device{}()};
64 std::uniform_int_distribution<int> dist(0, 8);
68 std::vector<std::pair<int, int>> inputs;
69 auto pcomp = [](
auto a,
auto b) {
return a.first < b.first; };
72 std::map<int, int> counts;
75 inputs.emplace_back(r, counts[r]++);
82 std::map<int, int> counts;
83 for (
auto p : inputs) {
84 CHECK(p.second == counts[p.first]++);
89 SECTION(
"insertion_sort on random data") {
90 std::minstd_rand rng{std::random_device{}()};
91 std::uniform_int_distribution<int> dist(0, 65535);
93 std::vector<int> input2(100);
94 std::generate(begin(input2), end(input2), [&] {
return dist(rng); });
96 auto output_std = input2;
97 std::sort(output_std.begin(), output_std.end());
98 decltype(input2) output_kblib(input2.size());
100 output_kblib.begin(), output_kblib.end());
101 CHECK(output_std == output_kblib);
106static std::ostream& log_location = std::cout;
108auto linear(std::size_t i) {
return static_cast<double>(i); }
112 = [&](
auto line,
auto&& f, std::size_t quick = 30,
113 std::size_t slow = 10000, double (*O)(std::size_t) =
linear) {
114 auto time_fast = f(quick) / O(quick);
115 auto time_slow = f(slow) / O(slow);
116 auto error = time_slow / time_fast;
117 log_location << __FILE__
":" << std::left << line <<
": \t"
118 << time_fast <<
"\t " << std::setw(12) << time_slow
119 <<
'\t' << std::setw(14) << error <<
'\t'
120 << time_slow * 10000 <<
'\t' << time_fast * 30 <<
"\n";
125#define TIME(...) time_and_log(__LINE__, __VA_ARGS__)
128 using namespace std::literals;
129 log_location << __FILE__
":" << std::left << __LINE__
130 <<
": \t/el (30)\t /el (10000)"
131 "\tsuperlinearity\ttotal (10000)\t"
136 SECTION(
"insertion_sort_copy on sorted data is fast") {
137 auto time_per = [](std::size_t
size) {
138 std::vector<int> input(
size);
139 decltype(input) output(
size);
140 std::iota(input.begin(), input.end(), 0);
142 auto start = std::chrono::high_resolution_clock::now();
144 output.begin(), output.end());
145 auto end = std::chrono::high_resolution_clock::now();
146 auto duration = end - start;
147 return static_cast<double>(duration.count());
152 SECTION(
"insertion_sort_copy on reverse sorted data is slow") {
153 auto time_per = [](std::size_t
size) {
154 std::vector<int> input(
size);
155 decltype(input) output(
size);
156 std::iota(input.rbegin(), input.rend(), 0);
158 auto start = std::chrono::high_resolution_clock::now();
160 output.begin(), output.end());
161 auto end = std::chrono::high_resolution_clock::now();
162 auto duration = end - start;
163 return static_cast<double>(duration.count());
167 time_per, 30, 1000, +[](std::size_t i) {
168 return static_cast<double>(i) *
static_cast<double>(i);
171 SECTION(
"adaptive_insertion_sort_copy on sorted data is fast") {
172 auto time_per = [](std::size_t
size) {
173 std::vector<int> input(
size);
174 decltype(input) output(
size);
175 std::iota(input.begin(), input.end(), 0);
177 auto start = std::chrono::high_resolution_clock::now();
179 output.begin(), output.end());
180 auto end = std::chrono::high_resolution_clock::now();
181 auto duration = end - start;
182 return static_cast<double>(duration.count());
187 SECTION(
"adaptive_insertion_sort_copy on reverse sorted data is fast") {
188 auto time_per = [](std::size_t
size) {
189 std::vector<int> input(
size);
190 decltype(input) output(
size);
191 std::iota(input.rbegin(), input.rend(), 0);
193 auto start = std::chrono::high_resolution_clock::now();
195 output.begin(), output.end());
196 auto end = std::chrono::high_resolution_clock::now();
197 auto duration = end - start;
198 return static_cast<double>(duration.count());
203 SECTION(
"insertion_sort_copy on mostly sorted data is fast") {
204 std::minstd_rand rng{std::random_device{}()};
205 auto time_per = [&](
int ssize,
int noise) {
206 auto size =
static_cast<std::size_t
>(ssize);
207 std::uniform_int_distribution<int> dist(-noise, noise);
208 std::vector<int> input(
size);
209 decltype(input) output(
size);
214 auto start = std::chrono::high_resolution_clock::now();
216 output.begin(), output.end());
217 auto end = std::chrono::high_resolution_clock::now();
218 auto duration = end - start;
219 return static_cast<double>(duration.count());
226 using namespace std::literals;
228 << __FILE__
":" << std::left << __LINE__
229 <<
": \t/el (s) \t /el (v) "
230 "\tsuperlinearity\ttotal (v) \t"
234 auto time_fast = time_per(n, 0) / n;
235 auto time_slow = time_per(n, v) / n;
236 auto ratio = time_slow / time_fast;
237 auto error = ratio / (n / v);
239 log_location << __FILE__
":" << std::left << __LINE__ <<
": \t"
240 << time_fast <<
"\t " << std::setw(12) << time_slow <<
'\t'
241 << std::setw(14) << error <<
'\t' << time_slow * 10000
242 <<
'\t' << time_fast * 30 <<
"\n";
247 log_location << std::flush;
252 constexpr std::uint32_t x{0xAB23CD67};
254 static_assert(std::numeric_limits<std::uint32_t>::digits
255 ==
sizeof(uint32_t) * CHAR_BIT,
256 "these checks assume uint32_t does not have padding.");
257 static_assert(CHAR_BIT == 8,
"these checks assume 8-bit bytes");
265 std::string str{
"0123456789"};
271 constexpr std::array<std::int32_t, 2> arr{0x10325476,
272 std::int32_t(0x98BADCFE)};
constexpr auto sort(RandomAccessIt, const RandomAccessIt, Compare) -> void
constexpr auto size(const C &c) -> decltype(c.size())
constexpr auto a(const std::initializer_list< T > &a) -> auto
Index an array literal without naming its type.
constexpr auto generate(OutputIt first, EndIt last, Generator g) noexcept(noexcept(*++first=g())) -> OutputIt
Like std::generate except that it returns the output iterator at the end. It also allows for a sentin...
constexpr auto byte_count(T) noexcept -> enable_if_t< std::is_integral< T >::value, std::size_t >
constexpr auto iota(ForwardIt first, ForwardIt last, T value) noexcept(noexcept(*first++=value) and noexcept(++value)) -> void
constexpr auto insertion_sort(const RandomAccessIt begin, const RandomAccessIt end, Compare &&compare={}) noexcept(noexcept(swap(*begin, *begin)) and noexcept(compare(*begin, *begin))) -> void
In-place insertion sort. As is usual, it is stable. Provides as a guarantee that it will perform no m...
constexpr auto insertion_sort_copy(const RandomAccessIt begin, const RandomAccessIt end, const RandomAccessIt2 d_begin, const RandomAccessIt2 d_end, Compare &&compare={}) noexcept(noexcept(detail_algorithm::shift_backward(d_begin, d_begin, d_end)) and noexcept(*d_begin= *begin)) -> void
Out-of-place insertion sort, which does not modify the input. Provides as a guarantee that it will pe...
constexpr auto adaptive_insertion_sort_copy(const RandomAccessIt begin, const RandomAccessIt end, const RandomAccessIt2 d_begin, const RandomAccessIt2 d_end, Compare &&compare={}) noexcept(noexcept(detail_algorithm::shift_backward(d_begin, d_begin, d_end)) and noexcept(*d_begin= *begin)) -> void
An adaptive sort which, at the cost of some additional work (time complexity Θ(sqrt(n))),...
constexpr auto range(Value min, Value max, Delta step=0) -> range_t< Value, Delta >
Constructs a range from beginning, end, and step amount. The range is half-open, that is min is in th...
constexpr auto copy(InputIt first, EndIt last, OutputIt out) -> OutputIt
Copies all elements of [first, last) to out. It also allows for a sentinel end iterator.
constexpr auto get_byte_index(T x, std::size_t idx) noexcept -> enable_if_t< std::is_integral< T >::value, unsigned char >
constexpr auto to_unsigned(I x) -> std::make_unsigned_t< I >
Cast integral argument to corresponding unsigned type.
constexpr auto repeat(std::size_t N, Callable func) noexcept(noexcept(func())) -> return_assert_t< is_invocable< Callable >::value, void >
Invoke a function N times.
constexpr auto sort_test(kblib::trivial_array< T, N > val) noexcept -> bool
auto linear(std::size_t i)
{WIP} Provides a fast and generic sorting interface.
Provides numerical and mathematical utilities.
Provides utilities for performing common operations on strings.
std::array isn't constexpr enough in C++14, so a dedicated array class is needed for constexpr functi...
#define KBLIB_UNUSED
This internal macro is used to provide a fallback for [[maybe_unused]] in C++14.