GCC Code Coverage Report


Directory: ./
File: tasks/safaryan_a_sparse_matrix_mult_crs/tbb/src/ops_tbb.cpp
Date: 2026-06-04 20:25:32
Exec Total Coverage
Lines: 70 72 97.2%
Functions: 10 10 100.0%
Branches: 57 88 64.8%

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