16
16
namespace miniselect {
17
17
namespace floyd_rivest_detail {
18
18
19
+ enum floyd_rivest_constants {
20
+ kQCap = 600 ,
21
+ };
22
+
19
23
template <class Compare >
20
24
struct CompareRefType {
21
25
// Pass the comparator by lvalue reference. Or in debug mode, using a
22
26
// debugging wrapper that stores a reference.
23
27
using type = typename std::add_lvalue_reference<Compare>::type;
24
28
};
25
29
26
- template <class Iter , class Compare , class Diff >
27
- inline void floyd_rivest_select_loop (Iter begin, Diff left, Diff right, Diff k,
28
- Compare comp) {
30
+ template <class Iter , class Compare ,
31
+ class DiffType = typename std::iterator_traits<Iter>::difference_type>
32
+ inline void floyd_rivest_select_loop (Iter begin, DiffType left, DiffType right,
33
+ DiffType k, Compare comp) {
29
34
while (right > left) {
30
- Diff size = right - left;
31
- if (size > 600 ) {
32
- Diff n = right - left + 1 ;
33
- Diff i = k - left + 1 ;
35
+ DiffType size = right - left;
36
+ if (size > floyd_rivest_constants::kQCap ) {
37
+ DiffType n = right - left + 1 ;
38
+ DiffType i = k - left + 1 ;
39
+
34
40
double z = log (n);
35
41
double s = 0.5 * exp (2 * z / 3 );
36
42
double sd = 0.5 * sqrt (z * s * (n - s) / n);
37
43
if (i < n / 2 ) {
38
44
sd *= -1.0 ;
39
45
}
40
- Diff newLeft = std::max (left, (Diff)(k - i * s / n + sd));
41
- Diff newRight = std::min (right, (Diff)(k + (n - i) * s / n + sd));
42
- floyd_rivest_select_loop<Iter, Compare, Diff>(begin, newLeft, newRight, k,
43
- comp);
46
+ DiffType newLeft =
47
+ std::max (left, static_cast <DiffType>(k - i * s / n + sd));
48
+ DiffType newRight =
49
+ std::min (right, static_cast <DiffType>(k + (n - i) * s / n + sd));
50
+ floyd_rivest_select_loop<Iter, Compare, DiffType>(begin, newLeft,
51
+ newRight, k, comp);
44
52
}
45
- Diff i = left;
46
- Diff j = right;
53
+ DiffType i = left;
54
+ DiffType j = right;
55
+
47
56
std::swap (begin[left], begin[k]);
48
57
const bool to_swap = comp (begin[left], begin[right]);
49
58
if (to_swap) {
@@ -87,10 +96,9 @@ inline void floyd_rivest_partial_sort(Iter begin, Iter mid, Iter end,
87
96
if (begin == end) return ;
88
97
if (begin == mid) return ;
89
98
using CompType = typename floyd_rivest_detail::CompareRefType<Compare>::type;
90
-
91
- floyd_rivest_detail::floyd_rivest_select_loop<
92
- Iter, CompType, typename std::iterator_traits<Iter>::difference_type>(
93
- begin, 0 , end - begin - 1 , mid - begin - 1 , comp);
99
+ using DiffType = typename std::iterator_traits<Iter>::difference_type;
100
+ floyd_rivest_detail::floyd_rivest_select_loop<Iter, CompType>(
101
+ begin, DiffType{0 }, end - begin - 1 , mid - begin - 1 , comp);
94
102
// std::sort proved to be better than other sorts because of pivoting.
95
103
std::sort<Iter, CompType>(begin, mid, comp);
96
104
}
@@ -105,10 +113,9 @@ template <class Iter, class Compare>
105
113
inline void floyd_rivest_select (Iter begin, Iter mid, Iter end, Compare comp) {
106
114
if (mid == end) return ;
107
115
using CompType = typename floyd_rivest_detail::CompareRefType<Compare>::type;
108
-
109
- floyd_rivest_detail::floyd_rivest_select_loop<
110
- Iter, CompType, typename std::iterator_traits<Iter>::difference_type>(
111
- begin, 0 , end - begin - 1 , mid - begin, comp);
116
+ using DiffType = typename std::iterator_traits<Iter>::difference_type;
117
+ floyd_rivest_detail::floyd_rivest_select_loop<Iter, CompType>(
118
+ begin, DiffType{0 }, end - begin - 1 , mid - begin, comp);
112
119
}
113
120
114
121
template <class Iter >
0 commit comments