GCC Code Coverage Report


Directory: ./
File: tasks/posternak_a_crs_mul_complex_matrix/omp/src/ops_omp.cpp
Date: 2026-04-02 17:12:27
Exec Total Coverage
Lines: 61 61 100.0%
Functions: 8 8 100.0%
Branches: 39 74 52.7%

Line Branch Exec Source
1 #include "posternak_a_crs_mul_complex_matrix/omp/include/ops_omp.hpp"
2
3 #include <algorithm>
4 #include <cmath>
5 #include <complex>
6 #include <cstddef>
7 #include <unordered_map>
8 #include <utility>
9 #include <vector>
10
11 #include "posternak_a_crs_mul_complex_matrix/common/include/common.hpp"
12
13 namespace {
14
15 40 size_t ComputeRowNoZeroCount(const posternak_a_crs_mul_complex_matrix::CRSMatrix &a,
16 const posternak_a_crs_mul_complex_matrix::CRSMatrix &b, int row, double threshold) {
17 std::unordered_map<int, std::complex<double>> row_sum;
18
19
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 40 times.
88 for (int idx_a = a.index_row[row]; idx_a < a.index_row[row + 1]; ++idx_a) {
20 48 int col_a = a.index_col[idx_a];
21 48 auto val_a = a.values[idx_a];
22
23
2/2
✓ Branch 0 taken 68 times.
✓ Branch 1 taken 48 times.
116 for (int idx_b = b.index_row[col_a]; idx_b < b.index_row[col_a + 1]; ++idx_b) {
24
1/2
✓ Branch 1 taken 68 times.
✗ Branch 2 not taken.
68 int col_b = b.index_col[idx_b];
25
1/2
✓ Branch 1 taken 68 times.
✗ Branch 2 not taken.
68 auto val_b = b.values[idx_b];
26 row_sum[col_b] += val_a * val_b;
27 }
28 }
29
30 size_t local = 0;
31
2/2
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 40 times.
96 for (const auto &[col, val] : row_sum) {
32
1/2
✓ Branch 0 taken 56 times.
✗ Branch 1 not taken.
56 if (std::abs(val) > threshold) {
33 56 ++local;
34 }
35 }
36 40 return local;
37 }
38
39 16 void BuildResultStructure(posternak_a_crs_mul_complex_matrix::CRSMatrix &res, std::vector<size_t> &row_prefix) {
40
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 16 times.
40 for (int i = 1; i < res.rows; ++i) {
41 24 row_prefix[i] += row_prefix[i - 1];
42 }
43
44
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 const size_t total = row_prefix.empty() ? 0 : row_prefix.back();
45 16 res.values.resize(total);
46 16 res.index_col.resize(total);
47 16 res.index_row.resize(res.rows + 1);
48
49
2/2
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 16 times.
72 for (int i = 0; i <= res.rows; ++i) {
50
2/2
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 16 times.
56 res.index_row[i] = (i == 0 ? 0 : static_cast<int>(row_prefix[i - 1]));
51 }
52 16 }
53
54 40 void ComputeAndWriteRow(const posternak_a_crs_mul_complex_matrix::CRSMatrix &a,
55 const posternak_a_crs_mul_complex_matrix::CRSMatrix &b,
56 posternak_a_crs_mul_complex_matrix::CRSMatrix &res, int row, double threshold) {
57 std::unordered_map<int, std::complex<double>> row_sum;
58
59
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 40 times.
88 for (int idx_a = a.index_row[row]; idx_a < a.index_row[row + 1]; ++idx_a) {
60 48 int col_a = a.index_col[idx_a];
61 48 auto val_a = a.values[idx_a];
62
63
2/2
✓ Branch 0 taken 68 times.
✓ Branch 1 taken 48 times.
116 for (int idx_b = b.index_row[col_a]; idx_b < b.index_row[col_a + 1]; ++idx_b) {
64
1/2
✓ Branch 1 taken 68 times.
✗ Branch 2 not taken.
68 int col_b = b.index_col[idx_b];
65
1/2
✓ Branch 1 taken 68 times.
✗ Branch 2 not taken.
68 auto val_b = b.values[idx_b];
66 row_sum[col_b] += val_a * val_b;
67 }
68 }
69
70
1/2
✓ Branch 1 taken 40 times.
✗ Branch 2 not taken.
40 std::vector<std::pair<int, std::complex<double>>> sorted(row_sum.begin(), row_sum.end());
71
72
1/22
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✓ Branch 12 taken 16 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
16 std::ranges::sort(sorted, [](const auto &p1, const auto &p2) { return p1.first < p2.first; });
73
74 40 size_t pos = res.index_row[row];
75
2/2
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 40 times.
96 for (const auto &[col_idx, value] : sorted) {
76
1/2
✓ Branch 0 taken 56 times.
✗ Branch 1 not taken.
56 if (std::abs(value) > threshold) {
77 56 res.values[pos] = value;
78 56 res.index_col[pos] = col_idx;
79 56 ++pos;
80 }
81 }
82 40 }
83
84 } // namespace
85
86 namespace posternak_a_crs_mul_complex_matrix {
87
88
1/2
✓ Branch 2 taken 24 times.
✗ Branch 3 not taken.
24 PosternakACRSMulComplexMatrixOMP::PosternakACRSMulComplexMatrixOMP(const InType &in) {
89 SetTypeOfTask(GetStaticTypeOfTask());
90 GetInput() = in;
91 24 GetOutput() = CRSMatrix{};
92 24 }
93
94 24 bool PosternakACRSMulComplexMatrixOMP::ValidationImpl() {
95 const auto &input = GetInput();
96 24 const auto &a = input.first;
97 24 const auto &b = input.second;
98
3/6
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 24 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 24 times.
24 return a.IsValid() && b.IsValid() && a.cols == b.rows;
99 }
100
101 24 bool PosternakACRSMulComplexMatrixOMP::PreProcessingImpl() {
102 const auto &input = GetInput();
103 const auto &a = input.first;
104 const auto &b = input.second;
105 auto &res = GetOutput();
106
107 24 res.rows = a.rows;
108 24 res.cols = b.cols;
109 24 return true;
110 }
111
112 24 bool PosternakACRSMulComplexMatrixOMP::RunImpl() {
113 const auto &input = GetInput();
114 24 const auto &a = input.first;
115
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 4 times.
24 const auto &b = input.second;
116 auto &res = GetOutput();
117
118
4/4
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 16 times.
24 if (a.values.empty() || b.values.empty()) {
119 res.values.clear();
120 res.index_col.clear();
121 8 res.index_row.assign(res.rows + 1, 0);
122 8 return true;
123 }
124
125 constexpr double kThreshold = 1e-12;
126 16 std::vector<size_t> no_zero_rows(res.rows, 0);
127
128 // каждый поток определяет количество ненулевых элементов в своих строках
129
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 #pragma omp parallel for default(none) shared(a, b, res, no_zero_rows) schedule(dynamic)
130 for (int row = 0; row < res.rows; ++row) {
131 no_zero_rows[row] = ComputeRowNoZeroCount(a, b, row, kThreshold);
132 }
133
134 // структурируем результат, чтобы избежать конфликта потоков (предотвращаем гонку данных)
135 #pragma omp single
136 {
137 16 BuildResultStructure(res, no_zero_rows);
138 }
139
140 // записываем результат в итоговый массив параллельно
141 16 #pragma omp parallel for default(none) shared(a, b, res) schedule(dynamic)
142 for (int row = 0; row < res.rows; ++row) {
143 ComputeAndWriteRow(a, b, res, row, kThreshold);
144 }
145
146
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 return res.IsValid();
147 }
148
149 24 bool PosternakACRSMulComplexMatrixOMP::PostProcessingImpl() {
150 24 return GetOutput().IsValid();
151 }
152
153 } // namespace posternak_a_crs_mul_complex_matrix
154