GCC Code Coverage Report


Directory: ./
File: tasks/moskaev_v_lin_filt_block_gauss_3/stl/src/ops_stl.cpp
Date: 2026-06-04 20:25:32
Exec Total Coverage
Lines: 82 82 100.0%
Functions: 10 10 100.0%
Branches: 37 48 77.1%

Line Branch Exec Source
1 #include "moskaev_v_lin_filt_block_gauss_3/stl/include/ops_stl.hpp"
2
3 #include <algorithm>
4 #include <cmath>
5 #include <cstddef>
6 #include <cstdint>
7 #include <thread>
8 #include <vector>
9
10 #include "moskaev_v_lin_filt_block_gauss_3/common/include/common.hpp"
11 #include "util/include/util.hpp"
12
13 namespace moskaev_v_lin_filt_block_gauss_3 {
14
15
1/2
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
32 MoskaevVLinFiltBlockGauss3STL::MoskaevVLinFiltBlockGauss3STL(const InType &in) {
16 SetTypeOfTask(GetStaticTypeOfTask());
17 GetInput() = in;
18 32 GetOutput() = OutType();
19 32 }
20
21 32 bool MoskaevVLinFiltBlockGauss3STL::ValidationImpl() {
22 const auto &input = GetInput();
23 32 return !std::get<4>(input).empty();
24 }
25
26 32 bool MoskaevVLinFiltBlockGauss3STL::PreProcessingImpl() {
27 32 return true;
28 }
29
30 namespace {
31
32 208 inline void ComputeFilteredPixel(const std::vector<uint8_t> &input_block, std::vector<uint8_t> &output_block,
33 int block_width, int inner_width, int channels, int row, int col, int channel) {
34 float sum = 0.0F;
35
2/2
✓ Branch 0 taken 624 times.
✓ Branch 1 taken 208 times.
832 for (int ky = -1; ky <= 1; ++ky) {
36
2/2
✓ Branch 0 taken 1872 times.
✓ Branch 1 taken 624 times.
2496 for (int kx = -1; kx <= 1; ++kx) {
37 1872 int ny = row + 1 + ky;
38 1872 int nx = col + 1 + kx;
39 1872 int idx = (((ny * block_width) + nx) * channels) + channel;
40 1872 sum += static_cast<float>(input_block[idx]) * kGaussianKernel[((ky + 1) * 3) + (kx + 1)];
41 }
42 }
43 208 int out_idx = (((row * inner_width) + col) * channels) + channel;
44 208 output_block[out_idx] = static_cast<uint8_t>(std::round(sum));
45 208 }
46
47 32 void CopyBlockWithPadding(const std::vector<uint8_t> &source_image, std::vector<uint8_t> &padded_block, int width,
48 int height, int channels, int block_x, int block_y, int current_block_width,
49 int current_block_height, int block_with_padding_width) {
50
2/2
✓ Branch 0 taken 128 times.
✓ Branch 1 taken 32 times.
160 for (int row = -1; row <= current_block_height; ++row) {
51
2/2
✓ Branch 0 taken 528 times.
✓ Branch 1 taken 128 times.
656 for (int col = -1; col <= current_block_width; ++col) {
52 528 int src_y = std::clamp(block_y + row, 0, height - 1);
53 528 int src_x = std::clamp(block_x + col, 0, width - 1);
54 528 int dst_y = row + 1;
55 528 int dst_x = col + 1;
56
2/2
✓ Branch 0 taken 784 times.
✓ Branch 1 taken 528 times.
1312 for (int channel = 0; channel < channels; ++channel) {
57 784 int src_idx = (((src_y * width) + src_x) * channels) + channel;
58 784 int dst_idx = (((dst_y * block_with_padding_width) + dst_x) * channels) + channel;
59 784 padded_block[dst_idx] = source_image[src_idx];
60 }
61 }
62 }
63 32 }
64
65 32 void CopyProcessedBlockToOutput(const std::vector<uint8_t> &processed_block, std::vector<uint8_t> &output_image,
66 int width, int channels, int block_x, int block_y, int current_block_width,
67 int current_block_height) {
68
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 32 times.
96 for (int row = 0; row < current_block_height; ++row) {
69
2/2
✓ Branch 0 taken 144 times.
✓ Branch 1 taken 64 times.
208 for (int col = 0; col < current_block_width; ++col) {
70
2/2
✓ Branch 0 taken 208 times.
✓ Branch 1 taken 144 times.
352 for (int channel = 0; channel < channels; ++channel) {
71 208 int src_idx = (((row * current_block_width) + col) * channels) + channel;
72 208 int dst_idx = ((((block_y + row) * width) + (block_x + col)) * channels) + channel;
73 208 output_image[dst_idx] = processed_block[src_idx];
74 }
75 }
76 }
77 32 }
78
79 } // namespace
80
81 32 void MoskaevVLinFiltBlockGauss3STL::ApplyGaussianFilterToBlock(const std::vector<uint8_t> &input_block,
82 std::vector<uint8_t> &output_block, int block_width,
83 int block_height, int channels) {
84 32 int inner_width = block_width - 2;
85 32 int inner_height = block_height - 2;
86
87
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 32 times.
96 for (int row = 0; row < inner_height; ++row) {
88
2/2
✓ Branch 0 taken 144 times.
✓ Branch 1 taken 64 times.
208 for (int col = 0; col < inner_width; ++col) {
89
2/2
✓ Branch 0 taken 208 times.
✓ Branch 1 taken 144 times.
352 for (int channel = 0; channel < channels; ++channel) {
90 208 ComputeFilteredPixel(input_block, output_block, block_width, inner_width, channels, row, col, channel);
91 }
92 }
93 }
94 32 }
95
96 32 bool MoskaevVLinFiltBlockGauss3STL::RunImpl() {
97 const auto &input = GetInput();
98
99 32 int width = std::get<0>(input);
100 32 int height = std::get<1>(input);
101
1/2
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
32 int channels = std::get<2>(input);
102 const auto &image_data = std::get<4>(input);
103
104
1/2
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
32 if (image_data.empty()) {
105 return false;
106 }
107
108 32 block_size_ = 64;
109 32 int block_size = block_size_;
110
111 32 GetOutput().resize(static_cast<size_t>(width) * static_cast<size_t>(height) * static_cast<size_t>(channels));
112
113 32 int blocks_x = (width + block_size - 1) / block_size;
114 32 int blocks_y = (height + block_size - 1) / block_size;
115 32 int total_blocks = blocks_y * blocks_x;
116
117 32 const int num_threads = ppc::util::GetNumThreads();
118 32 std::vector<std::thread> threads(num_threads);
119
120
2/2
✓ Branch 0 taken 80 times.
✓ Branch 1 taken 32 times.
112 for (int tid = 0; tid < num_threads; ++tid) {
121 80 int block_start = (tid * total_blocks) / num_threads;
122 80 int block_end = ((tid + 1) * total_blocks) / num_threads;
123
124
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 80 times.
80 threads[tid] = std::thread([&, block_start, block_end]() {
125
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 80 times.
112 for (int linear_idx = block_start; linear_idx < block_end; ++linear_idx) {
126 32 int by = linear_idx / blocks_x;
127 32 int bx = linear_idx % blocks_x;
128 32 int block_x = bx * block_size;
129 32 int block_y = by * block_size;
130
1/2
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
32 int current_block_width = std::min(block_size, width - block_x);
131
1/2
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
32 int current_block_height = std::min(block_size, height - block_y);
132 32 int pw = current_block_width + 2;
133 32 int ph = current_block_height + 2;
134
135 32 std::vector<uint8_t> in_block(static_cast<size_t>(pw) * ph * channels, 0);
136
1/4
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
32 std::vector<uint8_t> out_block(static_cast<size_t>(current_block_width) * current_block_height * channels, 0);
137
138 32 CopyBlockWithPadding(image_data, in_block, width, height, channels, block_x, block_y, current_block_width,
139 current_block_height, pw);
140 32 ApplyGaussianFilterToBlock(in_block, out_block, pw, ph, channels);
141 32 CopyProcessedBlockToOutput(out_block, GetOutput(), width, channels, block_x, block_y, current_block_width,
142 current_block_height);
143 }
144
1/2
✓ Branch 1 taken 80 times.
✗ Branch 2 not taken.
160 });
145 }
146
147
2/2
✓ Branch 0 taken 80 times.
✓ Branch 1 taken 32 times.
112 for (auto &th : threads) {
148
1/2
✓ Branch 1 taken 80 times.
✗ Branch 2 not taken.
80 th.join();
149 }
150
151 return true;
152 32 }
153
154 32 bool MoskaevVLinFiltBlockGauss3STL::PostProcessingImpl() {
155 32 return !GetOutput().empty();
156 }
157
158 } // namespace moskaev_v_lin_filt_block_gauss_3
159