GCC Code Coverage Report


Directory: ./
File: tasks/fatehov_k_gaussian/all/src/ops_all.cpp
Date: 2026-06-04 20:25:32
Exec Total Coverage
Lines: 69 69 100.0%
Functions: 8 8 100.0%
Branches: 33 50 66.0%

Line Branch Exec Source
1 #include "fatehov_k_gaussian/all/include/ops_all.hpp"
2
3 #include <mpi.h>
4
5 #include <algorithm>
6 #include <cmath>
7 #include <cstddef>
8 #include <cstdint>
9 #include <vector>
10
11 #include "fatehov_k_gaussian/common/include/common.hpp"
12
13 namespace fatehov_k_gaussian {
14
15 namespace {
16
17 2175 float ConvolvePixel(const std::vector<uint8_t> &data, const std::vector<float> &kernel, int kernel_size, int half,
18 int w, int h, int ch, int y_coord, int x_coord, int c_coord) {
19 float res = 0.0F;
20
21
2/2
✓ Branch 0 taken 15225 times.
✓ Branch 1 taken 2175 times.
17400 for (int ky = -half; ky <= half; ++ky) {
22
2/2
✓ Branch 0 taken 106575 times.
✓ Branch 1 taken 15225 times.
121800 for (int kx = -half; kx <= half; ++kx) {
23 106575 const int ny = std::clamp(y_coord + ky, 0, h - 1);
24 106575 const int nx = std::clamp(x_coord + kx, 0, w - 1);
25 106575 const float weight = kernel[((ky + half) * kernel_size) + (kx + half)];
26 106575 res += static_cast<float>(data[((ny * w + nx) * ch) + c_coord]) * weight;
27 }
28 }
29
30 2175 return res;
31 }
32
33 725 void ProcessPixel(const std::vector<uint8_t> &src_data, std::vector<uint8_t> &dst_data,
34 const std::vector<float> &kernel, int kernel_size, int half, int w, int h, int ch, int y_coord,
35 int x_coord, int row_offset) {
36
2/2
✓ Branch 0 taken 2175 times.
✓ Branch 1 taken 725 times.
2900 for (int c_coord = 0; c_coord < ch; ++c_coord) {
37 2175 const float res = ConvolvePixel(src_data, kernel, kernel_size, half, w, h, ch, y_coord, x_coord, c_coord);
38 2175 dst_data[(((y_coord - row_offset) * w + x_coord) * ch) + c_coord] =
39 2175 static_cast<uint8_t>(std::clamp(res, 0.0F, 255.0F));
40 }
41 725 }
42
43 void ProcessRowRangeOMP(const std::vector<uint8_t> &src_data, std::vector<uint8_t> &dst_data,
44 const std::vector<float> &kernel, int kernel_size, int half, int w, int h, int ch,
45 int row_begin, int row_end) {
46 6 #pragma omp parallel for default(none) \
47 shared(src_data, dst_data, kernel, kernel_size, half, w, h, ch, row_begin, row_end) schedule(static)
48 for (int y_coord = row_begin; y_coord < row_end; ++y_coord) {
49 for (int x_coord = 0; x_coord < w; ++x_coord) {
50 ProcessPixel(src_data, dst_data, kernel, kernel_size, half, w, h, ch, y_coord, x_coord, row_begin);
51 }
52 }
53 }
54
55 6 void ComputeDistribution(int h, int size, std::vector<int> &recv_counts, std::vector<int> &displacements, int w,
56 int ch) {
57 6 const int rows_per_proc = h / size;
58 6 const int remainder = h % size;
59
60
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 6 times.
18 for (int i = 0; i < size; ++i) {
61
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 2 times.
12 const int r_begin = (i * rows_per_proc) + std::min(i, remainder);
62
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 2 times.
12 const int r_end = r_begin + rows_per_proc + (i < remainder ? 1 : 0);
63 12 recv_counts[i] = (r_end - r_begin) * w * ch;
64 12 displacements[i] = r_begin * w * ch;
65 }
66 6 }
67
68 } // namespace
69
70
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 FatehovKGaussianALL::FatehovKGaussianALL(const InType &in) {
71 SetTypeOfTask(GetStaticTypeOfTask());
72 GetInput() = in;
73 6 }
74
75 6 bool FatehovKGaussianALL::ValidationImpl() {
76 const auto &input = GetInput();
77
4/8
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 6 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 6 times.
6 return input.image.width > 0 && input.image.height > 0 && input.image.channels > 0 && !input.image.data.empty() &&
78
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 input.sigma > 0.0F;
79 }
80
81 6 bool FatehovKGaussianALL::PreProcessingImpl() {
82 const auto &input = GetInput();
83 6 const float sigma = input.sigma;
84
85 6 kernel_size_ = (2 * static_cast<int>(std::ceil(3.0F * sigma))) + 1;
86 6 kernel_.resize(static_cast<std::size_t>(kernel_size_) * kernel_size_);
87
88 6 const int half = kernel_size_ / 2;
89 6 const float two_sigma_sq = 2.0F * sigma * sigma;
90 float sum = 0.0F;
91
92
2/2
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 6 times.
48 for (int i = -half; i <= half; ++i) {
93
2/2
✓ Branch 0 taken 294 times.
✓ Branch 1 taken 42 times.
336 for (int j = -half; j <= half; ++j) {
94 294 const float val = std::exp(-(static_cast<float>((i * i) + (j * j))) / two_sigma_sq);
95 294 kernel_[((i + half) * kernel_size_) + (j + half)] = val;
96 294 sum += val;
97 }
98 }
99
100
2/2
✓ Branch 0 taken 294 times.
✓ Branch 1 taken 6 times.
300 for (float &val : kernel_) {
101 294 val /= sum;
102 }
103
104 6 GetOutput() = Image(input.image.width, input.image.height, input.image.channels);
105
106 6 return true;
107 }
108
109 6 bool FatehovKGaussianALL::RunImpl() {
110 6 int rank = 0;
111 6 int size = 1;
112 6 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
113 6 MPI_Comm_size(MPI_COMM_WORLD, &size);
114
115 const auto &input = GetInput();
116 auto &output = GetOutput();
117 6 const int w = static_cast<int>(input.image.width);
118 6 const int h = static_cast<int>(input.image.height);
119 6 const int ch = static_cast<int>(input.image.channels);
120 6 const int half = kernel_size_ / 2;
121 const int kernel_size = kernel_size_;
122 6 const auto &kernel = kernel_;
123
124 6 std::vector<uint8_t> img_data(input.image.data);
125
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 MPI_Bcast(img_data.data(), static_cast<int>(img_data.size()), MPI_UNSIGNED_CHAR, 0, MPI_COMM_WORLD);
126
127 6 const int rows_per_proc = h / size;
128 6 const int remainder = h % size;
129
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 1 times.
6 const int row_begin = (rank * rows_per_proc) + std::min(rank, remainder);
130
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 1 times.
6 const int row_end = row_begin + rows_per_proc + (rank < remainder ? 1 : 0);
131 6 const int local_rows = row_end - row_begin;
132
133
1/4
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
6 std::vector<uint8_t> local_output(static_cast<std::size_t>(local_rows) * w * ch);
134
135 ProcessRowRangeOMP(img_data, local_output, kernel, kernel_size, half, w, h, ch, row_begin, row_end);
136
137
1/4
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
6 std::vector<int> recv_counts(size);
138
1/4
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
6 std::vector<int> displacements(size);
139 6 ComputeDistribution(h, size, recv_counts, displacements, w, ch);
140
141
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 MPI_Gatherv(local_output.data(), local_rows * w * ch, MPI_UINT8_T, output.data.data(), recv_counts.data(),
142 displacements.data(), MPI_UINT8_T, 0, MPI_COMM_WORLD);
143
144 6 return true;
145 }
146
147 6 bool FatehovKGaussianALL::PostProcessingImpl() {
148 6 return true;
149 }
150
151 } // namespace fatehov_k_gaussian
152