| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #include "yushkova_p_hoare_sorting_simple_merging/tbb/include/ops_tbb.hpp" | ||
| 2 | |||
| 3 | #include <oneapi/tbb/blocked_range.h> | ||
| 4 | #include <oneapi/tbb/parallel_for.h> | ||
| 5 | |||
| 6 | #include <algorithm> | ||
| 7 | #include <cstddef> | ||
| 8 | #include <utility> | ||
| 9 | #include <vector> | ||
| 10 | |||
| 11 | #include "yushkova_p_hoare_sorting_simple_merging/common/include/common.hpp" | ||
| 12 | |||
| 13 | namespace yushkova_p_hoare_sorting_simple_merging { | ||
| 14 | |||
| 15 | namespace { | ||
| 16 | constexpr size_t kBlockSize = 64; | ||
| 17 | } // namespace | ||
| 18 | |||
| 19 |
1/2✓ Branch 1 taken 68 times.
✗ Branch 2 not taken.
|
68 | YushkovaPHoareSortingSimpleMergingTBB::YushkovaPHoareSortingSimpleMergingTBB(const InType &in) { |
| 20 | SetTypeOfTask(GetStaticTypeOfTask()); | ||
| 21 |
1/2✓ Branch 1 taken 68 times.
✗ Branch 2 not taken.
|
68 | GetInput() = in; |
| 22 | GetOutput() = {}; | ||
| 23 | 68 | } | |
| 24 | |||
| 25 | 2736 | int YushkovaPHoareSortingSimpleMergingTBB::HoarePartition(std::vector<int> &values, int left, int right) { | |
| 26 | 2736 | const int pivot = values[left + ((right - left) / 2)]; | |
| 27 | 2736 | int i = left - 1; | |
| 28 | 2736 | int j = right + 1; | |
| 29 | |||
| 30 | while (true) { | ||
| 31 | 5420 | ++i; | |
| 32 |
2/2✓ Branch 0 taken 3692 times.
✓ Branch 1 taken 5420 times.
|
9112 | while (values[i] < pivot) { |
| 33 | 3692 | ++i; | |
| 34 | } | ||
| 35 | |||
| 36 | 5420 | --j; | |
| 37 |
2/2✓ Branch 0 taken 5264 times.
✓ Branch 1 taken 5420 times.
|
10684 | while (values[j] > pivot) { |
| 38 | 5264 | --j; | |
| 39 | } | ||
| 40 | |||
| 41 |
2/2✓ Branch 0 taken 2736 times.
✓ Branch 1 taken 2684 times.
|
5420 | if (i >= j) { |
| 42 | 2736 | return j; | |
| 43 | } | ||
| 44 | |||
| 45 | std::swap(values[i], values[j]); | ||
| 46 | } | ||
| 47 | } | ||
| 48 | |||
| 49 | 80 | void YushkovaPHoareSortingSimpleMergingTBB::HoareQuickSort(std::vector<int> &values, int left, int right) { | |
| 50 |
3/6✓ Branch 0 taken 80 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 80 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 80 times.
|
80 | if (left >= right || static_cast<size_t>(left) >= values.size() || static_cast<size_t>(right) >= values.size()) { |
| 51 | ✗ | return; | |
| 52 | } | ||
| 53 | |||
| 54 | 80 | std::vector<std::pair<int, int>> stack; | |
| 55 |
1/2✓ Branch 1 taken 80 times.
✗ Branch 2 not taken.
|
80 | stack.emplace_back(left, right); |
| 56 | |||
| 57 |
2/2✓ Branch 0 taken 5552 times.
✓ Branch 1 taken 80 times.
|
5632 | while (!stack.empty()) { |
| 58 | auto [current_left, current_right] = stack.back(); | ||
| 59 | stack.pop_back(); | ||
| 60 | |||
| 61 |
2/2✓ Branch 0 taken 2816 times.
✓ Branch 1 taken 2736 times.
|
5552 | if (current_left >= current_right) { |
| 62 | 2816 | continue; | |
| 63 | } | ||
| 64 | |||
| 65 |
2/4✓ Branch 0 taken 2736 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2736 times.
✗ Branch 3 not taken.
|
2736 | if (current_left < 0 || static_cast<size_t>(current_right) >= values.size()) { |
| 66 | ✗ | continue; | |
| 67 | } | ||
| 68 | |||
| 69 | 2736 | const int partition_index = HoarePartition(values, current_left, current_right); | |
| 70 |
2/4✓ Branch 0 taken 2736 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2736 times.
|
2736 | if (partition_index < current_left || partition_index > current_right) { |
| 71 | ✗ | continue; | |
| 72 | } | ||
| 73 | |||
| 74 |
2/2✓ Branch 0 taken 240 times.
✓ Branch 1 taken 2496 times.
|
2736 | if ((partition_index - current_left) > (current_right - (partition_index + 1))) { |
| 75 |
1/2✓ Branch 1 taken 240 times.
✗ Branch 2 not taken.
|
240 | stack.emplace_back(current_left, partition_index); |
| 76 |
1/2✓ Branch 1 taken 240 times.
✗ Branch 2 not taken.
|
240 | stack.emplace_back(partition_index + 1, current_right); |
| 77 | } else { | ||
| 78 |
1/4✓ Branch 1 taken 2496 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
2496 | stack.emplace_back(partition_index + 1, current_right); |
| 79 |
1/2✓ Branch 1 taken 2496 times.
✗ Branch 2 not taken.
|
2496 | stack.emplace_back(current_left, partition_index); |
| 80 | } | ||
| 81 | } | ||
| 82 | } | ||
| 83 | |||
| 84 | 24 | void YushkovaPHoareSortingSimpleMergingTBB::SimpleMerge(const std::vector<int> &source, std::vector<int> &destination, | |
| 85 | size_t left, size_t middle, size_t right) { | ||
| 86 |
2/4✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 24 times.
✗ Branch 3 not taken.
|
24 | if (left >= right || middle > right || left >= middle) { |
| 87 | return; | ||
| 88 | } | ||
| 89 | |||
| 90 | size_t left_index = left; | ||
| 91 | size_t right_index = middle; | ||
| 92 | size_t destination_index = left; | ||
| 93 | |||
| 94 |
2/2✓ Branch 0 taken 1480 times.
✓ Branch 1 taken 24 times.
|
1504 | while (left_index < middle && right_index < right) { |
| 95 |
2/2✓ Branch 0 taken 736 times.
✓ Branch 1 taken 744 times.
|
1480 | if (source[left_index] <= source[right_index]) { |
| 96 | 736 | destination[destination_index++] = source[left_index++]; | |
| 97 | } else { | ||
| 98 | 744 | destination[destination_index++] = source[right_index++]; | |
| 99 | } | ||
| 100 | } | ||
| 101 | |||
| 102 |
2/2✓ Branch 0 taken 1312 times.
✓ Branch 1 taken 24 times.
|
1336 | while (left_index < middle) { |
| 103 | 1312 | destination[destination_index++] = source[left_index++]; | |
| 104 | } | ||
| 105 | |||
| 106 |
2/2✓ Branch 0 taken 40 times.
✓ Branch 1 taken 24 times.
|
64 | while (right_index < right) { |
| 107 | 40 | destination[destination_index++] = source[right_index++]; | |
| 108 | } | ||
| 109 | } | ||
| 110 | |||
| 111 | 88 | void YushkovaPHoareSortingSimpleMergingTBB::SortBlockIfNeeded(std::vector<int> &data, size_t size, size_t block_index) { | |
| 112 | 88 | const size_t block_start = block_index * kBlockSize; | |
| 113 |
2/2✓ Branch 0 taken 80 times.
✓ Branch 1 taken 8 times.
|
88 | const size_t block_end = std::min(block_start + kBlockSize, size); |
| 114 |
4/6✓ Branch 0 taken 80 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 80 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 80 times.
✗ Branch 5 not taken.
|
88 | if (block_end > block_start + 1U && block_end <= size && block_start < size) { |
| 115 | 80 | HoareQuickSort(data, static_cast<int>(block_start), static_cast<int>(block_end - 1U)); | |
| 116 | } | ||
| 117 | 88 | } | |
| 118 | |||
| 119 | 64 | void YushkovaPHoareSortingSimpleMergingTBB::SortBlocks(std::vector<int> &data, size_t size) { | |
| 120 | 64 | const size_t block_count = (size + kBlockSize - 1U) / kBlockSize; | |
| 121 | 64 | oneapi::tbb::parallel_for(oneapi::tbb::blocked_range<size_t>(0U, block_count), | |
| 122 | 64 | [&data, size](const oneapi::tbb::blocked_range<size_t> &range) { | |
| 123 |
2/4✓ Branch 0 taken 88 times.
✓ Branch 1 taken 88 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
176 | for (size_t block_index = range.begin(); block_index != range.end(); ++block_index) { |
| 124 |
0/2✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
88 | SortBlockIfNeeded(data, size, block_index); |
| 125 | } | ||
| 126 | }); | ||
| 127 | 64 | } | |
| 128 | |||
| 129 | 32 | void YushkovaPHoareSortingSimpleMergingTBB::MergeChunk(const std::vector<int> &source, std::vector<int> &destination, | |
| 130 | size_t size, size_t merge_width, size_t merge_index) { | ||
| 131 | 32 | const size_t left = merge_index * 2U * merge_width; | |
| 132 |
1/2✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
|
32 | const size_t middle = std::min(left + merge_width, size); |
| 133 | 32 | const size_t right = std::min(left + (2U * merge_width), size); | |
| 134 | |||
| 135 |
1/2✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
|
32 | if (left >= size) { |
| 136 | return; | ||
| 137 | } | ||
| 138 | |||
| 139 |
2/2✓ Branch 0 taken 24 times.
✓ Branch 1 taken 8 times.
|
32 | if (middle < right) { |
| 140 | 24 | SimpleMerge(source, destination, left, middle, right); | |
| 141 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | } else if (left < right) { |
| 142 |
2/2✓ Branch 0 taken 12 times.
✓ Branch 1 taken 8 times.
|
20 | for (size_t i = left; i < right; ++i) { |
| 143 | 12 | destination[i] = source[i]; | |
| 144 | } | ||
| 145 | } | ||
| 146 | } | ||
| 147 | |||
| 148 | 24 | void YushkovaPHoareSortingSimpleMergingTBB::MergePass(std::vector<int> &data, size_t size, size_t merge_width) { | |
| 149 | 24 | std::vector<int> merged_data(size); | |
| 150 | 24 | const size_t merge_count = (size + (2U * merge_width) - 1U) / (2U * merge_width); | |
| 151 | |||
| 152 | 24 | oneapi::tbb::parallel_for(oneapi::tbb::blocked_range<size_t>(0U, merge_count), | |
| 153 |
2/6✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 24 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
56 | [&data, size, merge_width, &merged_data](const oneapi::tbb::blocked_range<size_t> &range) { |
| 154 |
2/2✓ Branch 0 taken 32 times.
✓ Branch 1 taken 32 times.
|
64 | for (size_t merge_index = range.begin(); merge_index != range.end(); ++merge_index) { |
| 155 | 32 | MergeChunk(data, merged_data, size, merge_width, merge_index); | |
| 156 | } | ||
| 157 | 32 | }); | |
| 158 | |||
| 159 | data.swap(merged_data); | ||
| 160 | 24 | } | |
| 161 | |||
| 162 | 68 | bool YushkovaPHoareSortingSimpleMergingTBB::ValidationImpl() { | |
| 163 | 68 | return !GetInput().empty(); | |
| 164 | } | ||
| 165 | |||
| 166 | 68 | bool YushkovaPHoareSortingSimpleMergingTBB::PreProcessingImpl() { | |
| 167 | 68 | data_ = GetInput(); | |
| 168 | GetOutput().clear(); | ||
| 169 | 68 | return true; | |
| 170 | } | ||
| 171 | |||
| 172 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 68 times.
|
68 | bool YushkovaPHoareSortingSimpleMergingTBB::RunImpl() { |
| 173 | const size_t size = data_.size(); | ||
| 174 | |||
| 175 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 68 times.
|
68 | if (size == 0) { |
| 176 | GetOutput().clear(); | ||
| 177 | ✗ | return true; | |
| 178 | } | ||
| 179 | |||
| 180 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 64 times.
|
68 | if (size == 1) { |
| 181 | GetOutput().assign(1, data_[0]); | ||
| 182 | 4 | return true; | |
| 183 | } | ||
| 184 | |||
| 185 | 64 | SortBlocks(data_, size); | |
| 186 |
2/2✓ Branch 0 taken 24 times.
✓ Branch 1 taken 64 times.
|
88 | for (size_t merge_width = kBlockSize; merge_width < size; merge_width *= 2) { |
| 187 | 24 | MergePass(data_, size, merge_width); | |
| 188 | } | ||
| 189 | |||
| 190 |
1/2✓ Branch 0 taken 64 times.
✗ Branch 1 not taken.
|
64 | if (std::ranges::is_sorted(data_)) { |
| 191 | 64 | GetOutput() = data_; | |
| 192 | 64 | return true; | |
| 193 | } | ||
| 194 | |||
| 195 | return false; | ||
| 196 | } | ||
| 197 | |||
| 198 |
1/2✓ Branch 0 taken 68 times.
✗ Branch 1 not taken.
|
68 | bool YushkovaPHoareSortingSimpleMergingTBB::PostProcessingImpl() { |
| 199 |
1/2✓ Branch 0 taken 68 times.
✗ Branch 1 not taken.
|
68 | if (GetOutput().empty()) { |
| 200 | return false; | ||
| 201 | } | ||
| 202 | return std::ranges::is_sorted(GetOutput()); | ||
| 203 | } | ||
| 204 | |||
| 205 | } // namespace yushkova_p_hoare_sorting_simple_merging | ||
| 206 |