GCC Code Coverage Report


Directory: ./
File: tasks/safaryan_a_sparse_matrix_mult_crs/stl/src/ops_stl.cpp
Date: 2026-06-04 20:25:32
Exec Total Coverage
Lines: 74 76 97.4%
Functions: 10 10 100.0%
Branches: 62 92 67.4%

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