-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbitonic_sort.cpp
More file actions
130 lines (104 loc) · 3.1 KB
/
Copy pathbitonic_sort.cpp
File metadata and controls
130 lines (104 loc) · 3.1 KB
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
#include <algorithm>
#include <vector>
#include <iostream>
#include <type_traits>
#include <cassert>
#include <cstdlib>
#ifdef NPARALLEL
#define cilk_for for
#define cilk_spawn
#define cilk_sync
#define bitonic_sort serial_bitonic_sort
#else
#include <cilk/cilk.h>
#define bitonic_sort parallel_bitonic_sort
#endif
template <class RandomIt, class Compare>
void serial_bitonic_sort(RandomIt first, RandomIt last, Compare comp) {
const auto len = std::distance(first, last);
if (len <= 1) {
return;
}
const auto half_len = len / 2;
const auto mid = first + half_len;
using difference_type = typename std::iterator_traits<RandomIt>::difference_type;
for (difference_type i{}; i < half_len; ++i) {
const auto left = first + i;
const auto right = mid + i;
if (comp(*right, *left)) {
std::iter_swap(left, right);
}
}
serial_bitonic_sort(first, mid, comp);
serial_bitonic_sort(mid, last, comp);
}
template <class RandomIt, class Compare>
void parallel_bitonic_sort(RandomIt first, RandomIt last, Compare comp) {
const auto len = std::distance(first, last);
if (len <= 4194304) {
return serial_bitonic_sort(first, last, comp);
}
const auto half_len = len / 2;
const auto mid = first + half_len;
using difference_type = typename std::iterator_traits<RandomIt>::difference_type;
for (difference_type i{}; i < half_len; ++i) {
const auto left = first + i;
const auto right = mid + i;
if (comp(*right, *left)) {
std::iter_swap(left, right);
}
}
cilk_spawn parallel_bitonic_sort(first, mid, comp);
parallel_bitonic_sort(mid, last, comp);
cilk_sync;
}
template <class RandomIt>
auto bitonic_sort(RandomIt first, RandomIt last) {
return bitonic_sort(first, last, std::less<typename std::iterator_traits<RandomIt>::value_type>{});
}
template <class RandomIt, class Compare>
bool sorted(RandomIt first, RandomIt last, Compare comp) {
for (auto it1 = first, it2 = first + 1; it2 != last; ++it1, ++it2){
if (comp(*it2, *it1)) {
return false;
}
}
return true;
}
template <class RandomIt>
auto sorted(RandomIt first, RandomIt last) {
return sorted(first, last, std::less<typename std::iterator_traits<RandomIt>::value_type>{});
}
std::vector<int> make_bitonic_sequence(size_t n) {
std::vector<int> vec(n);
const auto switch_point = n / 2 - (n > 8 ? n / 10 : 0);
for (size_t i = 0; i < switch_point; ++i) {
vec[i] = 2 * i;
}
for (size_t i = switch_point; i < n; ++i) {
vec[i] = 2 * (2 * switch_point - i - 1) - 1;
}
return vec;
}
template <typename T>
void print_seq(T a) {
for (int i : a) {
std::cout << i << " ";
}
std::cout << std::endl;
}
int main(int argc, char *argv[]) {
const int n = (argc > 1) ? atoi(argv[1]) : 256;
std::vector<int> a = make_bitonic_sequence(n);
if (a.size() <= 256) {
print_seq(a);
}
// length must be a power of 2
assert((a.size() > 0) && ((a.size() & (a.size() - 1)) == 0));
bitonic_sort(a.begin(), a.end());
if (a.size() <= 256) {
print_seq(a);
}
std::cout << (sorted(a.begin(), a.end()) ? "Sorted!" : "Not Sorted!") << std::endl;
return 0;
}