| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #include "morozova_s_connected_components/mpi/include/ops_mpi.hpp" | ||
| 2 | |||
| 3 | #include <mpi.h> | ||
| 4 | |||
| 5 | #include <algorithm> | ||
| 6 | #include <array> | ||
| 7 | #include <cstddef> | ||
| 8 | #include <queue> | ||
| 9 | #include <unordered_map> | ||
| 10 | #include <utility> | ||
| 11 | #include <vector> | ||
| 12 | |||
| 13 | #include "morozova_s_connected_components/common/include/common.hpp" | ||
| 14 | |||
| 15 | namespace morozova_s_connected_components { | ||
| 16 | |||
| 17 | namespace { | ||
| 18 | constexpr int kLabelOffset = 1000000; | ||
| 19 | constexpr int kTagLocal = 0; | ||
| 20 | constexpr int kTagFinal = 1; | ||
| 21 | |||
| 22 | constexpr std::array<std::pair<int, int>, 8> kShifts = { | ||
| 23 | {{-1, -1}, {-1, 0}, {-1, 1}, {0, -1}, {0, 1}, {1, -1}, {1, 0}, {1, 1}}}; | ||
| 24 | } // namespace | ||
| 25 | |||
| 26 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
8 | MorozovaSConnectedComponentsMPI::MorozovaSConnectedComponentsMPI(const InType &in) { |
| 27 | SetTypeOfTask(GetStaticTypeOfTask()); | ||
| 28 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
8 | GetInput() = in; |
| 29 | GetOutput() = {}; | ||
| 30 | 8 | } | |
| 31 | |||
| 32 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
|
8 | bool MorozovaSConnectedComponentsMPI::ValidationImpl() { |
| 33 | const auto &input = GetInput(); | ||
| 34 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
|
8 | if (input.empty()) { |
| 35 | return true; | ||
| 36 | } | ||
| 37 | const size_t cols = input.front().size(); | ||
| 38 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 72 times.
|
80 | for (const auto &row : input) { |
| 39 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
|
72 | if (row.size() != cols) { |
| 40 | return false; | ||
| 41 | } | ||
| 42 |
2/2✓ Branch 0 taken 688 times.
✓ Branch 1 taken 72 times.
|
760 | for (int v : row) { |
| 43 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 688 times.
|
688 | if (v != 0 && v != 1) { |
| 44 | return false; | ||
| 45 | } | ||
| 46 | } | ||
| 47 | } | ||
| 48 | return true; | ||
| 49 | } | ||
| 50 | |||
| 51 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
|
8 | bool MorozovaSConnectedComponentsMPI::PreProcessingImpl() { |
| 52 | 8 | rows_ = static_cast<int>(GetInput().size()); | |
| 53 | |||
| 54 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
|
8 | if (rows_ == 0) { |
| 55 | ✗ | cols_ = 0; | |
| 56 | GetOutput().clear(); | ||
| 57 | ✗ | return true; | |
| 58 | } | ||
| 59 | |||
| 60 | 8 | cols_ = static_cast<int>(GetInput().front().size()); | |
| 61 | |||
| 62 | auto &output = GetOutput(); | ||
| 63 | 8 | output.resize(rows_); | |
| 64 |
2/2✓ Branch 0 taken 72 times.
✓ Branch 1 taken 8 times.
|
80 | for (int i = 0; i < rows_; ++i) { |
| 65 | 72 | output[i].assign(cols_, 0); | |
| 66 | } | ||
| 67 | |||
| 68 | return true; | ||
| 69 | } | ||
| 70 | |||
| 71 | 8 | void MorozovaSConnectedComponentsMPI::InitMPI() { | |
| 72 | 8 | MPI_Comm_rank(MPI_COMM_WORLD, &rank_); | |
| 73 | 8 | MPI_Comm_size(MPI_COMM_WORLD, &size_); | |
| 74 | 8 | rows_per_proc_ = rows_ / size_; | |
| 75 | 8 | remainder_ = rows_ % size_; | |
| 76 | 8 | } | |
| 77 | |||
| 78 | ✗ | std::pair<int, int> MorozovaSConnectedComponentsMPI::ComputeRowRange() const { | |
| 79 |
1/4✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
8 | const int start = (rank_ * rows_per_proc_) + std::min(rank_, remainder_); |
| 80 |
1/4✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
8 | const int end = start + rows_per_proc_ + (rank_ < remainder_ ? 1 : 0); |
| 81 | ✗ | return {start, end}; | |
| 82 | } | ||
| 83 | |||
| 84 | 156 | std::vector<std::pair<int, int>> MorozovaSConnectedComponentsMPI::GetNeighbors(int row, int col) { | |
| 85 | 156 | std::vector<std::pair<int, int>> neighbors; | |
| 86 | const auto &input = GetInput(); | ||
| 87 |
2/2✓ Branch 0 taken 1248 times.
✓ Branch 1 taken 156 times.
|
1404 | for (const auto &[dr, dc] : kShifts) { |
| 88 | 1248 | const int nr = row + dr; | |
| 89 | 1248 | const int nc = col + dc; | |
| 90 |
10/10✓ Branch 0 taken 1206 times.
✓ Branch 1 taken 42 times.
✓ Branch 2 taken 1146 times.
✓ Branch 3 taken 60 times.
✓ Branch 4 taken 1108 times.
✓ Branch 5 taken 38 times.
✓ Branch 6 taken 1053 times.
✓ Branch 7 taken 55 times.
✓ Branch 8 taken 456 times.
✓ Branch 9 taken 597 times.
|
1248 | if (nr >= 0 && nr < rows_ && nc >= 0 && nc < cols_ && input[nr][nc] == 1) { |
| 91 |
1/2✓ Branch 1 taken 456 times.
✗ Branch 2 not taken.
|
456 | neighbors.emplace_back(nr, nc); |
| 92 | } | ||
| 93 | } | ||
| 94 | 156 | return neighbors; | |
| 95 | } | ||
| 96 | |||
| 97 | 42 | void MorozovaSConnectedComponentsMPI::FloodFill(int row, int col, int label) { | |
| 98 | auto &output = GetOutput(); | ||
| 99 | std::queue<std::pair<int, int>> q; | ||
| 100 | q.emplace(row, col); | ||
| 101 | 42 | output[row][col] = label; | |
| 102 |
2/2✓ Branch 0 taken 156 times.
✓ Branch 1 taken 42 times.
|
198 | while (!q.empty()) { |
| 103 | const auto [r, c] = q.front(); | ||
| 104 | q.pop(); | ||
| 105 |
3/4✓ Branch 1 taken 156 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 456 times.
✓ Branch 4 taken 156 times.
|
612 | for (const auto &[nr, nc] : GetNeighbors(r, c)) { |
| 106 |
2/2✓ Branch 0 taken 114 times.
✓ Branch 1 taken 342 times.
|
456 | if (output[nr][nc] == 0) { |
| 107 |
1/2✓ Branch 1 taken 114 times.
✗ Branch 2 not taken.
|
114 | output[nr][nc] = label; |
| 108 | q.emplace(nr, nc); | ||
| 109 | } | ||
| 110 | } | ||
| 111 | } | ||
| 112 | 42 | } | |
| 113 | |||
| 114 | 8 | void MorozovaSConnectedComponentsMPI::ComputeLocalComponents(int start_row, int end_row, int base_label) { | |
| 115 | const auto &input = GetInput(); | ||
| 116 | auto &output = GetOutput(); | ||
| 117 | int local_label = 1; | ||
| 118 |
2/2✓ Branch 0 taken 36 times.
✓ Branch 1 taken 8 times.
|
44 | for (int i = start_row; i < end_row; ++i) { |
| 119 |
2/2✓ Branch 0 taken 344 times.
✓ Branch 1 taken 36 times.
|
380 | for (int j = 0; j < cols_; ++j) { |
| 120 |
4/4✓ Branch 0 taken 96 times.
✓ Branch 1 taken 248 times.
✓ Branch 2 taken 42 times.
✓ Branch 3 taken 54 times.
|
344 | if (input[i][j] == 1 && output[i][j] == 0) { |
| 121 | 42 | FloodFill(i, j, base_label + local_label); | |
| 122 | 42 | ++local_label; | |
| 123 | } | ||
| 124 | } | ||
| 125 | } | ||
| 126 | 8 | } | |
| 127 | |||
| 128 | 4 | void MorozovaSConnectedComponentsMPI::GatherLocalResults() { | |
| 129 | auto &output = GetOutput(); | ||
| 130 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
|
8 | for (int proc = 1; proc < size_; ++proc) { |
| 131 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | const int ps = (proc * rows_per_proc_) + std::min(proc, remainder_); |
| 132 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | const int pe = ps + rows_per_proc_ + (proc < remainder_ ? 1 : 0); |
| 133 | 4 | const int pr = pe - ps; | |
| 134 |
1/2✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
4 | std::vector<int> buf(static_cast<size_t>(pr) * static_cast<size_t>(cols_)); |
| 135 | MPI_Status status; | ||
| 136 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | MPI_Recv(buf.data(), static_cast<int>(buf.size()), MPI_INT, proc, kTagLocal, MPI_COMM_WORLD, &status); |
| 137 | 4 | int count = 0; | |
| 138 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | MPI_Get_count(&status, MPI_INT, &count); |
| 139 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | if (static_cast<size_t>(count) != buf.size()) { |
| 140 | return; | ||
| 141 | } | ||
| 142 |
2/2✓ Branch 0 taken 18 times.
✓ Branch 1 taken 4 times.
|
22 | for (int i = 0; i < pr; ++i) { |
| 143 | 18 | const ptrdiff_t offset = static_cast<ptrdiff_t>(i) * static_cast<ptrdiff_t>(cols_); | |
| 144 | 18 | std::copy(buf.begin() + offset, buf.begin() + offset + cols_, output[ps + i].begin()); | |
| 145 | } | ||
| 146 | } | ||
| 147 | } | ||
| 148 | |||
| 149 | 108 | bool MorozovaSConnectedComponentsMPI::TryProcessBoundaryCell(int proc, int j, int dj, | |
| 150 | std::unordered_map<int, int> &parent) { | ||
| 151 | const auto &input = GetInput(); | ||
| 152 | const auto &output = GetOutput(); | ||
| 153 |
1/2✓ Branch 0 taken 108 times.
✗ Branch 1 not taken.
|
108 | const int br = (proc * rows_per_proc_) + std::min(proc, remainder_); |
| 154 | |||
| 155 |
2/4✓ Branch 0 taken 108 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 108 times.
|
108 | if (br <= 0 || br >= rows_) { |
| 156 | return false; | ||
| 157 | } | ||
| 158 | |||
| 159 | 108 | const int nj = j + dj; | |
| 160 |
4/4✓ Branch 0 taken 4 times.
✓ Branch 1 taken 104 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 100 times.
|
108 | if (nj < 0 || nj >= cols_) { |
| 161 | return false; | ||
| 162 | } | ||
| 163 | |||
| 164 |
4/4✓ Branch 0 taken 61 times.
✓ Branch 1 taken 39 times.
✓ Branch 2 taken 21 times.
✓ Branch 3 taken 18 times.
|
100 | if (input[br - 1][j] != 1 || input[br][nj] != 1) { |
| 165 | return false; | ||
| 166 | } | ||
| 167 | |||
| 168 | 18 | const int a = output[br - 1][j]; | |
| 169 | 18 | const int b = output[br][nj]; | |
| 170 | |||
| 171 |
3/6✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 18 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 18 times.
|
18 | if (a == 0 || b == 0 || a == b) { |
| 172 | return false; | ||
| 173 | } | ||
| 174 | |||
| 175 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
|
18 | int root_a = a; |
| 176 | auto it = parent.find(a); | ||
| 177 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
|
18 | if (it != parent.end()) { |
| 178 | ✗ | root_a = it->second; | |
| 179 | } | ||
| 180 | |||
| 181 |
2/2✓ Branch 0 taken 15 times.
✓ Branch 1 taken 3 times.
|
18 | int root_b = b; |
| 182 | it = parent.find(b); | ||
| 183 |
2/2✓ Branch 0 taken 15 times.
✓ Branch 1 taken 3 times.
|
18 | if (it != parent.end()) { |
| 184 | 15 | root_b = it->second; | |
| 185 | } | ||
| 186 | |||
| 187 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 15 times.
|
18 | if (root_a != root_b) { |
| 188 | 3 | parent[std::max(root_a, root_b)] = std::min(root_a, root_b); | |
| 189 | } | ||
| 190 | |||
| 191 | return true; | ||
| 192 | } | ||
| 193 | |||
| 194 | 96 | int MorozovaSConnectedComponentsMPI::FindRoot(std::unordered_map<int, int> &parent, int v) { | |
| 195 | 96 | int root = v; | |
| 196 | 96 | std::vector<int> path; | |
| 197 |
3/4✓ Branch 0 taken 31 times.
✓ Branch 1 taken 96 times.
✓ Branch 2 taken 31 times.
✗ Branch 3 not taken.
|
158 | while (parent.contains(root) && parent[root] != root) { |
| 198 | path.push_back(root); | ||
| 199 | 31 | root = parent[root]; | |
| 200 | } | ||
| 201 |
2/2✓ Branch 0 taken 31 times.
✓ Branch 1 taken 96 times.
|
127 | for (int node : path) { |
| 202 |
1/2✓ Branch 1 taken 31 times.
✗ Branch 2 not taken.
|
31 | parent[node] = root; |
| 203 | } | ||
| 204 |
2/2✓ Branch 0 taken 31 times.
✓ Branch 1 taken 65 times.
|
127 | return root; |
| 205 | } | ||
| 206 | |||
| 207 | 4 | void MorozovaSConnectedComponentsMPI::MergeBoundaries() { | |
| 208 | auto &output = GetOutput(); | ||
| 209 | std::unordered_map<int, int> parent; | ||
| 210 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
|
8 | for (int proc = 1; proc < size_; ++proc) { |
| 211 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | const int br = (proc * rows_per_proc_) + std::min(proc, remainder_); |
| 212 |
2/4✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
4 | if (br <= 0 || br >= rows_) { |
| 213 | ✗ | continue; | |
| 214 | } | ||
| 215 |
2/2✓ Branch 0 taken 36 times.
✓ Branch 1 taken 4 times.
|
40 | for (int j = 0; j < cols_; ++j) { |
| 216 |
1/2✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
|
36 | TryProcessBoundaryCell(proc, j, -1, parent); |
| 217 |
1/2✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
|
36 | TryProcessBoundaryCell(proc, j, 0, parent); |
| 218 |
1/2✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
|
36 | TryProcessBoundaryCell(proc, j, 1, parent); |
| 219 | } | ||
| 220 | } | ||
| 221 |
2/2✓ Branch 0 taken 36 times.
✓ Branch 1 taken 4 times.
|
40 | for (int i = 0; i < rows_; ++i) { |
| 222 |
2/2✓ Branch 0 taken 344 times.
✓ Branch 1 taken 36 times.
|
380 | for (int j = 0; j < cols_; ++j) { |
| 223 |
2/2✓ Branch 0 taken 96 times.
✓ Branch 1 taken 248 times.
|
344 | int &v = output[i][j]; |
| 224 |
2/2✓ Branch 0 taken 96 times.
✓ Branch 1 taken 248 times.
|
344 | if (v > 0) { |
| 225 |
1/2✓ Branch 1 taken 96 times.
✗ Branch 2 not taken.
|
96 | v = FindRoot(parent, v); |
| 226 | } | ||
| 227 | } | ||
| 228 | } | ||
| 229 | 4 | } | |
| 230 | |||
| 231 | 4 | void MorozovaSConnectedComponentsMPI::NormalizeLabels() { | |
| 232 | auto &output = GetOutput(); | ||
| 233 | std::unordered_map<int, int> remap; | ||
| 234 | int next = 1; | ||
| 235 |
2/2✓ Branch 0 taken 36 times.
✓ Branch 1 taken 4 times.
|
40 | for (auto &row : output) { |
| 236 |
2/2✓ Branch 0 taken 344 times.
✓ Branch 1 taken 36 times.
|
380 | for (int &v : row) { |
| 237 |
2/2✓ Branch 0 taken 248 times.
✓ Branch 1 taken 96 times.
|
344 | if (v > 0) { |
| 238 | auto it = remap.find(v); | ||
| 239 |
2/2✓ Branch 0 taken 39 times.
✓ Branch 1 taken 57 times.
|
96 | if (it == remap.end()) { |
| 240 |
2/4✓ Branch 1 taken 39 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 39 times.
✗ Branch 5 not taken.
|
39 | remap[v] = next++; |
| 241 | 39 | v = remap[v]; | |
| 242 | } else { | ||
| 243 | 57 | v = it->second; | |
| 244 | } | ||
| 245 | } | ||
| 246 | } | ||
| 247 | } | ||
| 248 | 4 | } | |
| 249 | |||
| 250 | 4 | void MorozovaSConnectedComponentsMPI::BroadcastResult() { | |
| 251 | auto &output = GetOutput(); | ||
| 252 | 4 | std::vector<int> flat(static_cast<size_t>(rows_) * static_cast<size_t>(cols_)); | |
| 253 |
2/2✓ Branch 0 taken 36 times.
✓ Branch 1 taken 4 times.
|
40 | for (int i = 0; i < rows_; ++i) { |
| 254 | 36 | const ptrdiff_t offset = static_cast<ptrdiff_t>(i) * static_cast<ptrdiff_t>(cols_); | |
| 255 | 36 | std::copy(output[i].begin(), output[i].end(), flat.begin() + offset); | |
| 256 | } | ||
| 257 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
|
8 | for (int proc = 1; proc < size_; ++proc) { |
| 258 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | MPI_Send(flat.data(), static_cast<int>(flat.size()), MPI_INT, proc, kTagFinal, MPI_COMM_WORLD); |
| 259 | } | ||
| 260 | 4 | } | |
| 261 | |||
| 262 | 4 | void MorozovaSConnectedComponentsMPI::SendLocalResult(int start_row, int end_row) { | |
| 263 | const auto &output = GetOutput(); | ||
| 264 | 4 | const int lr = end_row - start_row; | |
| 265 | 4 | std::vector<int> send(static_cast<size_t>(lr) * static_cast<size_t>(cols_)); | |
| 266 |
2/2✓ Branch 0 taken 18 times.
✓ Branch 1 taken 4 times.
|
22 | for (int i = 0; i < lr; ++i) { |
| 267 | 18 | const ptrdiff_t offset = static_cast<ptrdiff_t>(i) * static_cast<ptrdiff_t>(cols_); | |
| 268 | 18 | std::copy(output[start_row + i].begin(), output[start_row + i].end(), send.begin() + offset); | |
| 269 | } | ||
| 270 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | MPI_Send(send.data(), static_cast<int>(send.size()), MPI_INT, 0, kTagLocal, MPI_COMM_WORLD); |
| 271 | 4 | } | |
| 272 | |||
| 273 | 4 | void MorozovaSConnectedComponentsMPI::ReceiveFinalResult() { | |
| 274 | auto &output = GetOutput(); | ||
| 275 |
1/2✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
4 | std::vector<int> recv(static_cast<size_t>(rows_) * static_cast<size_t>(cols_)); |
| 276 | MPI_Status status; | ||
| 277 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | MPI_Recv(recv.data(), static_cast<int>(recv.size()), MPI_INT, 0, kTagFinal, MPI_COMM_WORLD, &status); |
| 278 | 4 | int count = 0; | |
| 279 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | MPI_Get_count(&status, MPI_INT, &count); |
| 280 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | if (static_cast<size_t>(count) != recv.size()) { |
| 281 | return; | ||
| 282 | } | ||
| 283 |
2/2✓ Branch 0 taken 36 times.
✓ Branch 1 taken 4 times.
|
40 | for (int i = 0; i < rows_; ++i) { |
| 284 | 36 | const ptrdiff_t offset = static_cast<ptrdiff_t>(i) * static_cast<ptrdiff_t>(cols_); | |
| 285 | 36 | std::copy(recv.begin() + offset, recv.begin() + offset + cols_, output[i].begin()); | |
| 286 | } | ||
| 287 | } | ||
| 288 | |||
| 289 | 8 | bool MorozovaSConnectedComponentsMPI::RunImpl() { | |
| 290 | 8 | InitMPI(); | |
| 291 |
2/4✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
|
8 | if (rows_ == 0 || cols_ == 0) { |
| 292 | return true; | ||
| 293 | } | ||
| 294 | const auto [start, end] = ComputeRowRange(); | ||
| 295 | 8 | ComputeLocalComponents(start, end, rank_ * kLabelOffset); | |
| 296 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
|
8 | if (rank_ == 0) { |
| 297 | 4 | GatherLocalResults(); | |
| 298 | 4 | MergeBoundaries(); | |
| 299 | 4 | NormalizeLabels(); | |
| 300 | 4 | BroadcastResult(); | |
| 301 | } else { | ||
| 302 | 4 | SendLocalResult(start, end); | |
| 303 | 4 | ReceiveFinalResult(); | |
| 304 | } | ||
| 305 | return true; | ||
| 306 | } | ||
| 307 | |||
| 308 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | bool MorozovaSConnectedComponentsMPI::PostProcessingImpl() { |
| 309 | auto &output = GetOutput(); | ||
| 310 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | if (output.empty()) { |
| 311 | return true; | ||
| 312 | } | ||
| 313 | 8 | int max_label = 0; | |
| 314 |
2/2✓ Branch 0 taken 72 times.
✓ Branch 1 taken 8 times.
|
80 | for (const auto &row : output) { |
| 315 |
2/2✓ Branch 0 taken 688 times.
✓ Branch 1 taken 72 times.
|
760 | for (int v : row) { |
| 316 | 688 | max_label = std::max(max_label, v); | |
| 317 | } | ||
| 318 | } | ||
| 319 | 8 | output.push_back({max_label}); | |
| 320 | 8 | return true; | |
| 321 | } | ||
| 322 | |||
| 323 | } // namespace morozova_s_connected_components | ||
| 324 |