GCC Code Coverage Report


Directory: ./
File: tasks/safaryan_a_sparse_matrix_mult_crs/omp/src/ops_omp.cpp
Date: 2026-06-04 20:25:32
Exec Total Coverage
Lines: 71 73 97.3%
Functions: 9 9 100.0%
Branches: 62 90 68.9%

Line Branch Exec Source
1 #include "safaryan_a_sparse_matrix_mult_crs/omp/include/ops_omp.hpp"
2
3 #include <algorithm>
4 #include <cmath>
5 #include <cstddef>
6 #include <vector>
7
8 #include "safaryan_a_sparse_matrix_mult_crs/common/include/common.hpp"
9 #include "util/include/util.hpp"
10
11 namespace safaryan_a_sparse_matrix_mult_crs {
12
13
1/2
✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
20 SafaryanATaskOMP::SafaryanATaskOMP(const InType &in) {
14 SetTypeOfTask(GetStaticTypeOfTask());
15 GetInput() = in;
16 20 GetOutput() = SparseMatrixCCS();
17 20 }
18
19 40 bool SafaryanATaskOMP::IsMatrixValid(const SparseMatrixCCS &matrix) {
20
2/4
✓ Branch 0 taken 40 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 40 times.
40 if (matrix.rows < 0 || matrix.cols < 0) {
21 return false;
22 }
23
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
40 if (matrix.col_ptrs.size() != static_cast<size_t>(matrix.cols) + 1) {
24 return false;
25 }
26
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
40 if (matrix.values.size() != matrix.row_indices.size()) {
27 return false;
28 }
29
30
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 40 times.
40 if (matrix.col_ptrs.empty() || matrix.col_ptrs[0] != 0) {
31 return false;
32 }
33
34
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
40 const int total_elements = static_cast<int>(matrix.values.size());
35
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
40 if (matrix.col_ptrs[matrix.cols] != total_elements) {
36 return false;
37 }
38
39
2/2
✓ Branch 0 taken 116 times.
✓ Branch 1 taken 40 times.
156 for (size_t i = 0; i < matrix.col_ptrs.size() - 1; ++i) {
40
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 116 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 116 times.
116 if (matrix.col_ptrs[i] > matrix.col_ptrs[i + 1] || matrix.col_ptrs[i] < 0) {
41 return false;
42 }
43 }
44
45
2/2
✓ Branch 0 taken 144 times.
✓ Branch 1 taken 40 times.
184 for (size_t i = 0; i < matrix.row_indices.size(); ++i) {
46
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 144 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 144 times.
144 if (matrix.row_indices[i] < 0 || matrix.row_indices[i] >= matrix.rows) {
47 return false;
48 }
49 }
50
51 return true;
52 }
53
54
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 bool SafaryanATaskOMP::ValidationImpl() {
55 const auto &[a, b] = GetInput();
56
57
2/4
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
20 if (!IsMatrixValid(a) || !IsMatrixValid(b)) {
58 return false;
59 }
60
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 if (a.cols != b.rows) {
61 return false;
62 }
63
64 return true;
65 }
66
67 20 bool SafaryanATaskOMP::PreProcessingImpl() {
68 const auto &[a, b] = GetInput();
69 20 GetOutput() = SparseMatrixCCS(a.rows, b.cols);
70 20 return true;
71 }
72
73 namespace {
74 56 void ProcessColumn(const SparseMatrixCCS &a, const SparseMatrixCCS &b, int j, std::vector<double> &temp) {
75
2/2
✓ Branch 0 taken 176 times.
✓ Branch 1 taken 56 times.
232 for (int k = 0; k < a.cols; ++k) {
76 double b_val = 0.0;
77
2/2
✓ Branch 0 taken 176 times.
✓ Branch 1 taken 120 times.
296 for (int b_idx = b.col_ptrs[j]; b_idx < b.col_ptrs[j + 1]; ++b_idx) {
78
2/2
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 120 times.
176 if (b.row_indices[b_idx] == k) {
79 56 b_val = b.values[b_idx];
80 56 break;
81 }
82 }
83
84
2/2
✓ Branch 0 taken 120 times.
✓ Branch 1 taken 56 times.
176 if (b_val == 0.0) {
85 120 continue;
86 }
87
88
2/2
✓ Branch 0 taken 84 times.
✓ Branch 1 taken 56 times.
140 for (int a_idx = a.col_ptrs[k]; a_idx < a.col_ptrs[k + 1]; ++a_idx) {
89 84 const int i = a.row_indices[a_idx];
90 84 const double a_val = a.values[a_idx];
91 84 temp[i] += a_val * b_val;
92 }
93 }
94 56 }
95
96 42 SparseMatrixCCS BuildColumnRange(const SparseMatrixCCS &a, const SparseMatrixCCS &b, int begin_col, int end_col) {
97 42 SparseMatrixCCS part(a.rows, end_col - begin_col);
98
1/2
✓ Branch 1 taken 42 times.
✗ Branch 2 not taken.
42 std::vector<double> temp(a.rows, 0.0);
99
100
2/2
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 42 times.
98 for (int j = begin_col; j < end_col; ++j) {
101 56 part.col_ptrs[j - begin_col] = static_cast<int>(part.values.size());
102 56 ProcessColumn(a, b, j, temp);
103
104
2/2
✓ Branch 0 taken 168 times.
✓ Branch 1 taken 56 times.
224 for (int i = 0; i < a.rows; ++i) {
105
2/2
✓ Branch 0 taken 84 times.
✓ Branch 1 taken 84 times.
168 if (std::abs(temp[i]) > 1e-10) {
106
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 76 times.
84 part.values.push_back(temp[i]);
107
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 76 times.
84 part.row_indices.push_back(i);
108 84 temp[i] = 0.0;
109 }
110 }
111 }
112
113
1/2
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
42 part.col_ptrs[end_col - begin_col] = static_cast<int>(part.values.size());
114 42 return part;
115 }
116 } // namespace
117
118 20 SparseMatrixCCS SafaryanATaskOMP::MultiplyMatrices(const SparseMatrixCCS &a, const SparseMatrixCCS &b) {
119 20 SparseMatrixCCS result(a.rows, b.cols);
120
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 if (b.cols == 0) {
121 return result;
122 }
123
124
5/6
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 14 times.
✓ Branch 5 taken 15 times.
✓ Branch 6 taken 5 times.
26 const int threads_count = std::max(1, std::min(ppc::util::GetNumThreads(), b.cols));
125
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 std::vector<SparseMatrixCCS> parts(threads_count);
126
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 std::vector<int> begin_cols(threads_count + 1, 0);
127
128
2/2
✓ Branch 0 taken 62 times.
✓ Branch 1 taken 20 times.
82 for (int i = 0; i <= threads_count; ++i) {
129 62 begin_cols[i] = (b.cols * i) / threads_count;
130 }
131
132 20 #pragma omp parallel for num_threads(threads_count) default(none) shared(a, b, begin_cols, parts, threads_count)
133 for (int thread_id = 0; thread_id < threads_count; ++thread_id) {
134 parts[thread_id] = BuildColumnRange(a, b, begin_cols[thread_id], begin_cols[thread_id + 1]);
135 }
136
137
2/2
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 20 times.
62 for (int part_id = 0; part_id < threads_count; ++part_id) {
138 42 const SparseMatrixCCS &part = parts[part_id];
139 42 const int column_offset = begin_cols[part_id];
140
2/2
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 42 times.
98 for (int local_col = 0; local_col < part.cols; ++local_col) {
141
1/2
✓ Branch 1 taken 56 times.
✗ Branch 2 not taken.
56 result.col_ptrs[column_offset + local_col] = static_cast<int>(result.values.size());
142
1/2
✓ Branch 1 taken 56 times.
✗ Branch 2 not taken.
56 const int begin = part.col_ptrs[local_col];
143 56 const int end = part.col_ptrs[local_col + 1];
144
1/2
✓ Branch 1 taken 56 times.
✗ Branch 2 not taken.
56 result.values.insert(result.values.end(), part.values.begin() + begin, part.values.begin() + end);
145
1/2
✓ Branch 1 taken 56 times.
✗ Branch 2 not taken.
56 result.row_indices.insert(result.row_indices.end(), part.row_indices.begin() + begin,
146 part.row_indices.begin() + end);
147 }
148 }
149
150
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 result.col_ptrs[b.cols] = static_cast<int>(result.values.size());
151 return result;
152 20 }
153
154 20 bool SafaryanATaskOMP::RunImpl() {
155 const auto &[a, b] = GetInput();
156 20 GetOutput() = MultiplyMatrices(a, b);
157 20 return true;
158 }
159
160 20 bool SafaryanATaskOMP::PostProcessingImpl() {
161 20 return true;
162 }
163
164 } // namespace safaryan_a_sparse_matrix_mult_crs
165