| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #include "peryashkin_v_binary_component_contour_processing/all/include/ops_all.hpp" | ||
| 2 | |||
| 3 | #include <mpi.h> | ||
| 4 | #include <omp.h> | ||
| 5 | |||
| 6 | #include <algorithm> | ||
| 7 | #include <cstddef> | ||
| 8 | #include <cstdint> | ||
| 9 | #include <queue> | ||
| 10 | #include <ranges> | ||
| 11 | #include <utility> | ||
| 12 | #include <vector> | ||
| 13 | |||
| 14 | #include "peryashkin_v_binary_component_contour_processing/common/include/common.hpp" | ||
| 15 | |||
| 16 | namespace peryashkin_v_binary_component_contour_processing { | ||
| 17 | |||
| 18 | namespace { | ||
| 19 | |||
| 20 | inline bool InBounds(int x, int y, int w, int h) { | ||
| 21 | 371 | return (x >= 0) && (y >= 0) && (x < w) && (y < h); | |
| 22 | } | ||
| 23 | |||
| 24 | inline std::int64_t Cross(const Point &o, const Point &a, const Point &b) { | ||
| 25 | 90 | return (static_cast<std::int64_t>(a.x - o.x) * static_cast<std::int64_t>(b.y - o.y)) - | |
| 26 | 90 | (static_cast<std::int64_t>(a.y - o.y) * static_cast<std::int64_t>(b.x - o.x)); | |
| 27 | } | ||
| 28 | |||
| 29 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
|
7 | inline std::vector<Point> ConvexHullMonotonicChain(std::vector<Point> pts) { |
| 30 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
|
7 | if (pts.empty()) { |
| 31 | ✗ | return {}; | |
| 32 | } | ||
| 33 | |||
| 34 |
9/78✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
✗ Branch 48 not taken.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✗ Branch 51 not taken.
✗ Branch 52 not taken.
✗ Branch 53 not taken.
✗ Branch 54 not taken.
✗ Branch 55 not taken.
✗ Branch 56 not taken.
✗ Branch 57 not taken.
✗ Branch 58 not taken.
✗ Branch 59 not taken.
✗ Branch 60 not taken.
✗ Branch 61 not taken.
✗ Branch 62 not taken.
✗ Branch 63 not taken.
✗ Branch 64 not taken.
✗ Branch 65 not taken.
✗ Branch 66 not taken.
✓ Branch 67 taken 40 times.
✓ Branch 68 taken 11 times.
✓ Branch 69 taken 29 times.
✗ Branch 70 not taken.
✓ Branch 71 taken 11 times.
✓ Branch 72 taken 36 times.
✓ Branch 73 taken 40 times.
✓ Branch 74 taken 27 times.
✓ Branch 75 taken 13 times.
✗ Branch 76 not taken.
✓ Branch 77 taken 27 times.
|
116 | std::ranges::sort(pts, [](const Point &a, const Point &b) { return (a.x < b.x) || ((a.x == b.x) && (a.y < b.y)); }); |
| 35 | |||
| 36 | const auto uniq = | ||
| 37 |
3/8✓ Branch 0 taken 27 times.
✓ Branch 1 taken 13 times.
✓ Branch 2 taken 27 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
|
40 | std::ranges::unique(pts, [](const Point &a, const Point &b) { return (a.x == b.x) && (a.y == b.y); }); |
| 38 | pts.erase(uniq.begin(), pts.end()); | ||
| 39 | |||
| 40 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6 times.
|
7 | if (pts.size() == 1) { |
| 41 | return pts; | ||
| 42 | } | ||
| 43 | |||
| 44 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | std::vector<Point> lower; |
| 45 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | lower.reserve(pts.size()); |
| 46 |
2/2✓ Branch 0 taken 46 times.
✓ Branch 1 taken 6 times.
|
52 | for (const auto &p : pts) { |
| 47 |
4/4✓ Branch 0 taken 45 times.
✓ Branch 1 taken 30 times.
✓ Branch 2 taken 29 times.
✓ Branch 3 taken 16 times.
|
75 | while ((lower.size() >= 2) && (Cross(lower[lower.size() - 2], lower[lower.size() - 1], p) <= 0)) { |
| 48 | lower.pop_back(); | ||
| 49 | } | ||
| 50 | lower.push_back(p); | ||
| 51 | } | ||
| 52 | |||
| 53 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | std::vector<Point> upper; |
| 54 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | upper.reserve(pts.size()); |
| 55 |
2/2✓ Branch 0 taken 46 times.
✓ Branch 1 taken 6 times.
|
52 | for (std::size_t i = pts.size(); i-- > 0;) { |
| 56 | const auto &p = pts[i]; | ||
| 57 |
4/4✓ Branch 0 taken 45 times.
✓ Branch 1 taken 30 times.
✓ Branch 2 taken 16 times.
✓ Branch 3 taken 29 times.
|
75 | while ((upper.size() >= 2) && (Cross(upper[upper.size() - 2], upper[upper.size() - 1], p) <= 0)) { |
| 58 | upper.pop_back(); | ||
| 59 | } | ||
| 60 | upper.push_back(p); | ||
| 61 | } | ||
| 62 | |||
| 63 | lower.pop_back(); | ||
| 64 | upper.pop_back(); | ||
| 65 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | lower.insert(lower.end(), upper.begin(), upper.end()); |
| 66 | return lower; | ||
| 67 | } | ||
| 68 | |||
| 69 | inline std::size_t Idx(int x, int y, int w) { | ||
| 70 |
5/6✓ Branch 0 taken 47 times.
✓ Branch 1 taken 191 times.
✓ Branch 3 taken 7 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 100 times.
✓ Branch 6 taken 78 times.
|
423 | return (static_cast<std::size_t>(y) * static_cast<std::size_t>(w)) + static_cast<std::size_t>(x); |
| 71 | } | ||
| 72 | |||
| 73 |
2/2✓ Branch 0 taken 183 times.
✓ Branch 1 taken 5 times.
|
188 | inline void TryPush4(const BinaryImage &img, int w, int h, int nx, int ny, std::vector<std::uint8_t> &vis, |
| 74 | std::queue<Point> &q) { | ||
| 75 |
2/2✓ Branch 0 taken 178 times.
✓ Branch 1 taken 5 times.
|
183 | if (!InBounds(nx, ny, w, h)) { |
| 76 | return; | ||
| 77 | } | ||
| 78 | const std::size_t nid = Idx(nx, ny, w); | ||
| 79 |
4/4✓ Branch 0 taken 100 times.
✓ Branch 1 taken 78 times.
✓ Branch 2 taken 40 times.
✓ Branch 3 taken 60 times.
|
178 | if ((img.data[nid] == 1) && (vis[nid] == 0U)) { |
| 80 | 40 | vis[nid] = 1U; | |
| 81 | 40 | q.push(Point{.x = nx, .y = ny}); | |
| 82 | } | ||
| 83 | } | ||
| 84 | |||
| 85 | 7 | inline std::vector<Point> BfsComponent4(const BinaryImage &img, int w, int h, int sx, int sy, | |
| 86 | std::vector<std::uint8_t> &vis) { | ||
| 87 | 7 | std::vector<Point> pts; | |
| 88 |
1/2✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
|
7 | pts.reserve(128); |
| 89 | |||
| 90 | std::queue<Point> q; | ||
| 91 | |||
| 92 | const std::size_t sid = Idx(sx, sy, w); | ||
| 93 | 7 | vis[sid] = 1U; | |
| 94 |
1/2✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
|
7 | q.push(Point{.x = sx, .y = sy}); |
| 95 | |||
| 96 |
2/2✓ Branch 0 taken 47 times.
✓ Branch 1 taken 7 times.
|
54 | while (!q.empty()) { |
| 97 | 47 | const Point p = q.front(); | |
| 98 | q.pop(); | ||
| 99 | |||
| 100 | pts.push_back(p); | ||
| 101 | |||
| 102 |
1/2✓ Branch 1 taken 47 times.
✗ Branch 2 not taken.
|
47 | TryPush4(img, w, h, p.x + 1, p.y, vis, q); |
| 103 |
1/2✓ Branch 1 taken 47 times.
✗ Branch 2 not taken.
|
47 | TryPush4(img, w, h, p.x - 1, p.y, vis, q); |
| 104 |
1/2✓ Branch 1 taken 47 times.
✗ Branch 2 not taken.
|
47 | TryPush4(img, w, h, p.x, p.y + 1, vis, q); |
| 105 |
1/2✓ Branch 1 taken 47 times.
✗ Branch 2 not taken.
|
47 | TryPush4(img, w, h, p.x, p.y - 1, vis, q); |
| 106 | } | ||
| 107 | |||
| 108 | 7 | return pts; | |
| 109 | } | ||
| 110 | |||
| 111 | 7 | inline std::vector<std::vector<Point>> ExtractComponents4(const BinaryImage &img) { | |
| 112 | 7 | const int w = img.width; | |
| 113 | 7 | const int h = img.height; | |
| 114 | |||
| 115 | 7 | std::vector<std::vector<Point>> comps; | |
| 116 |
1/2✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
|
7 | if ((w <= 0) || (h <= 0)) { |
| 117 | return comps; | ||
| 118 | } | ||
| 119 | |||
| 120 | 7 | const std::size_t n = static_cast<std::size_t>(w) * static_cast<std::size_t>(h); | |
| 121 |
1/2✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
|
7 | std::vector<std::uint8_t> vis(n, 0U); |
| 122 | |||
| 123 |
2/2✓ Branch 0 taken 38 times.
✓ Branch 1 taken 7 times.
|
45 | for (int yy = 0; yy < h; ++yy) { |
| 124 |
2/2✓ Branch 0 taken 238 times.
✓ Branch 1 taken 38 times.
|
276 | for (int xx = 0; xx < w; ++xx) { |
| 125 | const std::size_t id = Idx(xx, yy, w); | ||
| 126 |
4/4✓ Branch 0 taken 47 times.
✓ Branch 1 taken 191 times.
✓ Branch 2 taken 40 times.
✓ Branch 3 taken 7 times.
|
238 | if ((img.data[id] == 0) || (vis[id] != 0U)) { |
| 127 | 231 | continue; | |
| 128 | } | ||
| 129 |
1/4✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
14 | comps.push_back(BfsComponent4(img, w, h, xx, yy, vis)); |
| 130 | } | ||
| 131 | } | ||
| 132 | |||
| 133 | return comps; | ||
| 134 | ✗ | } | |
| 135 | |||
| 136 | 28 | inline std::vector<int> FlattenComponents(const std::vector<std::vector<Point>> &comps) { | |
| 137 | 28 | std::vector<int> flat; | |
| 138 |
2/2✓ Branch 0 taken 14 times.
✓ Branch 1 taken 28 times.
|
42 | for (const auto &comp : comps) { |
| 139 |
1/4✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
14 | flat.push_back(static_cast<int>(comp.size())); |
| 140 |
2/2✓ Branch 0 taken 70 times.
✓ Branch 1 taken 14 times.
|
84 | for (const auto &p : comp) { |
| 141 |
2/2✓ Branch 0 taken 56 times.
✓ Branch 1 taken 14 times.
|
70 | flat.push_back(p.x); |
| 142 |
2/2✓ Branch 0 taken 30 times.
✓ Branch 1 taken 40 times.
|
70 | flat.push_back(p.y); |
| 143 | } | ||
| 144 | } | ||
| 145 | 28 | return flat; | |
| 146 | } | ||
| 147 | |||
| 148 | 28 | inline std::vector<std::vector<Point>> UnflattenComponents(const std::vector<int> &flat) { | |
| 149 | 28 | std::vector<std::vector<Point>> comps; | |
| 150 | std::size_t pos = 0; | ||
| 151 | |||
| 152 |
2/2✓ Branch 0 taken 21 times.
✓ Branch 1 taken 28 times.
|
49 | while (pos < flat.size()) { |
| 153 |
1/2✓ Branch 1 taken 21 times.
✗ Branch 2 not taken.
|
21 | const int cnt = flat[pos++]; |
| 154 | 21 | std::vector<Point> comp; | |
| 155 |
1/2✓ Branch 1 taken 21 times.
✗ Branch 2 not taken.
|
21 | comp.reserve(static_cast<std::size_t>(cnt)); |
| 156 | |||
| 157 |
2/2✓ Branch 0 taken 93 times.
✓ Branch 1 taken 21 times.
|
114 | for (int i = 0; i < cnt; ++i) { |
| 158 |
1/2✓ Branch 1 taken 93 times.
✗ Branch 2 not taken.
|
93 | const int x = flat[pos++]; |
| 159 | 93 | const int y = flat[pos++]; | |
| 160 |
1/4✓ Branch 1 taken 93 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
93 | comp.push_back(Point{.x = x, .y = y}); |
| 161 | } | ||
| 162 | |||
| 163 | comps.push_back(std::move(comp)); | ||
| 164 | } | ||
| 165 | |||
| 166 | 28 | return comps; | |
| 167 | ✗ | } | |
| 168 | |||
| 169 | 14 | inline std::vector<int> MakeDispls(const std::vector<int> &counts) { | |
| 170 | 14 | std::vector<int> displs(counts.size(), 0); | |
| 171 |
2/2✓ Branch 0 taken 14 times.
✓ Branch 1 taken 14 times.
|
28 | for (std::size_t i = 1; i < counts.size(); ++i) { |
| 172 | 14 | displs[i] = displs[i - 1] + counts[i - 1]; | |
| 173 | } | ||
| 174 | 14 | return displs; | |
| 175 | } | ||
| 176 | |||
| 177 | 7 | inline std::vector<int> MakeComponentCounts(int total_components, int proc_count) { | |
| 178 | 7 | std::vector<int> comp_counts(proc_count, 0); | |
| 179 |
2/2✓ Branch 0 taken 14 times.
✓ Branch 1 taken 7 times.
|
21 | for (int i = 0; i < proc_count; ++i) { |
| 180 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 5 times.
|
23 | comp_counts[i] = (total_components / proc_count) + ((i < (total_components % proc_count)) ? 1 : 0); |
| 181 | } | ||
| 182 | 7 | return comp_counts; | |
| 183 | } | ||
| 184 | |||
| 185 | 7 | inline std::vector<int> FlattenDistributedComponents(const std::vector<std::vector<Point>> &all_components, | |
| 186 | const std::vector<int> &comp_counts, | ||
| 187 | std::vector<int> &send_counts) { | ||
| 188 | 7 | std::vector<int> flat_send; | |
| 189 | int comp_offset = 0; | ||
| 190 | |||
| 191 |
2/2✓ Branch 0 taken 14 times.
✓ Branch 1 taken 7 times.
|
21 | for (std::size_t proc = 0; proc < comp_counts.size(); ++proc) { |
| 192 |
1/2✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
|
14 | std::vector<std::vector<Point>> part; |
| 193 |
1/2✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
|
14 | part.reserve(static_cast<std::size_t>(comp_counts[proc])); |
| 194 | |||
| 195 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 14 times.
|
21 | for (int j = 0; j < comp_counts[proc]; ++j) { |
| 196 |
1/2✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
|
7 | const auto comp_index = static_cast<std::size_t>(comp_offset) + static_cast<std::size_t>(j); |
| 197 |
1/2✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
|
7 | part.push_back(all_components[comp_index]); |
| 198 | } | ||
| 199 | |||
| 200 | 14 | comp_offset += comp_counts[proc]; | |
| 201 | |||
| 202 |
1/2✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
|
14 | std::vector<int> flat_part = FlattenComponents(part); |
| 203 |
1/2✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
|
14 | send_counts[proc] = static_cast<int>(flat_part.size()); |
| 204 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 7 times.
|
14 | flat_send.insert(flat_send.end(), flat_part.begin(), flat_part.end()); |
| 205 | 14 | } | |
| 206 | |||
| 207 | 7 | return flat_send; | |
| 208 | } | ||
| 209 | |||
| 210 | 14 | inline OutType BuildLocalHulls(std::vector<std::vector<Point>> local_components) { | |
| 211 | 14 | OutType local_hulls(local_components.size()); | |
| 212 | 14 | const int local_components_count = static_cast<int>(local_components.size()); | |
| 213 | |||
| 214 | 14 | #pragma omp parallel for default(none) shared(local_components, local_hulls, local_components_count) | |
| 215 | for (int i = 0; i < local_components_count; ++i) { | ||
| 216 | const auto idx = static_cast<std::size_t>(i); | ||
| 217 | local_hulls[idx] = ConvexHullMonotonicChain(std::move(local_components[idx])); | ||
| 218 | } | ||
| 219 | |||
| 220 | 14 | return local_hulls; | |
| 221 | } | ||
| 222 | |||
| 223 | 14 | inline std::vector<int> GatherFlatHulls(const std::vector<int> &flat_local_hulls, int rank, int size) { | |
| 224 | 14 | const int local_hulls_size = static_cast<int>(flat_local_hulls.size()); | |
| 225 | |||
| 226 |
1/2✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
|
14 | std::vector<int> recv_hull_counts(static_cast<std::size_t>(size), 0); |
| 227 |
1/2✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
|
14 | MPI_Gather(&local_hulls_size, 1, MPI_INT, recv_hull_counts.data(), 1, MPI_INT, 0, MPI_COMM_WORLD); |
| 228 | |||
| 229 | 14 | std::vector<int> recv_hull_displs; | |
| 230 | 14 | std::vector<int> flat_hulls_root; | |
| 231 | |||
| 232 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 7 times.
|
14 | if (rank == 0) { |
| 233 |
2/6✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
14 | recv_hull_displs = MakeDispls(recv_hull_counts); |
| 234 | |||
| 235 | int total_size = 0; | ||
| 236 |
1/2✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
|
7 | if (!recv_hull_counts.empty()) { |
| 237 | const auto last_idx = recv_hull_counts.size() - 1; | ||
| 238 | 7 | total_size = recv_hull_displs[last_idx] + recv_hull_counts[last_idx]; | |
| 239 | } | ||
| 240 | |||
| 241 |
1/2✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
|
7 | flat_hulls_root.resize(static_cast<std::size_t>(total_size)); |
| 242 | } | ||
| 243 | |||
| 244 |
3/4✓ Branch 0 taken 7 times.
✓ Branch 1 taken 7 times.
✓ Branch 3 taken 14 times.
✗ Branch 4 not taken.
|
21 | MPI_Gatherv(flat_local_hulls.data(), local_hulls_size, MPI_INT, rank == 0 ? flat_hulls_root.data() : nullptr, |
| 245 | recv_hull_counts.data(), rank == 0 ? recv_hull_displs.data() : nullptr, MPI_INT, 0, MPI_COMM_WORLD); | ||
| 246 | |||
| 247 | 14 | return flat_hulls_root; | |
| 248 | } | ||
| 249 | |||
| 250 | 14 | inline OutType SolveALL(const BinaryImage &img) { | |
| 251 | 14 | int rank = 0; | |
| 252 | 14 | int size = 1; | |
| 253 | 14 | MPI_Comm_rank(MPI_COMM_WORLD, &rank); | |
| 254 | 14 | MPI_Comm_size(MPI_COMM_WORLD, &size); | |
| 255 | |||
| 256 | 14 | std::vector<int> send_counts(static_cast<std::size_t>(size), 0); | |
| 257 |
1/4✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
14 | std::vector<int> send_displs(static_cast<std::size_t>(size), 0); |
| 258 | 14 | std::vector<int> flat_send; | |
| 259 | |||
| 260 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 7 times.
|
14 | if (rank == 0) { |
| 261 |
1/2✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
|
7 | const auto all_components = ExtractComponents4(img); |
| 262 | 7 | const int total_components = static_cast<int>(all_components.size()); | |
| 263 |
1/2✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
|
7 | const auto comp_counts = MakeComponentCounts(total_components, size); |
| 264 | |||
| 265 |
1/2✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
|
7 | flat_send = FlattenDistributedComponents(all_components, comp_counts, send_counts); |
| 266 |
2/6✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
14 | send_displs = MakeDispls(send_counts); |
| 267 | 7 | } | |
| 268 | |||
| 269 |
1/2✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
|
14 | int recv_count = 0; |
| 270 |
1/2✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
|
14 | MPI_Scatter(send_counts.data(), 1, MPI_INT, &recv_count, 1, MPI_INT, 0, MPI_COMM_WORLD); |
| 271 | |||
| 272 |
1/4✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
14 | std::vector<int> flat_recv(static_cast<std::size_t>(recv_count)); |
| 273 |
3/4✓ Branch 0 taken 7 times.
✓ Branch 1 taken 7 times.
✓ Branch 3 taken 14 times.
✗ Branch 4 not taken.
|
21 | MPI_Scatterv(rank == 0 ? flat_send.data() : nullptr, send_counts.data(), send_displs.data(), MPI_INT, |
| 274 | flat_recv.data(), recv_count, MPI_INT, 0, MPI_COMM_WORLD); | ||
| 275 | |||
| 276 |
1/2✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
|
14 | auto local_components = UnflattenComponents(flat_recv); |
| 277 |
1/2✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
|
14 | const auto local_hulls = BuildLocalHulls(std::move(local_components)); |
| 278 |
1/2✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
|
14 | const auto flat_local_hulls = FlattenComponents(local_hulls); |
| 279 | |||
| 280 | 14 | std::vector<int> flat_broadcast; | |
| 281 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 7 times.
|
14 | if (rank == 0) { |
| 282 |
1/2✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
|
14 | flat_broadcast = GatherFlatHulls(flat_local_hulls, rank, size); |
| 283 | } else { | ||
| 284 |
1/4✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
14 | GatherFlatHulls(flat_local_hulls, rank, size); |
| 285 | } | ||
| 286 | |||
| 287 | 14 | int broadcast_size = 0; | |
| 288 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 7 times.
|
14 | if (rank == 0) { |
| 289 | 7 | broadcast_size = static_cast<int>(flat_broadcast.size()); | |
| 290 | } | ||
| 291 | |||
| 292 |
1/2✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
|
14 | MPI_Bcast(&broadcast_size, 1, MPI_INT, 0, MPI_COMM_WORLD); |
| 293 | |||
| 294 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 7 times.
|
14 | if (rank != 0) { |
| 295 |
1/2✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
|
7 | flat_broadcast.resize(static_cast<std::size_t>(broadcast_size)); |
| 296 | } | ||
| 297 | |||
| 298 |
1/2✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
|
14 | MPI_Bcast(flat_broadcast.data(), broadcast_size, MPI_INT, 0, MPI_COMM_WORLD); |
| 299 | |||
| 300 |
1/2✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
|
28 | return UnflattenComponents(flat_broadcast); |
| 301 | 14 | } | |
| 302 | |||
| 303 | } // namespace | ||
| 304 | |||
| 305 |
1/2✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
|
14 | PeryashkinVBinaryComponentContourProcessingALL::PeryashkinVBinaryComponentContourProcessingALL(const InType &in) { |
| 306 | SetTypeOfTask(GetStaticTypeOfTask()); | ||
| 307 | GetInput() = in; | ||
| 308 | GetOutput().clear(); | ||
| 309 | 14 | } | |
| 310 | |||
| 311 | 28 | bool PeryashkinVBinaryComponentContourProcessingALL::ValidationImpl() { | |
| 312 | const auto &in = GetInput(); | ||
| 313 |
2/4✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 28 times.
✗ Branch 3 not taken.
|
28 | if ((in.width <= 0) || (in.height <= 0)) { |
| 314 | return false; | ||
| 315 | } | ||
| 316 | |||
| 317 | 28 | const std::size_t need = static_cast<std::size_t>(in.width) * static_cast<std::size_t>(in.height); | |
| 318 | 28 | return in.data.size() == need; | |
| 319 | } | ||
| 320 | |||
| 321 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
|
14 | bool PeryashkinVBinaryComponentContourProcessingALL::PreProcessingImpl() { |
| 322 | local_out_.clear(); | ||
| 323 | 14 | return true; | |
| 324 | } | ||
| 325 | |||
| 326 | 14 | bool PeryashkinVBinaryComponentContourProcessingALL::RunImpl() { | |
| 327 |
1/2✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
|
14 | if (!ValidationImpl()) { |
| 328 | return false; | ||
| 329 | } | ||
| 330 | |||
| 331 | 14 | local_out_ = SolveALL(GetInput()); | |
| 332 | 14 | return true; | |
| 333 | } | ||
| 334 | |||
| 335 | 14 | bool PeryashkinVBinaryComponentContourProcessingALL::PostProcessingImpl() { | |
| 336 | 14 | GetOutput() = local_out_; | |
| 337 | 14 | return true; | |
| 338 | } | ||
| 339 | |||
| 340 | } // namespace peryashkin_v_binary_component_contour_processing | ||
| 341 |