GCC Code Coverage Report


Directory: ./
File: tasks/romanov_a_gauss_block/omp/src/ops_omp.cpp
Date: 2026-04-02 17:12:27
Exec Total Coverage
Lines: 51 51 100.0%
Functions: 8 8 100.0%
Branches: 24 28 85.7%

Line Branch Exec Source
1 #include "romanov_a_gauss_block/omp/include/ops_omp.hpp"
2
3 #include <omp.h>
4
5 #include <algorithm>
6 #include <array>
7 #include <cstddef>
8 #include <cstdint>
9 #include <tuple>
10 #include <vector>
11
12 #include "romanov_a_gauss_block/common/include/common.hpp"
13
14 namespace romanov_a_gauss_block {
15
16
1/2
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
32 RomanovAGaussBlockOMP::RomanovAGaussBlockOMP(const InType &in) {
17 SetTypeOfTask(GetStaticTypeOfTask());
18 GetInput() = in;
19 32 GetOutput() = std::vector<uint8_t>();
20 32 }
21
22 32 bool RomanovAGaussBlockOMP::ValidationImpl() {
23 32 return std::get<0>(GetInput()) * std::get<1>(GetInput()) * 3 == static_cast<int>(std::get<2>(GetInput()).size());
24 }
25
26 32 bool RomanovAGaussBlockOMP::PreProcessingImpl() {
27 32 return true;
28 }
29
30 namespace {
31
32 constexpr int kBlockSize = 32;
33
34 120336 int ApplyKernel(const std::vector<uint8_t> &img, int row, int col, int channel, int width, int height,
35 const std::array<std::array<int, 3>, 3> &kernel) {
36 int sum = 0;
37
2/2
✓ Branch 0 taken 361008 times.
✓ Branch 1 taken 120336 times.
481344 for (size_t kr = 0; kr < 3; ++kr) {
38
2/2
✓ Branch 0 taken 1083024 times.
✓ Branch 1 taken 361008 times.
1444032 for (size_t kc = 0; kc < 3; ++kc) {
39 1083024 int nr = row + static_cast<int>(kr) - 1;
40 1083024 int nc = col + static_cast<int>(kc) - 1;
41
4/4
✓ Branch 0 taken 1074744 times.
✓ Branch 1 taken 8280 times.
✓ Branch 2 taken 1066992 times.
✓ Branch 3 taken 7752 times.
1083024 if (nr >= 0 && nr < height && nc >= 0 && nc < width) {
42 1066992 size_t idx = (((static_cast<size_t>(nr) * width) + nc) * 3) + channel;
43 1066992 sum += (static_cast<int>(img[idx]) * kernel.at(kr).at(kc));
44 }
45 }
46 }
47 120336 return sum;
48 }
49
50 36 void ProcessFullBlock(const std::vector<uint8_t> &initial_picture, std::vector<uint8_t> &result_picture, int width,
51 int height, int start_row, int start_col) {
52 36 const std::array<std::array<int, 3>, 3> kernel = {{{1, 2, 1}, {2, 4, 2}, {1, 2, 1}}};
53
54
2/2
✓ Branch 0 taken 1152 times.
✓ Branch 1 taken 36 times.
1188 for (int row = start_row; row < start_row + kBlockSize; ++row) {
55
2/2
✓ Branch 0 taken 36864 times.
✓ Branch 1 taken 1152 times.
38016 for (int col = start_col; col < start_col + kBlockSize; ++col) {
56
2/2
✓ Branch 0 taken 110592 times.
✓ Branch 1 taken 36864 times.
147456 for (int channel = 0; channel < 3; ++channel) {
57 110592 int sum = ApplyKernel(initial_picture, row, col, channel, width, height, kernel);
58
1/2
✓ Branch 0 taken 110592 times.
✗ Branch 1 not taken.
110592 int result_value = (sum + 8) / 16;
59 result_value = std::clamp(result_value, 0, 255);
60 110592 auto idx = ((static_cast<size_t>(row) * width + col) * 3) + channel;
61 110592 result_picture[idx] = static_cast<uint8_t>(result_value);
62 }
63 }
64 }
65 36 }
66
67 56 void ProcessPartBlock(const std::vector<uint8_t> &initial_picture, std::vector<uint8_t> &result_picture, int width,
68 int height, int start_row, int start_col) {
69 56 const std::array<std::array<int, 3>, 3> kernel = {{{1, 2, 1}, {2, 4, 2}, {1, 2, 1}}};
70
71 56 const int end_row = std::min(height, start_row + kBlockSize);
72 56 const int end_col = std::min(width, start_col + kBlockSize);
73
74
2/2
✓ Branch 0 taken 500 times.
✓ Branch 1 taken 56 times.
556 for (int row = start_row; row < end_row; ++row) {
75
2/2
✓ Branch 0 taken 3248 times.
✓ Branch 1 taken 500 times.
3748 for (int col = start_col; col < end_col; ++col) {
76
2/2
✓ Branch 0 taken 9744 times.
✓ Branch 1 taken 3248 times.
12992 for (int channel = 0; channel < 3; ++channel) {
77 9744 int sum = ApplyKernel(initial_picture, row, col, channel, width, height, kernel);
78
1/2
✓ Branch 0 taken 9744 times.
✗ Branch 1 not taken.
9744 int result_value = (sum + 8) / 16;
79 result_value = std::clamp(result_value, 0, 255);
80 9744 auto idx = ((static_cast<size_t>(row) * width + col) * 3) + channel;
81 9744 result_picture[idx] = static_cast<uint8_t>(result_value);
82 }
83 }
84 }
85 56 }
86
87 } // namespace
88
89 32 bool RomanovAGaussBlockOMP::RunImpl() {
90 32 const int width = std::get<0>(GetInput());
91 32 const int height = std::get<1>(GetInput());
92
93 const std::vector<uint8_t> &initial_picture = std::get<2>(GetInput());
94 32 std::vector<uint8_t> result_picture(static_cast<size_t>(height * width * 3));
95
96 32 #pragma omp parallel for schedule(static) default(none) shared(initial_picture, result_picture, width, height)
97 for (int start_row = 0; start_row < (height + 1 - kBlockSize); start_row += kBlockSize) {
98 for (int start_col = 0; start_col < (width + 1 - kBlockSize); start_col += kBlockSize) {
99 ProcessFullBlock(initial_picture, result_picture, width, height, start_row, start_col);
100 }
101 }
102
103 32 #pragma omp parallel for schedule(static) default(none) shared(initial_picture, result_picture, width, height)
104 for (int start_row = 0; start_row < (height + 1 - kBlockSize); start_row += kBlockSize) {
105 ProcessPartBlock(initial_picture, result_picture, width, height, start_row, width - (width % kBlockSize));
106 }
107
108 32 #pragma omp parallel for schedule(static) default(none) shared(initial_picture, result_picture, width, height)
109 for (int start_col = 0; start_col < (width + 1 - kBlockSize); start_col += kBlockSize) {
110 ProcessPartBlock(initial_picture, result_picture, width, height, height - (height % kBlockSize), start_col);
111 }
112
113 32 ProcessPartBlock(initial_picture, result_picture, width, height, height - (height % kBlockSize),
114 32 width - (width % kBlockSize));
115
116
1/2
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
32 GetOutput() = result_picture;
117 32 return true;
118 }
119
120 32 bool RomanovAGaussBlockOMP::PostProcessingImpl() {
121 32 return true;
122 }
123
124 } // namespace romanov_a_gauss_block
125