Skip to content

Commit 21fdc24

Browse files
committed
Merge branch 'dev' into main
2 parents f1b5902 + b54bbdd commit 21fdc24

7 files changed

+181
-174
lines changed

benches/benchmark_select.cpp

+10-23
Original file line numberDiff line numberDiff line change
@@ -18,44 +18,31 @@
1818
namespace miniselect {
1919
namespace {
2020

21-
static constexpr size_t kSize = 1000 * 1000 * 10;
21+
static constexpr size_t kSize = 65536;
2222

2323
template <class DataGen, class Impl>
2424
static void BM_sel(benchmark::State& state) {
2525
auto vec = DataGen::Gen(kSize);
2626
const size_t arg = state.range(0);
2727
size_t cnt = 0;
28-
size_t cmp = 0;
28+
size_t access_count = 0;
29+
size_t comparison_count = 0;
30+
miniselect::datagens::CountingIterator begin_v(&vec, 0, &access_count);
31+
miniselect::datagens::CountingIterator end_v(&vec, vec.size(), &access_count);
2932
for (auto _ : state) {
30-
Impl::Select(vec.begin(), vec.begin() + arg, vec.end(),
31-
[&cmp](const auto& left, const auto& right) {
32-
cmp++;
33+
Impl::Select(begin_v, begin_v + arg, end_v,
34+
[&comparison_count](const auto& left, const auto& right) {
35+
comparison_count++;
3336
return left < right;
3437
});
3538
++cnt;
3639
benchmark::DoNotOptimize(vec[arg]);
3740
}
38-
state.counters["Comparisons"] = 1.0 * cmp / cnt;
39-
}
40-
41-
template <class DataGen, class Impl>
42-
static void BM_sel_accesses(benchmark::State& state) {
43-
auto vec = DataGen::Gen(kSize);
44-
const size_t arg = state.range(0);
45-
size_t cnt = 0;
46-
size_t cmp = 0;
47-
miniselect::datagens::CountingIterator begin_v(&vec, 0, &cmp);
48-
miniselect::datagens::CountingIterator end_v(&vec, vec.size(), &cmp);
49-
for (auto _ : state) {
50-
Impl::Select(begin_v, begin_v + arg, end_v);
51-
++cnt;
52-
benchmark::DoNotOptimize(vec[arg]);
53-
}
54-
state.counters["Array Accesses"] = 1.0 * cmp / cnt;
41+
state.counters["Array Accesses"] = 1.0 * access_count / cnt;
42+
state.counters["Comparisons"] = 1.0 * comparison_count / cnt;
5543
}
5644

5745
BENCH(BM_sel);
58-
BENCH(BM_sel_accesses);
5946

6047
} // namespace
6148
} // namespace miniselect

benches/benchmark_sort.cpp

+9-22
Original file line numberDiff line numberDiff line change
@@ -25,37 +25,24 @@ static void BM_sort(benchmark::State& state) {
2525
auto vec = DataGen::Gen(kSize);
2626
const size_t arg = state.range(0);
2727
size_t cnt = 0;
28-
size_t cmp = 0;
28+
size_t access_count = 0;
29+
size_t comparison_count = 0;
30+
miniselect::datagens::CountingIterator begin_v(&vec, 0, &access_count);
31+
miniselect::datagens::CountingIterator end_v(&vec, vec.size(), &access_count);
2932
for (auto _ : state) {
30-
Impl::Sort(vec.begin(), vec.begin() + arg, vec.end(),
31-
[&cmp](const auto& left, const auto& right) {
32-
cmp++;
33+
Impl::Sort(begin_v, begin_v + arg, end_v,
34+
[&comparison_count](const auto& left, const auto& right) {
35+
comparison_count++;
3336
return left < right;
3437
});
3538
++cnt;
3639
benchmark::DoNotOptimize(vec[arg]);
3740
}
38-
state.counters["Comparisons"] = 1.0 * cmp / cnt;
39-
}
40-
41-
template <class DataGen, class Impl>
42-
static void BM_sort_accesses(benchmark::State& state) {
43-
auto vec = DataGen::Gen(kSize);
44-
const size_t arg = state.range(0);
45-
size_t cnt = 0;
46-
size_t cmp = 0;
47-
miniselect::datagens::CountingIterator begin_v(&vec, 0, &cmp);
48-
miniselect::datagens::CountingIterator end_v(&vec, vec.size(), &cmp);
49-
for (auto _ : state) {
50-
Impl::Sort(begin_v, begin_v + arg, end_v);
51-
++cnt;
52-
benchmark::DoNotOptimize(vec[arg]);
53-
}
54-
state.counters["Array Accesses"] = 1.0 * cmp / cnt;
41+
state.counters["Array Accesses"] = 1.0 * access_count / cnt;
42+
state.counters["Comparisons"] = 1.0 * comparison_count / cnt;
5543
}
5644

5745
BENCH(BM_sort);
58-
BENCH(BM_sort_accesses);
5946

6047
} // namespace
6148
} // namespace miniselect

include/miniselect/floyd_rivest_select.h

+28-21
Original file line numberDiff line numberDiff line change
@@ -16,34 +16,43 @@
1616
namespace miniselect {
1717
namespace floyd_rivest_detail {
1818

19+
enum floyd_rivest_constants {
20+
kQCap = 600,
21+
};
22+
1923
template <class Compare>
2024
struct CompareRefType {
2125
// Pass the comparator by lvalue reference. Or in debug mode, using a
2226
// debugging wrapper that stores a reference.
2327
using type = typename std::add_lvalue_reference<Compare>::type;
2428
};
2529

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) {
2934
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+
3440
double z = log(n);
3541
double s = 0.5 * exp(2 * z / 3);
3642
double sd = 0.5 * sqrt(z * s * (n - s) / n);
3743
if (i < n / 2) {
3844
sd *= -1.0;
3945
}
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);
4452
}
45-
Diff i = left;
46-
Diff j = right;
53+
DiffType i = left;
54+
DiffType j = right;
55+
4756
std::swap(begin[left], begin[k]);
4857
const bool to_swap = comp(begin[left], begin[right]);
4958
if (to_swap) {
@@ -87,10 +96,9 @@ inline void floyd_rivest_partial_sort(Iter begin, Iter mid, Iter end,
8796
if (begin == end) return;
8897
if (begin == mid) return;
8998
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);
94102
// std::sort proved to be better than other sorts because of pivoting.
95103
std::sort<Iter, CompType>(begin, mid, comp);
96104
}
@@ -105,10 +113,9 @@ template <class Iter, class Compare>
105113
inline void floyd_rivest_select(Iter begin, Iter mid, Iter end, Compare comp) {
106114
if (mid == end) return;
107115
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);
112119
}
113120

114121
template <class Iter>

include/miniselect/median_of_3_random.h

+9-9
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,17 @@ namespace miniselect {
1717
namespace median_of_3_random_detail {
1818

1919
template <class Iter, class Compare>
20-
static inline Iter partition(Iter r, Iter end, Compare&& comp) {
21-
typedef typename std::iterator_traits<Iter>::difference_type T;
22-
const T len = end - r;
20+
inline Iter partition(Iter r, Iter end, Compare&& comp) {
21+
using DiffType = typename std::iterator_traits<Iter>::difference_type;
22+
const DiffType len = end - r;
2323
assert(len >= 3);
2424
static std::mt19937_64 gen(1);
25-
std::uniform_int_distribution<T> dis(0, len - 1);
26-
T x = dis(gen);
27-
T y = dis(gen);
28-
T z = dis(gen);
29-
return median_common_detail::pivotPartition(
30-
r, median_common_detail::medianIndex(r, x, y, z, comp), len, comp);
25+
std::uniform_int_distribution<DiffType> dis(0, len - 1);
26+
DiffType x = dis(gen);
27+
DiffType y = dis(gen);
28+
DiffType z = dis(gen);
29+
return median_common_detail::pivot_partition(
30+
r, median_common_detail::median_index(r, x, y, z, comp), len, comp);
3131
}
3232

3333
} // namespace median_of_3_random_detail

include/miniselect/median_of_medians.h

+9-8
Original file line numberDiff line numberDiff line change
@@ -16,20 +16,21 @@ namespace miniselect {
1616
namespace median_of_medians_detail {
1717

1818
template <class Iter, class Compare>
19-
static inline Iter partition(Iter r, Iter end, Compare&& comp) {
19+
inline Iter partition(Iter r, Iter end, Compare&& comp) {
2020
using CompType = typename median_common_detail::CompareRefType<Compare>::type;
21-
const size_t len = end - r;
21+
using DiffType = typename std::iterator_traits<Iter>::difference_type;
22+
const DiffType len = end - r;
2223
if (len < 5) {
23-
return median_common_detail::pivotPartition(r, len / 2, len, comp);
24+
return median_common_detail::pivot_partition(r, len / 2, len, comp);
2425
}
25-
size_t j = 0;
26-
for (size_t i = 4; i < len; i += 5, ++j) {
26+
DiffType j = 0;
27+
for (DiffType i = 4; i < len; i += 5, ++j) {
2728
median_common_detail::partition5(r, i - 4, i - 3, i, i - 2, i - 1, comp);
2829
std::swap(r[i], r[j]);
2930
}
3031
median_common_detail::quickselect<Iter, CompType, &partition>(r, r + j / 2,
3132
r + j, comp);
32-
return median_common_detail::pivotPartition(r, j / 2, len, comp);
33+
return median_common_detail::pivot_partition(r, j / 2, len, comp);
3334
}
3435

3536
} // namespace median_of_medians_detail
@@ -47,7 +48,7 @@ inline void median_of_medians_select(Iter begin, Iter mid, Iter end,
4748

4849
template <class Iter>
4950
inline void median_of_medians_select(Iter begin, Iter mid, Iter end) {
50-
typedef typename std::iterator_traits<Iter>::value_type T;
51+
using T = typename std::iterator_traits<Iter>::value_type;
5152
median_of_medians_select(begin, mid, end, std::less<T>());
5253
}
5354

@@ -64,7 +65,7 @@ inline void median_of_medians_partial_sort(Iter begin, Iter mid, Iter end,
6465

6566
template <class Iter>
6667
inline void median_of_medians_partial_sort(Iter begin, Iter mid, Iter end) {
67-
typedef typename std::iterator_traits<Iter>::value_type T;
68+
using T = typename std::iterator_traits<Iter>::value_type;
6869
median_of_medians_partial_sort(begin, mid, end, std::less<T>());
6970
}
7071

0 commit comments

Comments
 (0)