GCC Code Coverage Report


Directory: ./
File: tasks/Rastvorov_K_Number_of_character_alternations/mpi/src/ops_mpi.cpp
Date: 2026-01-27 01:59:34
Exec Total Coverage
Lines: 61 61 100.0%
Functions: 7 7 100.0%
Branches: 36 40 90.0%

Line Branch Exec Source
1 #include "Rastvorov_K_Number_of_character_alternations/mpi/include/ops_mpi.hpp"
2
3 #include <mpi.h>
4
5 #include <array>
6 #include <cstddef>
7 #include <vector>
8
9 #include "Rastvorov_K_Number_of_character_alternations/common/include/common.hpp"
10
11 namespace rastvorov_k_number_of_character_alternations {
12
13 namespace {
14
15 inline int Sign(double x) {
16 if (x > 0.0) {
17 return 1;
18 }
19
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 16 times.
25 if (x < 0.0) {
20 return -1;
21 }
22 return 0;
23 }
24
25 inline double GetElement(std::size_t i) {
26
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 9 times.
41 if (i % 5 == 0) {
27 return 0.0;
28 }
29
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 16 times.
32 if (i % 2 == 0) {
30 return 1.0;
31 }
32 return -1.0;
33 }
34
35 struct LocalInfo {
36 int count{};
37 int first_sign{};
38 int last_sign{};
39 };
40
41 inline void ComputeRange(std::size_t rank, std::size_t size, std::size_t total, std::size_t *begin, std::size_t *end) {
42 8 const std::size_t base = total / size;
43 8 const std::size_t rem = total % size;
44
45 8 if (rank < rem) {
46 3 *begin = rank * (base + 1);
47 3 *end = *begin + base + 1;
48 } else {
49 5 *begin = (rem * (base + 1)) + ((rank - rem) * base);
50 5 *end = *begin + base;
51 }
52 }
53
54 8 inline LocalInfo ProcessSegment(std::size_t begin, std::size_t end) {
55 LocalInfo info{};
56
57
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 8 times.
49 for (std::size_t i = begin; i < end; ++i) {
58 const int s = Sign(GetElement(i));
59 9 if (s == 0) {
60 9 continue;
61 }
62
63
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 26 times.
32 if (info.first_sign == 0) {
64 info.first_sign = s;
65 }
66
4/4
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 22 times.
✓ Branch 3 taken 4 times.
32 if (info.last_sign != 0 && info.last_sign != s) {
67 22 ++info.count;
68 }
69 info.last_sign = s;
70 }
71
72 8 return info;
73 }
74
75 4 inline int CombineGlobal(const std::vector<int> &all_info) {
76 int global_count = 0;
77 int prev_sign = 0;
78 4 const std::size_t size = all_info.size() / 3;
79
80
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 4 times.
12 for (std::size_t proc = 0; proc < size; ++proc) {
81 8 const int lc = all_info[(3 * proc) + 0];
82 8 const int fs = all_info[(3 * proc) + 1];
83 8 const int ls = all_info[(3 * proc) + 2];
84
85
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
8 if (fs != 0) {
86
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
6 if (prev_sign != 0 && fs != prev_sign) {
87 2 ++global_count;
88 }
89
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (ls != 0) {
90 prev_sign = ls;
91 }
92 }
93
94 8 global_count += lc;
95 }
96
97 4 return global_count;
98 }
99
100 } // namespace
101
102 10 RastvorovKNumberAfCharacterAlternationsMPI::RastvorovKNumberAfCharacterAlternationsMPI(const InType &in) {
103 SetTypeOfTask(GetStaticTypeOfTask());
104 10 GetInput() = in;
105 GetOutput() = 0;
106 10 }
107
108 10 bool RastvorovKNumberAfCharacterAlternationsMPI::ValidationImpl() {
109 10 return GetInput() >= 0;
110 }
111
112 10 bool RastvorovKNumberAfCharacterAlternationsMPI::PreProcessingImpl() {
113 10 GetOutput() = 0;
114 10 return true;
115 }
116
117 10 bool RastvorovKNumberAfCharacterAlternationsMPI::RunImpl() {
118 10 int rank = 0;
119 10 int size = 1;
120 10 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
121 10 MPI_Comm_size(MPI_COMM_WORLD, &size);
122
123 10 const InType n = GetInput();
124
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
10 if (n <= 0) {
125
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (rank == 0) {
126 1 GetOutput() = 0;
127 }
128 2 return true;
129 }
130
131 8 const auto total = static_cast<std::size_t>(n);
132
133 std::size_t begin = 0;
134 std::size_t end = 0;
135
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 5 times.
8 ComputeRange(static_cast<std::size_t>(rank), static_cast<std::size_t>(size), total, &begin, &end);
136
137 8 const LocalInfo local = ProcessSegment(begin, end);
138
139 8 std::array<int, 3> local_info = {local.count, local.first_sign, local.last_sign};
140
141 8 std::vector<int> all_info;
142
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
8 if (rank == 0) {
143
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 all_info.resize(static_cast<std::size_t>(size) * 3);
144 }
145
146
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
✓ Branch 3 taken 8 times.
✗ Branch 4 not taken.
12 MPI_Gather(local_info.data(), 3, MPI_INT, rank == 0 ? all_info.data() : nullptr, 3, MPI_INT, 0, MPI_COMM_WORLD);
147
148
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
8 if (rank == 0) {
149 4 GetOutput() = CombineGlobal(all_info);
150 }
151
152
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 MPI_Barrier(MPI_COMM_WORLD);
153 return true;
154 }
155
156 10 bool RastvorovKNumberAfCharacterAlternationsMPI::PostProcessingImpl() {
157 10 return true;
158 }
159
160 } // namespace rastvorov_k_number_of_character_alternations
161