GCC Code Coverage Report


Directory: ./
File: tasks/gaivoronskiy_m_gauss_jordan/mpi/src/ops_mpi.cpp
Date: 2026-01-27 01:59:34
Exec Total Coverage
Lines: 137 146 93.8%
Functions: 14 14 100.0%
Branches: 103 160 64.4%

Line Branch Exec Source
1 #include "gaivoronskiy_m_gauss_jordan/mpi/include/ops_mpi.hpp"
2
3 #include <mpi.h>
4
5 #include <algorithm>
6 #include <cmath>
7 #include <cstddef>
8 #include <vector>
9
10 #include "gaivoronskiy_m_gauss_jordan/common/include/common.hpp"
11
12 namespace gaivoronskiy_m_gauss_jordan {
13
14 namespace {
15
16 bool IsZero(double value) {
17
6/8
✓ Branch 0 taken 84 times.
✓ Branch 1 taken 88 times.
✓ Branch 2 taken 88 times.
✓ Branch 3 taken 84 times.
✓ Branch 4 taken 84 times.
✓ Branch 5 taken 88 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
516 return std::fabs(value) < 1e-10;
18 }
19
20 int FindPivotRow(const std::vector<std::vector<double>> &matrix, int col, int start_row, int n) {
21 int global_pivot_row = -1;
22 double max_val = 0.0;
23
24
2/2
✓ Branch 0 taken 172 times.
✓ Branch 1 taken 88 times.
260 for (int i = start_row; i < n; i++) {
25
2/2
✓ Branch 0 taken 102 times.
✓ Branch 1 taken 70 times.
172 double abs_val = std::fabs(matrix[i][col]);
26
2/2
✓ Branch 0 taken 102 times.
✓ Branch 1 taken 70 times.
172 if (abs_val > max_val) {
27 max_val = abs_val;
28 global_pivot_row = i;
29 }
30 }
31
32
1/2
✓ Branch 0 taken 88 times.
✗ Branch 1 not taken.
88 return (max_val > 1e-10) ? global_pivot_row : -1;
33 }
34
35 88 void SwapMatrixRows(std::vector<std::vector<double>> &matrix, int row1, int row2) {
36
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 68 times.
88 if (row1 != row2) {
37 20 std::swap(matrix[row1], matrix[row2]);
38 }
39 88 }
40
41 void NormalizeMatrixRow(std::vector<std::vector<double>> &matrix, int row, int pivot_col, int m) {
42
1/2
✓ Branch 0 taken 88 times.
✗ Branch 1 not taken.
88 double pivot = matrix[row][pivot_col];
43
1/2
✓ Branch 0 taken 88 times.
✗ Branch 1 not taken.
88 if (!IsZero(pivot)) {
44
2/2
✓ Branch 0 taken 344 times.
✓ Branch 1 taken 88 times.
432 for (int j = 0; j < m; j++) {
45 344 matrix[row][j] /= pivot;
46 }
47 }
48 }
49
50 88 void EliminateColumn(std::vector<std::vector<double>> &matrix, int pivot_row, int pivot_col, int n, int m) {
51
2/2
✓ Branch 0 taken 256 times.
✓ Branch 1 taken 88 times.
344 for (int i = 0; i < n; i++) {
52
2/2
✓ Branch 0 taken 88 times.
✓ Branch 1 taken 168 times.
256 if (i == pivot_row) {
53 88 continue;
54 }
55
56
2/2
✓ Branch 0 taken 54 times.
✓ Branch 1 taken 114 times.
168 double coeff = matrix[i][pivot_col];
57
2/2
✓ Branch 0 taken 54 times.
✓ Branch 1 taken 114 times.
168 if (!IsZero(coeff)) {
58
2/2
✓ Branch 0 taken 186 times.
✓ Branch 1 taken 54 times.
240 for (int j = 0; j < m; j++) {
59 186 matrix[i][j] -= coeff * matrix[pivot_row][j];
60 }
61 }
62 }
63 88 }
64
65 void SyncMatrixRow(std::vector<std::vector<double>> &matrix, int row, int m) {
66 88 MPI_Bcast(matrix[row].data(), m, MPI_DOUBLE, 0, MPI_COMM_WORLD);
67 }
68
69 88 void SyncEntireMatrix(std::vector<std::vector<double>> &matrix, int n, int m) {
70
2/2
✓ Branch 0 taken 256 times.
✓ Branch 1 taken 88 times.
344 for (int i = 0; i < n; i++) {
71 256 MPI_Bcast(matrix[i].data(), m, MPI_DOUBLE, 0, MPI_COMM_WORLD);
72 }
73 88 }
74
75 34 void PerformGaussJordanElimination(std::vector<std::vector<double>> &matrix, int n, int m) {
76 int row = 0;
77 int col = 0;
78
79
3/4
✓ Branch 0 taken 88 times.
✓ Branch 1 taken 34 times.
✓ Branch 2 taken 88 times.
✗ Branch 3 not taken.
122 while (row < n && col < m - 1) {
80 int pivot_row = FindPivotRow(matrix, col, row, n);
81
82
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 88 times.
88 if (pivot_row == -1) {
83 col++;
84 continue;
85 }
86
87 88 SwapMatrixRows(matrix, row, pivot_row);
88 NormalizeMatrixRow(matrix, row, col, m);
89 SyncMatrixRow(matrix, row, m);
90 88 EliminateColumn(matrix, row, col, n, m);
91 88 SyncEntireMatrix(matrix, n, m);
92
93 88 row++;
94 88 col++;
95 88 MPI_Barrier(MPI_COMM_WORLD);
96 }
97 34 }
98
99 34 struct MatrixAnalysisResult {
100 bool inconsistent{false};
101 int rank{0};
102 std::vector<double> solution;
103 };
104
105 bool IsRowAllZeros(const std::vector<double> &row, int cols) {
106
2/4
✓ Branch 0 taken 172 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 172 times.
✗ Branch 3 not taken.
344 for (int j = 0; j < cols; j++) {
107
4/4
✓ Branch 0 taken 84 times.
✓ Branch 1 taken 88 times.
✓ Branch 2 taken 84 times.
✓ Branch 3 taken 88 times.
344 if (!IsZero(row[j])) {
108 return false;
109 }
110 }
111 return true;
112 }
113
114 88 bool CheckRowInconsistency(const std::vector<double> &row, int m) {
115
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 88 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
176 return IsRowAllZeros(row, m - 1) && !IsZero(row[m - 1]);
116 }
117
118 void ExtractSolutionFromRow(const std::vector<double> &row, int m, std::vector<double> &solution) {
119
1/2
✓ Branch 0 taken 172 times.
✗ Branch 1 not taken.
172 for (int j = 0; j < m - 1; j++) {
120
2/2
✓ Branch 0 taken 88 times.
✓ Branch 1 taken 84 times.
172 if (!IsZero(row[j])) {
121 88 solution[j] = row[m - 1];
122 88 break;
123 }
124 }
125 }
126
127 34 MatrixAnalysisResult AnalyzeMatrixAndExtractSolution(const std::vector<std::vector<double>> &matrix, int n, int m) {
128 34 MatrixAnalysisResult result;
129
1/4
✓ Branch 1 taken 34 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
34 result.solution.resize(m - 1, 0.0);
130
131
2/2
✓ Branch 0 taken 88 times.
✓ Branch 1 taken 34 times.
122 for (int i = 0; i < n; i++) {
132 88 bool has_non_zero = !IsRowAllZeros(matrix[i], m - 1);
133
134
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 88 times.
88 if (CheckRowInconsistency(matrix[i], m)) {
135 result.inconsistent = true;
136 }
137
138
1/2
✓ Branch 0 taken 88 times.
✗ Branch 1 not taken.
88 if (has_non_zero) {
139 88 result.rank++;
140 }
141
142
1/2
✓ Branch 0 taken 88 times.
✗ Branch 1 not taken.
88 if (i < m - 1) {
143 ExtractSolutionFromRow(matrix[i], m, result.solution);
144 }
145 }
146
147 34 return result;
148 }
149
150 34 void BroadcastMatrixDimensions(int &n, int &m) {
151 34 MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD);
152 34 MPI_Bcast(&m, 1, MPI_INT, 0, MPI_COMM_WORLD);
153 34 }
154
155 17 void FlattenAndBroadcastMatrix(const std::vector<std::vector<double>> &input, int n, int m) {
156 17 std::vector<double> flat_matrix(static_cast<size_t>(n * m));
157
2/2
✓ Branch 0 taken 44 times.
✓ Branch 1 taken 17 times.
61 for (int i = 0; i < n; i++) {
158
2/2
✓ Branch 0 taken 172 times.
✓ Branch 1 taken 44 times.
216 for (int j = 0; j < m; j++) {
159 172 flat_matrix[(static_cast<size_t>(i) * static_cast<size_t>(m)) + static_cast<size_t>(j)] = input[i][j];
160 }
161 }
162
1/2
✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
17 MPI_Bcast(flat_matrix.data(), n * m, MPI_DOUBLE, 0, MPI_COMM_WORLD);
163 17 }
164
165 17 void ReceiveAndUnflattenMatrix(std::vector<std::vector<double>> &input, int n, int m) {
166
1/2
✓ Branch 2 taken 17 times.
✗ Branch 3 not taken.
17 std::vector<double> flat_matrix(static_cast<size_t>(n * m));
167
1/2
✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
17 MPI_Bcast(flat_matrix.data(), n * m, MPI_DOUBLE, 0, MPI_COMM_WORLD);
168
2/6
✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 17 times.
✗ Branch 5 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
17 input = std::vector<std::vector<double>>(static_cast<size_t>(n), std::vector<double>(static_cast<size_t>(m)));
169
2/2
✓ Branch 0 taken 44 times.
✓ Branch 1 taken 17 times.
61 for (int i = 0; i < n; i++) {
170
2/2
✓ Branch 0 taken 172 times.
✓ Branch 1 taken 44 times.
216 for (int j = 0; j < m; j++) {
171 172 input[i][j] = flat_matrix[(static_cast<size_t>(i) * static_cast<size_t>(m)) + static_cast<size_t>(j)];
172 }
173 }
174 17 }
175
176 } // namespace
177
178
1/2
✓ Branch 1 taken 34 times.
✗ Branch 2 not taken.
34 GaivoronskiyMGaussJordanMPI::GaivoronskiyMGaussJordanMPI(const InType &in) {
179 SetTypeOfTask(GetStaticTypeOfTask());
180
1/2
✓ Branch 1 taken 34 times.
✗ Branch 2 not taken.
34 InType tmp(in);
181 GetInput().swap(tmp);
182 34 }
183
184 34 bool GaivoronskiyMGaussJordanMPI::ValidationImpl() {
185 34 int rank = 0;
186 34 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
187
188
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 17 times.
34 if (rank == 0) {
189
1/2
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
17 if (GetInput().empty()) {
190 return true;
191 }
192 size_t cols = GetInput()[0].size();
193 std::size_t total = 0;
194
2/2
✓ Branch 0 taken 44 times.
✓ Branch 1 taken 17 times.
61 for (const auto &row : GetInput()) {
195 44 total += row.size();
196 }
197
3/6
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 17 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 17 times.
17 bool valid = GetOutput().empty() && (cols != 0) && ((cols * GetInput().size()) == total);
198 17 int valid_int = valid ? 1 : 0;
199 17 MPI_Bcast(&valid_int, 1, MPI_INT, 0, MPI_COMM_WORLD);
200 17 return valid;
201 }
202
203 17 int valid_int = 0;
204 17 MPI_Bcast(&valid_int, 1, MPI_INT, 0, MPI_COMM_WORLD);
205 17 return valid_int != 0;
206 }
207
208 34 bool GaivoronskiyMGaussJordanMPI::PreProcessingImpl() {
209 34 int rank = 0;
210 34 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
211
212 GetOutput().clear();
213
214 34 int n = 0;
215 34 int m = 0;
216
217
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 17 times.
34 if (rank == 0) {
218 17 n = static_cast<int>(GetInput().size());
219
1/2
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
17 m = (n > 0) ? static_cast<int>(GetInput()[0].size()) : 0;
220 }
221
222 34 BroadcastMatrixDimensions(n, m);
223
224
2/4
✓ Branch 0 taken 34 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 34 times.
✗ Branch 3 not taken.
34 if (n == 0 || m == 0) {
225 return true;
226 }
227
228
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 17 times.
34 if (rank == 0) {
229 17 FlattenAndBroadcastMatrix(GetInput(), n, m);
230 } else {
231 17 ReceiveAndUnflattenMatrix(GetInput(), n, m);
232 }
233
234 return true;
235 }
236
237 34 bool GaivoronskiyMGaussJordanMPI::RunImpl() {
238 34 int rank = 0;
239 34 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
240
241
1/2
✓ Branch 0 taken 34 times.
✗ Branch 1 not taken.
34 if (GetInput().empty()) {
242 return true;
243 }
244
245 34 std::vector<std::vector<double>> matrix = GetInput();
246 34 int n = static_cast<int>(matrix.size());
247
1/2
✓ Branch 0 taken 34 times.
✗ Branch 1 not taken.
34 int m = (n > 0) ? static_cast<int>(matrix[0].size()) : 0;
248
249
1/2
✓ Branch 0 taken 34 times.
✗ Branch 1 not taken.
34 if (m == 0) {
250 return false;
251 }
252
253
1/2
✓ Branch 1 taken 34 times.
✗ Branch 2 not taken.
34 PerformGaussJordanElimination(matrix, n, m);
254
255
1/2
✓ Branch 1 taken 34 times.
✗ Branch 2 not taken.
34 MatrixAnalysisResult local_result = AnalyzeMatrixAndExtractSolution(matrix, n, m);
256
257 34 bool inconsistent_global = false;
258 34 int rank_global = 0;
259
1/2
✓ Branch 1 taken 34 times.
✗ Branch 2 not taken.
34 MPI_Reduce(&local_result.inconsistent, &inconsistent_global, 1, MPI_C_BOOL, MPI_LOR, 0, MPI_COMM_WORLD);
260
1/2
✓ Branch 1 taken 34 times.
✗ Branch 2 not taken.
34 MPI_Reduce(&local_result.rank, &rank_global, 1, MPI_INT, MPI_MAX, 0, MPI_COMM_WORLD);
261
1/2
✓ Branch 1 taken 34 times.
✗ Branch 2 not taken.
34 MPI_Bcast(&rank_global, 1, MPI_INT, 0, MPI_COMM_WORLD);
262
263 34 int solution_type = 0;
264
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 17 times.
34 if (rank == 0) {
265
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
17 if (inconsistent_global) {
266 solution_type = 0;
267 GetOutput() = std::vector<double>();
268
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
17 } else if (rank_global < m - 1 && rank_global < n) {
269 solution_type = -1;
270 GetOutput() = std::vector<double>();
271 } else {
272
1/2
✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
17 solution_type = 1;
273
1/2
✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
17 GetOutput() = local_result.solution;
274 }
275 }
276
277
1/2
✓ Branch 1 taken 34 times.
✗ Branch 2 not taken.
34 MPI_Bcast(&solution_type, 1, MPI_INT, 0, MPI_COMM_WORLD);
278
279
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 34 times.
34 if (solution_type != 1) {
280 if (rank != 0) {
281 GetOutput() = std::vector<double>();
282 }
283 return false;
284 }
285
286 34 int solution_size = static_cast<int>(GetOutput().size());
287
1/2
✓ Branch 1 taken 34 times.
✗ Branch 2 not taken.
34 MPI_Bcast(&solution_size, 1, MPI_INT, 0, MPI_COMM_WORLD);
288
289
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 17 times.
34 if (rank != 0) {
290
1/2
✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
17 GetOutput().resize(static_cast<size_t>(solution_size));
291 }
292
293
1/2
✓ Branch 0 taken 34 times.
✗ Branch 1 not taken.
34 if (solution_size > 0) {
294
1/2
✓ Branch 1 taken 34 times.
✗ Branch 2 not taken.
34 MPI_Bcast(GetOutput().data(), solution_size, MPI_DOUBLE, 0, MPI_COMM_WORLD);
295 }
296
297 return true;
298 34 }
299
300 34 bool GaivoronskiyMGaussJordanMPI::PostProcessingImpl() {
301 34 return true;
302 }
303
304 } // namespace gaivoronskiy_m_gauss_jordan
305