GCC Code Coverage Report


Directory: ./
File: tasks/kondrashova_v_marking_components/stl/src/ops_stl.cpp
Date: 2026-05-11 08:26:31
Exec Total Coverage
Lines: 19 105 18.1%
Functions: 5 10 50.0%
Branches: 4 128 3.1%

Line Branch Exec Source
1 #include "kondrashova_v_marking_components/stl/include/ops_stl.hpp"
2
3 #include <algorithm>
4 #include <cstddef>
5 #include <cstdint>
6 #include <functional>
7 #include <thread>
8 #include <vector>
9
10 #include "kondrashova_v_marking_components/common/include/common.hpp"
11 #include "util/include/util.hpp"
12
13 namespace kondrashova_v_marking_components {
14
15
1/2
✓ Branch 1 taken 104 times.
✗ Branch 2 not taken.
104 KondrashovaVTaskSTL::KondrashovaVTaskSTL(const InType &in) {
16 SetTypeOfTask(GetStaticTypeOfTask());
17 GetInput() = in;
18 208 GetOutput() = {};
19 104 }
20
21 104 bool KondrashovaVTaskSTL::ValidationImpl() {
22 104 return true;
23 }
24
25 104 bool KondrashovaVTaskSTL::PreProcessingImpl() {
26 const auto &in = GetInput();
27
28 104 width_ = in.width;
29 104 height_ = in.height;
30 104 image_ = in.data;
31
32 104 labels_1d_.assign(static_cast<size_t>(width_) * static_cast<size_t>(height_), 0);
33
34
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 104 times.
104 GetOutput().count = 0;
35 GetOutput().labels.clear();
36 104 return true;
37 }
38
39 namespace {
40
41 int Find(std::vector<int> &parent, int xx) {
42 while (parent[static_cast<size_t>(xx)] != xx) {
43 parent[static_cast<size_t>(xx)] = parent[static_cast<size_t>(parent[static_cast<size_t>(xx)])];
44 xx = parent[static_cast<size_t>(xx)];
45 }
46 return xx;
47 }
48
49 void Unite(std::vector<int> &parent, std::vector<int> &rnk, int aa, int bb) {
50 aa = Find(parent, aa);
51 bb = Find(parent, bb);
52 if (aa == bb) {
53 return;
54 }
55 if (rnk[static_cast<size_t>(aa)] < rnk[static_cast<size_t>(bb)]) {
56 std::swap(aa, bb);
57 }
58 parent[static_cast<size_t>(bb)] = aa;
59 if (rnk[static_cast<size_t>(aa)] == rnk[static_cast<size_t>(bb)]) {
60 rnk[static_cast<size_t>(aa)]++;
61 }
62 }
63
64 int GetNeighborLabel(int ii, int jj, int di, int dj, int row_start, int row_end, int width,
65 const std::vector<uint8_t> &image, const std::vector<int> &local_labels) {
66 int ni = ii + di;
67 int nj = jj + dj;
68 if (ni < row_start || ni >= row_end || nj < 0 || nj >= width) {
69 return 0;
70 }
71 auto nidx = (static_cast<size_t>(ni) * static_cast<size_t>(width)) + static_cast<size_t>(nj);
72 if (image[nidx] == 0) {
73 return local_labels[nidx];
74 }
75 return 0;
76 }
77
78 void ScanStripe(int row_start, int row_end, int width, int label_offset, const std::vector<uint8_t> &image,
79 std::vector<int> &local_labels) {
80 int current_label = label_offset;
81 for (int ii = row_start; ii < row_end; ++ii) {
82 for (int jj = 0; jj < width; ++jj) {
83 auto idx = (static_cast<size_t>(ii) * static_cast<size_t>(width)) + static_cast<size_t>(jj);
84 if (image[idx] != 0) {
85 continue;
86 }
87
88 int left_label = GetNeighborLabel(ii, jj, 0, -1, row_start, row_end, width, image, local_labels);
89 int top_label = GetNeighborLabel(ii, jj, -1, 0, row_start, row_end, width, image, local_labels);
90
91 if (left_label == 0 && top_label == 0) {
92 local_labels[idx] = ++current_label;
93 } else if (left_label != 0 && top_label == 0) {
94 local_labels[idx] = left_label;
95 } else if (left_label == 0) {
96 local_labels[idx] = top_label;
97 } else {
98 local_labels[idx] = std::min(left_label, top_label);
99 }
100 }
101 }
102 }
103
104 void MergeHorizontal(int height, int width, const std::vector<int> &local_labels, std::vector<int> &parent,
105 std::vector<int> &rnk) {
106 for (int ii = 0; ii < height; ++ii) {
107 for (int jj = 1; jj < width; ++jj) {
108 auto idx = (static_cast<size_t>(ii) * static_cast<size_t>(width)) + static_cast<size_t>(jj);
109 auto lidx = (static_cast<size_t>(ii) * static_cast<size_t>(width)) + static_cast<size_t>(jj - 1);
110 if (local_labels[idx] != 0 && local_labels[lidx] != 0 && local_labels[idx] != local_labels[lidx]) {
111 Unite(parent, rnk, local_labels[idx], local_labels[lidx]);
112 }
113 }
114 }
115 }
116
117 void MergeBoundaries(int height, int width, int num_threads, const std::vector<int> &local_labels,
118 std::vector<int> &parent, std::vector<int> &rnk) {
119 for (int tid = 1; tid < num_threads; ++tid) {
120 const int boundary_row = (tid * height) / num_threads;
121 if (boundary_row >= height) {
122 continue;
123 }
124 for (int jj = 0; jj < width; ++jj) {
125 auto idx = (static_cast<size_t>(boundary_row) * static_cast<size_t>(width)) + static_cast<size_t>(jj);
126 auto tidx = (static_cast<size_t>(boundary_row - 1) * static_cast<size_t>(width)) + static_cast<size_t>(jj);
127 if (local_labels[idx] != 0 && local_labels[tidx] != 0 && local_labels[idx] != local_labels[tidx]) {
128 Unite(parent, rnk, local_labels[idx], local_labels[tidx]);
129 }
130 }
131 }
132 }
133
134 int Relabel(int total, const std::vector<int> &local_labels, std::vector<int> &parent, std::vector<int> &relabel_map,
135 std::vector<int> &labels_1d) {
136 int count = 0;
137 for (int ii = 0; ii < total; ++ii) {
138 auto idx = static_cast<size_t>(ii);
139 if (local_labels[idx] == 0) {
140 continue;
141 }
142 int root = Find(parent, local_labels[idx]);
143 if (relabel_map[static_cast<size_t>(root)] == 0) {
144 relabel_map[static_cast<size_t>(root)] = ++count;
145 }
146 labels_1d[idx] = relabel_map[static_cast<size_t>(root)];
147 }
148 return count;
149 }
150
151 } // namespace
152
153 104 bool KondrashovaVTaskSTL::RunImpl() {
154
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 104 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
104 if (width_ <= 0 || height_ <= 0 || image_.empty()) {
155 104 GetOutput().count = 0;
156 104 return true;
157 }
158
159 const int total = width_ * height_;
160 const int num_threads = ppc::util::GetNumThreads();
161 const int max_labels_per_thread = total + 1;
162 const int max_total_labels = (num_threads * max_labels_per_thread) + 1;
163
164 std::vector<int> local_labels(static_cast<size_t>(total), 0);
165
166 std::vector<std::thread> threads(static_cast<size_t>(num_threads));
167 for (int tid = 0; tid < num_threads; ++tid) {
168 const int row_start = (tid * height_) / num_threads;
169 const int row_end = ((tid + 1) * height_) / num_threads;
170 const int label_offset = tid * max_labels_per_thread;
171 threads[static_cast<size_t>(tid)] =
172 std::thread(ScanStripe, row_start, row_end, width_, label_offset, std::cref(image_), std::ref(local_labels));
173 }
174 for (auto &thr : threads) {
175 thr.join();
176 }
177
178 std::vector<int> parent(static_cast<size_t>(max_total_labels));
179 std::vector<int> rnk(static_cast<size_t>(max_total_labels), 0);
180 for (int ii = 0; ii < max_total_labels; ++ii) {
181 parent[static_cast<size_t>(ii)] = ii;
182 }
183
184 MergeHorizontal(height_, width_, local_labels, parent, rnk);
185 MergeBoundaries(height_, width_, num_threads, local_labels, parent, rnk);
186
187 std::vector<int> relabel_map(static_cast<size_t>(max_total_labels), 0);
188 GetOutput().count = Relabel(total, local_labels, parent, relabel_map, labels_1d_);
189
190 return true;
191 }
192
193 104 bool KondrashovaVTaskSTL::PostProcessingImpl() {
194
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 104 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
104 if (width_ <= 0 || height_ <= 0) {
195 GetOutput().labels.clear();
196 104 return true;
197 }
198
199 GetOutput().labels.assign(height_, std::vector<int>(width_, 0));
200 for (int ii = 0; ii < height_; ++ii) {
201 for (int jj = 0; jj < width_; ++jj) {
202 auto idx = (static_cast<size_t>(ii) * static_cast<size_t>(width_)) + static_cast<size_t>(jj);
203 GetOutput().labels[ii][jj] = labels_1d_[idx];
204 }
205 }
206 return true;
207 }
208
209 } // namespace kondrashova_v_marking_components
210