GCC Code Coverage Report


Directory: ./
File: tasks/krykov_e_sobel_op/all/src/ops_all.cpp
Date: 2026-06-04 20:25:32
Exec Total Coverage
Lines: 53 54 98.1%
Functions: 6 6 100.0%
Branches: 21 38 55.3%

Line Branch Exec Source
1 #include "krykov_e_sobel_op/all/include/ops_all.hpp"
2
3 #include <mpi.h>
4 #include <omp.h>
5
6 #include <algorithm>
7 #include <array>
8 #include <cmath>
9 #include <cstddef>
10 #include <vector>
11
12 #include "krykov_e_sobel_op/common/include/common.hpp"
13
14 namespace krykov_e_sobel_op {
15
16
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 KrykovESobelOpALL::KrykovESobelOpALL(const InType &in) {
17 SetTypeOfTask(GetStaticTypeOfTask());
18 GetInput() = in;
19 GetOutput().clear();
20 6 }
21
22 6 bool KrykovESobelOpALL::ValidationImpl() {
23 const auto &img = GetInput();
24
3/6
✓ 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.
6 return img.width > 2 && img.height > 2 && static_cast<int>(img.data.size()) == img.width * img.height;
25 }
26
27 6 bool KrykovESobelOpALL::PreProcessingImpl() {
28 const auto &img = GetInput();
29
30 6 width_ = img.width;
31 6 height_ = img.height;
32
33 6 grayscale_.resize(static_cast<size_t>(width_) * static_cast<size_t>(height_));
34 // RGB → grayscale
35
2/2
✓ Branch 0 taken 96 times.
✓ Branch 1 taken 6 times.
102 for (int i = 0; i < width_ * height_; ++i) {
36 96 const Pixel &p = img.data[i];
37 96 grayscale_[i] = static_cast<int>((0.299 * p.r) + (0.587 * p.g) + (0.114 * p.b));
38 }
39 6 GetOutput().assign(static_cast<size_t>(width_) * static_cast<size_t>(height_), 0);
40 6 return true;
41 }
42
43 namespace {
44
45 12 int ComputeSobelMagnitude(const std::vector<int> &gray, int row, int col, int w,
46 const std::array<std::array<int, 3>, 3> &gx_kernel,
47 const std::array<std::array<int, 3>, 3> &gy_kernel) {
48 int gx = 0;
49 int gy = 0;
50
51
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 12 times.
48 for (int ky = -1; ky <= 1; ++ky) {
52
2/2
✓ Branch 0 taken 108 times.
✓ Branch 1 taken 36 times.
144 for (int kx = -1; kx <= 1; ++kx) {
53 108 const int idx = ((row + ky) * w) + (col + kx);
54
2/4
✓ Branch 0 taken 108 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 108 times.
108 if (idx < 0 || static_cast<size_t>(idx) >= gray.size()) {
55 continue;
56 }
57 108 const int pixel = gray.at(static_cast<size_t>(idx));
58 108 const auto ky_idx = static_cast<size_t>(ky) + 1U;
59 108 const auto kx_idx = static_cast<size_t>(kx) + 1U;
60 108 gx += pixel * gx_kernel.at(ky_idx).at(kx_idx);
61 108 gy += pixel * gy_kernel.at(ky_idx).at(kx_idx);
62 }
63 }
64
65 12 return static_cast<int>(std::sqrt(static_cast<double>((gx * gx) + (gy * gy))));
66 }
67
68 void BuildMpiLayout(int nproc, int w, int base, int extra, std::vector<int> &counts, std::vector<int> &displs) {
69
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 6 times.
18 for (int i = 0; i < nproc; ++i) {
70
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 const int cnt = base + (i < extra ? 1 : 0);
71 12 const int start = 1 + (base * i) + std::min(i, extra);
72 12 counts[i] = cnt * w;
73 12 displs[i] = start * w;
74 }
75 }
76
77 } // namespace
78
79 6 bool KrykovESobelOpALL::RunImpl() {
80 6 const std::array<std::array<int, 3>, 3> gx_kernel = {{{-1, 0, 1}, {-2, 0, 2}, {-1, 0, 1}}};
81 6 const std::array<std::array<int, 3>, 3> gy_kernel = {{{-1, -2, -1}, {0, 0, 0}, {1, 2, 1}}};
82
83 auto &output = GetOutput();
84 6 const auto &gray = grayscale_;
85 6 const int h = height_;
86 6 const int w = width_;
87
88 6 int rank = 0;
89 6 int nproc = 1;
90 6 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
91 6 MPI_Comm_size(MPI_COMM_WORLD, &nproc);
92
93 6 const int base = (h - 2) / nproc;
94 6 const int extra = (h - 2) % nproc;
95
96
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 const int local_count = base + (rank < extra ? 1 : 0);
97 6 const int local_start = 1 + (base * rank) + std::min(rank, extra);
98
99 6 std::vector<int> local_output(static_cast<size_t>(local_count) * static_cast<size_t>(w), 0);
100
101
1/4
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
6 std::vector<int> counts(nproc);
102
1/4
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
6 std::vector<int> displs(nproc);
103 6 BuildMpiLayout(nproc, w, base, extra, counts, displs);
104
105
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 #pragma omp parallel for default(none) shared(local_output, gray, gx_kernel, gy_kernel) \
106 firstprivate(local_start, local_count, w) schedule(static)
107 for (int li = 0; li < local_count; ++li) {
108 const int row = local_start + li;
109 for (int col = 1; col < w - 1; ++col) {
110 const auto out_idx = (static_cast<size_t>(li) * static_cast<size_t>(w)) + static_cast<size_t>(col);
111 if (out_idx < local_output.size()) {
112 local_output[out_idx] = ComputeSobelMagnitude(gray, row, col, w, gx_kernel, gy_kernel);
113 }
114 }
115 }
116
117
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 MPI_Gatherv(local_output.data(), counts[rank], MPI_INT, output.data(), counts.data(), displs.data(), MPI_INT, 0,
118 MPI_COMM_WORLD);
119
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 MPI_Bcast(output.data(), static_cast<int>(static_cast<size_t>(w) * static_cast<size_t>(h)), MPI_INT, 0,
120 MPI_COMM_WORLD);
121
122 6 return true;
123 }
124
125 6 bool KrykovESobelOpALL::PostProcessingImpl() {
126 6 return true;
127 }
128
129 } // namespace krykov_e_sobel_op
130