GCC Code Coverage Report


Directory: ./
File: tasks/samoylenko_i_lex_order_check/mpi/src/ops_mpi.cpp
Date: 2026-01-27 01:59:34
Exec Total Coverage
Lines: 60 60 100.0%
Functions: 7 7 100.0%
Branches: 32 36 88.9%

Line Branch Exec Source
1 #include "samoylenko_i_lex_order_check/mpi/include/ops_mpi.hpp"
2
3 #include <mpi.h>
4
5 #include <algorithm>
6 #include <cstddef>
7 #include <string>
8 #include <utility>
9
10 #include "samoylenko_i_lex_order_check/common/include/common.hpp"
11
12 namespace samoylenko_i_lex_order_check {
13
14 namespace {
15
16 20 void ExchangeLengths(int rank, const std::pair<std::string, std::string> *input, size_t &len1, size_t &len2) {
17
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
20 if (rank == 0) {
18 10 len1 = input->first.size();
19 10 len2 = input->second.size();
20 }
21 20 MPI_Bcast(&len1, 1, MPI_UNSIGNED_LONG_LONG, 0, MPI_COMM_WORLD);
22 20 MPI_Bcast(&len2, 1, MPI_UNSIGNED_LONG_LONG, 0, MPI_COMM_WORLD);
23 20 }
24
25 20 void ScatterData(int rank, int size, const std::pair<std::string, std::string> *input, size_t min_len,
26 size_t substr_size, size_t substr_start, size_t substr_len, std::string &local_str1,
27 std::string &local_str2) {
28
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
20 if (rank == 0) {
29 const std::string &str1 = input->first;
30 const std::string &str2 = input->second;
31
32
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 3 times.
10 if (substr_len > 0) {
33 7 std::copy_n(str1.begin() + static_cast<std::ptrdiff_t>(substr_start), substr_len, local_str1.begin());
34 7 std::copy_n(str2.begin() + static_cast<std::ptrdiff_t>(substr_start), substr_len, local_str2.begin());
35 }
36
37
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
20 for (int proc = 1; proc < size; ++proc) {
38 10 size_t proc_start = proc * substr_size;
39
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 3 times.
10 if (proc_start < min_len) {
40 7 size_t proc_len = std::min(substr_size, min_len - proc_start);
41 7 MPI_Send(str1.data() + proc_start, static_cast<int>(proc_len), MPI_CHAR, proc, 0, MPI_COMM_WORLD);
42 7 MPI_Send(str2.data() + proc_start, static_cast<int>(proc_len), MPI_CHAR, proc, 1, MPI_COMM_WORLD);
43 }
44 }
45 } else {
46
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 3 times.
10 if (substr_len > 0) {
47 7 MPI_Recv(local_str1.data(), static_cast<int>(substr_len), MPI_CHAR, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
48 7 MPI_Recv(local_str2.data(), static_cast<int>(substr_len), MPI_CHAR, 0, 1, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
49 }
50 }
51 20 }
52
53 unsigned int FindLocalDifference(const std::string &s1, const std::string &s2, size_t offset, size_t default_val) {
54
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 14 times.
38 for (size_t i = 0; i < s1.size(); ++i) {
55
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 18 times.
24 if (s1[i] != s2[i]) {
56 6 return static_cast<unsigned int>(offset + i);
57 }
58 }
59 14 return static_cast<unsigned int>(default_val);
60 }
61
62 } // namespace
63
64
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 SamoylenkoILexOrderCheckMPI::SamoylenkoILexOrderCheckMPI(const InType &in) {
65 SetTypeOfTask(GetStaticTypeOfTask());
66 GetInput() = in;
67 20 GetOutput() = false;
68 20 }
69
70 20 bool SamoylenkoILexOrderCheckMPI::ValidationImpl() {
71 20 return true;
72 }
73
74 20 bool SamoylenkoILexOrderCheckMPI::PreProcessingImpl() {
75 20 return true;
76 }
77
78 20 bool SamoylenkoILexOrderCheckMPI::RunImpl() {
79 20 int rank = 0;
80 20 int size = 0;
81 20 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
82 20 MPI_Comm_size(MPI_COMM_WORLD, &size);
83
84 20 size_t len1 = 0;
85 20 size_t len2 = 0;
86
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
20 const auto *input_ptr = (rank == 0) ? &GetInput() : nullptr;
87
88 20 ExchangeLengths(rank, input_ptr, len1, len2);
89
90 size_t min_len = std::min(len1, len2);
91 20 size_t substr_size = (min_len + size - 1) / size;
92 20 size_t substr_start = rank * substr_size;
93 size_t substr_len = 0;
94
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 6 times.
20 if (substr_start < min_len) {
95 14 substr_len = std::min(substr_size, min_len - substr_start);
96 }
97
98 std::string local_str1(substr_len, '\0');
99 std::string local_str2(substr_len, '\0');
100
101
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 ScatterData(rank, size, input_ptr, min_len, substr_size, substr_start, substr_len, local_str1, local_str2);
102
103 20 unsigned int local_diff = FindLocalDifference(local_str1, local_str2, substr_start, min_len + 1);
104 20 unsigned int global_diff = 0;
105
106
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 MPI_Allreduce(&local_diff, &global_diff, 1, MPI_UNSIGNED, MPI_MIN, MPI_COMM_WORLD);
107
108 20 int output = 0;
109
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
20 if (rank == 0) {
110
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 4 times.
10 if (global_diff == static_cast<unsigned int>(min_len + 1)) {
111
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 5 times.
7 output = (len1 <= len2) ? 1 : 0;
112 } else {
113
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
7 output = (GetInput().first[global_diff] < GetInput().second[global_diff]) ? 1 : 0;
114 }
115 }
116
117
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 MPI_Bcast(&output, 1, MPI_INT, 0, MPI_COMM_WORLD);
118 20 GetOutput() = (output != 0);
119
120 20 return true;
121 }
122
123 20 bool SamoylenkoILexOrderCheckMPI::PostProcessingImpl() {
124 20 return true;
125 }
126
127 } // namespace samoylenko_i_lex_order_check
128