GCC Code Coverage Report


Directory: ./
File: tasks/moskaev_v_lin_filt_block_gauss_3/omp/src/ops_omp.cpp
Date: 2026-04-02 17:12:27
Exec Total Coverage
Lines: 19 24 79.2%
Functions: 5 6 83.3%
Branches: 3 6 50.0%

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