mutable
A Database System for Research and Fast Prototyping
Loading...
Searching...
No Matches
algorithms.hpp
Go to the documentation of this file.
1#pragma once
2
3
5#include <algorithm>
6#include <cstddef>
7#include <type_traits>
8#include <utility>
9
10
11namespace m {
12
13
18template<typename It>
19bool verify_partition(It begin, It mid, It end)
20{
21 using T = std::remove_reference_t<decltype(*begin)>;
22 T max_lo{std::numeric_limits<T>::lowest()};
23 T min_hi{std::numeric_limits<T>::max()};
24 M_insist(max_lo < min_hi);
25 for (It p = begin; p != mid; ++p)
26 max_lo = std::max(max_lo, *p);
27 for (It p = mid; p != end; ++p)
28 min_hi = std::min(min_hi, *p);
29 return max_lo <= min_hi;
30}
31
37{
38 template<typename T, typename It>
39 It operator()(const T pivot, It begin, It end)
40 {
41#ifndef NDEBUG
42 const It the_end = end;
43#endif
44 using std::prev;
45 while (begin < end) {
46 const T left = *begin;
47 const T right = *prev(end);
48 *begin = right;
49 *prev(end) = left;
50 const ptrdiff_t adv_lo = right <= pivot;
51 const ptrdiff_t adv_hi = left >= pivot;
52 begin += adv_lo;
53 end -= adv_hi;
54 }
55#ifndef NDEBUG
56 M_insist(begin == the_end or *begin >= pivot);
57#endif
58 return begin;
59 }
60};
61
62template<typename Partitioning, typename It>
63void qsort(It begin, It end, Partitioning p)
64{
65 using std::swap;
66 using std::min, std::max;
67 using std::distance;
68 using std::prev, std::next;
69 M_insist(begin <= end);
70
71 while (distance(begin, end) > 2) {
72 /* Compute median of three. */
73 auto pm = begin + (end - begin) / 2;
74 bool left_le_mid = *begin <= *pm;
75 bool left_le_right = *begin <= *prev(end);
76 bool mid_le_right = *pm <= *prev(end);
77 if (left_le_mid) {
78 if (left_le_right) {
79 if (mid_le_right)
80 swap(*begin, *pm);
81 else
82 swap(*begin, *prev(end));
83 } else {
84 /* nothing to be done */
85 }
86 } else {
87 if (mid_le_right) {
88 if (left_le_right) {
89 /* nothing to be done */
90 } else {
91 swap(*begin, *prev(end));
92 }
93 } else {
94 swap(*begin, *pm);
95 }
96 }
97
98 It mid = p(*begin, next(begin), end);
99 M_insist(mid <= end);
100 M_insist(mid >= next(begin));
101 M_insist(verify_partition(next(begin), mid, end));
102 swap(*begin, *prev(mid));
103
104 if (distance(mid, end) >= 2) qsort(mid, end, p); // recurse to the right
105 M_insist(std::is_sorted(mid, end));
106 end = prev(mid);
107 }
108
109 if (distance(begin, end) == 2) {
110 if (*begin > *prev(end))
111 swap(*begin, *prev(end));
112 }
113};
114
115}
#define M_insist(...)
Definition: macro.hpp:129
‍mutable namespace
Definition: Backend.hpp:10
void qsort(It begin, It end, Partitioning p)
Definition: algorithms.hpp:63
void swap(PlanTableBase< Actual > &first, PlanTableBase< Actual > &second)
Definition: PlanTable.hpp:394
T(x)
bool verify_partition(It begin, It mid, It end)
Verifies that mid splits the range begin to end (exclusive) into two partitions.
Definition: algorithms.hpp:19
Partitions the range begin to end (exclusive) into two partitions using pivot.
Definition: algorithms.hpp:37
It operator()(const T pivot, It begin, It end)
Definition: algorithms.hpp:39