GCC Code Coverage Report


Directory: ./
File: tasks/kapanova_s_sparse_matrix_mult_ccs/stl/src/ops_stl.cpp
Date: 2026-05-11 08:26:31
Exec Total Coverage
Lines: 75 78 96.2%
Functions: 8 8 100.0%
Branches: 56 90 62.2%

Line Branch Exec Source
1 #include "kapanova_s_sparse_matrix_mult_ccs/stl/include/ops_stl.hpp"
2
3 #include <algorithm>
4 #include <cstddef>
5 #include <functional>
6 #include <thread>
7 #include <vector>
8
9 #include "kapanova_s_sparse_matrix_mult_ccs/common/include/common.hpp"
10
11 namespace kapanova_s_sparse_matrix_mult_ccs {
12
13
1/2
✓ Branch 2 taken 40 times.
✗ Branch 3 not taken.
40 KapanovaSSparseMatrixMultCCSSTL::KapanovaSSparseMatrixMultCCSSTL(const InType &in) {
14 SetTypeOfTask(GetStaticTypeOfTask());
15 GetInput() = in;
16 40 }
17
18 40 bool KapanovaSSparseMatrixMultCCSSTL::ValidationImpl() {
19 const auto &a = std::get<0>(GetInput());
20 const auto &b = std::get<1>(GetInput());
21
22
1/2
✓ Branch 0 taken 40 times.
✗ Branch 1 not taken.
40 if (a.cols != b.rows) {
23 return false;
24 }
25
3/6
✓ Branch 0 taken 40 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 40 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 40 times.
✗ Branch 5 not taken.
40 if (a.rows == 0 || a.cols == 0 || b.rows == 0 || b.cols == 0) {
26 return false;
27 }
28
1/2
✓ Branch 0 taken 40 times.
✗ Branch 1 not taken.
40 if (a.col_ptrs.size() != static_cast<size_t>(a.cols + 1)) {
29 return false;
30 }
31
1/2
✓ Branch 0 taken 40 times.
✗ Branch 1 not taken.
40 if (b.col_ptrs.size() != static_cast<size_t>(b.cols + 1)) {
32 return false;
33 }
34
2/4
✓ Branch 0 taken 40 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 40 times.
✗ Branch 3 not taken.
40 if (a.col_ptrs[0] != 0 || b.col_ptrs[0] != 0) {
35 return false;
36 }
37
1/2
✓ Branch 0 taken 40 times.
✗ Branch 1 not taken.
40 if (a.col_ptrs[a.cols] != a.nnz) {
38 return false;
39 }
40
1/2
✓ Branch 0 taken 40 times.
✗ Branch 1 not taken.
40 if (b.col_ptrs[b.cols] != b.nnz) {
41 return false;
42 }
43
2/4
✓ Branch 0 taken 40 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 40 times.
✗ Branch 3 not taken.
40 if (a.values.size() != static_cast<size_t>(a.nnz) || a.row_indices.size() != static_cast<size_t>(a.nnz)) {
44 return false;
45 }
46
2/4
✓ Branch 0 taken 40 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 40 times.
40 if (b.values.size() != static_cast<size_t>(b.nnz) || b.row_indices.size() != static_cast<size_t>(b.nnz)) {
47 return false;
48 }
49
50 return true;
51 }
52
53 40 bool KapanovaSSparseMatrixMultCCSSTL::PreProcessingImpl() {
54 40 return true;
55 }
56
57 40 bool KapanovaSSparseMatrixMultCCSSTL::PostProcessingImpl() {
58 40 return true;
59 }
60
61 namespace {
62
63 struct ThreadLocalData {
64 std::vector<double> accum;
65 std::vector<char> mask;
66 std::vector<size_t> active;
67
68
1/2
✓ Branch 1 taken 96 times.
✗ Branch 2 not taken.
96 explicit ThreadLocalData(size_t rows) {
69
1/2
✓ Branch 1 taken 96 times.
✗ Branch 2 not taken.
96 accum.assign(rows, 0.0);
70
1/4
✓ Branch 1 taken 96 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
96 mask.assign(rows, 0);
71
1/2
✓ Branch 1 taken 96 times.
✗ Branch 2 not taken.
96 active.reserve(rows / 20);
72 96 }
73
74 void ClearActive() {
75
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 96 times.
96 for (size_t i : active) {
76 accum[i] = 0.0;
77 mask[i] = 0;
78 }
79 active.clear();
80 }
81 };
82
83 96 void ProcessColumn(int j, const CCSMatrix &a, const CCSMatrix &b, std::vector<size_t> &out_rows,
84 std::vector<double> &out_vals, ThreadLocalData &local) {
85 local.ClearActive();
86
87
2/2
✓ Branch 0 taken 144 times.
✓ Branch 1 taken 96 times.
240 for (size_t k = b.col_ptrs[j]; k < b.col_ptrs[j + 1]; ++k) {
88 144 size_t row_b = b.row_indices[k];
89 144 double val_b = b.values[k];
90
91
2/2
✓ Branch 0 taken 176 times.
✓ Branch 1 taken 144 times.
320 for (size_t zc = a.col_ptrs[row_b]; zc < a.col_ptrs[row_b + 1]; ++zc) {
92 176 size_t i = a.row_indices[zc];
93
2/2
✓ Branch 0 taken 128 times.
✓ Branch 1 taken 48 times.
176 double val_a = a.values[zc];
94
95 176 local.accum[i] += val_a * val_b;
96
2/2
✓ Branch 0 taken 128 times.
✓ Branch 1 taken 48 times.
176 if (local.mask[i] == 0) {
97 128 local.mask[i] = 1;
98
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 128 times.
128 local.active.push_back(i);
99 }
100 }
101 }
102
103 std::ranges::sort(local.active);
104
105
3/4
✓ Branch 0 taken 128 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 128 times.
✓ Branch 3 taken 96 times.
224 for (size_t i : local.active) {
106
1/2
✓ Branch 0 taken 128 times.
✗ Branch 1 not taken.
128 if (local.accum[i] != 0.0) {
107 out_rows.push_back(i);
108 out_vals.push_back(local.accum[i]);
109 }
110 }
111 96 }
112
113 96 void WorkerTask(const CCSMatrix &a, const CCSMatrix &b, int start, int end, std::vector<std::vector<size_t>> &rows,
114 std::vector<std::vector<double>> &vals) {
115 96 ThreadLocalData local(a.rows);
116
117
2/2
✓ Branch 0 taken 96 times.
✓ Branch 1 taken 96 times.
192 for (int j = start; j < end; ++j) {
118
1/2
✓ Branch 1 taken 96 times.
✗ Branch 2 not taken.
96 ProcessColumn(j, a, b, rows[j], vals[j], local);
119 }
120 96 }
121
122 } // namespace
123
124 40 bool KapanovaSSparseMatrixMultCCSSTL::RunImpl() {
125 const auto &a = std::get<0>(GetInput());
126 const auto &b = std::get<1>(GetInput());
127 OutType &c = GetOutput();
128
129 40 c.rows = a.rows;
130 40 c.cols = b.cols;
131 40 c.col_ptrs.assign(c.cols + 1, 0);
132 40 c.nnz = 0;
133
134 40 unsigned int num_threads = std::thread::hardware_concurrency();
135
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
40 if (num_threads == 0) {
136 num_threads = 2;
137 }
138
139 40 std::vector<std::vector<size_t>> temp_rows(c.cols);
140
1/2
✓ Branch 1 taken 40 times.
✗ Branch 2 not taken.
40 std::vector<std::vector<double>> temp_vals(c.cols);
141 40 std::vector<std::thread> threads;
142
143 40 size_t chunk = (c.cols + num_threads - 1) / num_threads;
144
145
1/2
✓ Branch 0 taken 136 times.
✗ Branch 1 not taken.
136 for (unsigned int thread_id = 0; thread_id < num_threads; ++thread_id) {
146 136 size_t start = thread_id * chunk;
147
2/2
✓ Branch 0 taken 96 times.
✓ Branch 1 taken 40 times.
136 size_t end = std::min(start + chunk, c.cols);
148
2/2
✓ Branch 0 taken 96 times.
✓ Branch 1 taken 40 times.
136 if (start >= c.cols) {
149 break;
150 }
151
152 192 threads.emplace_back(WorkerTask, std::cref(a), std::cref(b), static_cast<int>(start), static_cast<int>(end),
153
1/2
✓ Branch 1 taken 96 times.
✗ Branch 2 not taken.
96 std::ref(temp_rows), std::ref(temp_vals));
154 }
155
156
2/2
✓ Branch 0 taken 96 times.
✓ Branch 1 taken 40 times.
136 for (auto &th : threads) {
157
1/2
✓ Branch 0 taken 96 times.
✗ Branch 1 not taken.
96 if (th.joinable()) {
158
1/2
✓ Branch 1 taken 96 times.
✗ Branch 2 not taken.
96 th.join();
159 }
160 }
161
162 size_t offset = 0;
163
2/2
✓ Branch 0 taken 96 times.
✓ Branch 1 taken 40 times.
136 for (size_t j = 0; j < c.cols; ++j) {
164 96 c.col_ptrs[j] = offset;
165 96 offset += temp_rows[j].size();
166 }
167 40 c.col_ptrs[c.cols] = offset;
168 40 c.nnz = offset;
169
170
1/2
✓ Branch 1 taken 40 times.
✗ Branch 2 not taken.
40 c.values.resize(c.nnz);
171
1/2
✓ Branch 1 taken 40 times.
✗ Branch 2 not taken.
40 c.row_indices.resize(c.nnz);
172
173
2/2
✓ Branch 0 taken 96 times.
✓ Branch 1 taken 40 times.
136 for (size_t j = 0; j < c.cols; ++j) {
174 96 size_t start = c.col_ptrs[j];
175 size_t n = temp_rows[j].size();
176
2/2
✓ Branch 0 taken 128 times.
✓ Branch 1 taken 96 times.
224 for (size_t idx = 0; idx < n; ++idx) {
177 128 c.row_indices[start + idx] = temp_rows[j][idx];
178 128 c.values[start + idx] = temp_vals[j][idx];
179 }
180 }
181
182 40 return true;
183 40 }
184
185 } // namespace kapanova_s_sparse_matrix_mult_ccs
186