GCC Code Coverage Report


Directory: ./
File: tasks/dilshodov_a_spmm_double_css/stl/src/ops_stl.cpp
Date: 2026-05-11 08:26:31
Exec Total Coverage
Lines: 80 82 97.6%
Functions: 11 11 100.0%
Branches: 66 102 64.7%

Line Branch Exec Source
1 #include "dilshodov_a_spmm_double_css/stl/include/ops_stl.hpp"
2
3 #include <algorithm>
4 #include <cmath>
5 #include <cstddef>
6 #include <functional>
7 #include <thread>
8 #include <utility>
9 #include <vector>
10
11 #include "dilshodov_a_spmm_double_css/common/include/common.hpp"
12 #include "util/include/util.hpp"
13
14 namespace dilshodov_a_spmm_double_css {
15
16 namespace {
17 constexpr double kEps = 1e-10;
18
19 bool HasValidDimensions(const SparseMatrixCCS &m) {
20
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
48 return m.rows_count > 0 && m.cols_count > 0;
21 }
22
23
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
48 bool HasValidContainers(const SparseMatrixCCS &m) {
24
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
48 if (m.col_ptrs.size() != static_cast<size_t>(m.cols_count) + 1) {
25 return false;
26 }
27
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
48 if (m.row_indices.size() != m.values.size()) {
28 return false;
29 }
30
2/4
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 48 times.
✗ Branch 3 not taken.
48 if (m.col_ptrs.empty() || m.col_ptrs.front() != 0) {
31 return false;
32 }
33
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
48 if (m.col_ptrs.back() < 0) {
34 return false;
35 }
36
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 if (static_cast<size_t>(m.col_ptrs.back()) != m.values.size()) {
37 return false;
38 }
39 return true;
40 }
41
42 48 bool HasValidColumnOrdering(const SparseMatrixCCS &m) {
43
2/2
✓ Branch 0 taken 120 times.
✓ Branch 1 taken 48 times.
168 for (int j = 0; j < m.cols_count; ++j) {
44
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 120 times.
120 if (m.col_ptrs[j] > m.col_ptrs[j + 1]) {
45 return false;
46 }
47 int prev_row = -1;
48
2/2
✓ Branch 0 taken 184 times.
✓ Branch 1 taken 120 times.
304 for (int idx = m.col_ptrs[j]; idx < m.col_ptrs[j + 1]; ++idx) {
49
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 184 times.
184 const int row = m.row_indices[idx];
50
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 184 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 184 times.
184 if (row < 0 || row >= m.rows_count) {
51 return false;
52 }
53
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 184 times.
184 if (row <= prev_row) {
54 return false;
55 }
56 prev_row = row;
57 }
58 }
59 return true;
60 }
61
62
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
48 bool IsValidCCS(const SparseMatrixCCS &m) {
63
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
48 return HasValidDimensions(m) && HasValidContainers(m) && HasValidColumnOrdering(m);
64 }
65
66
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 46 times.
56 void AccumulateColumnProduct(const SparseMatrixCCS &lhs, const SparseMatrixCCS &rhs, int rhs_col,
67 std::vector<double> &acc, std::vector<int> &marker, std::vector<int> &used_rows,
68 std::vector<std::pair<int, double>> &col) {
69 used_rows.clear();
70 col.clear();
71
72
2/2
✓ Branch 0 taken 96 times.
✓ Branch 1 taken 56 times.
152 for (int idx_b = rhs.col_ptrs[rhs_col]; idx_b < rhs.col_ptrs[rhs_col + 1]; ++idx_b) {
73 96 const int k = rhs.row_indices[idx_b];
74 96 const double rhs_value = rhs.values[idx_b];
75
76
2/2
✓ Branch 0 taken 128 times.
✓ Branch 1 taken 96 times.
224 for (int idx_a = lhs.col_ptrs[k]; idx_a < lhs.col_ptrs[k + 1]; ++idx_a) {
77
2/2
✓ Branch 0 taken 96 times.
✓ Branch 1 taken 32 times.
128 const int row = lhs.row_indices[idx_a];
78 128 const double value = lhs.values[idx_a] * rhs_value;
79
80
2/2
✓ Branch 0 taken 96 times.
✓ Branch 1 taken 32 times.
128 if (marker[row] != rhs_col) {
81
1/2
✓ Branch 0 taken 96 times.
✗ Branch 1 not taken.
96 marker[row] = rhs_col;
82
1/2
✓ Branch 0 taken 96 times.
✗ Branch 1 not taken.
96 acc[row] = value;
83 used_rows.push_back(row);
84 } else {
85 32 acc[row] += value;
86 }
87 }
88 }
89
90 56 col.reserve(used_rows.size());
91
2/2
✓ Branch 0 taken 96 times.
✓ Branch 1 taken 56 times.
152 for (int row : used_rows) {
92
1/2
✓ Branch 0 taken 96 times.
✗ Branch 1 not taken.
96 const double value = acc[row];
93
1/2
✓ Branch 0 taken 96 times.
✗ Branch 1 not taken.
96 if (std::abs(value) > kEps) {
94 96 col.emplace_back(row, value);
95 }
96 }
97
98 std::ranges::sort(col, {}, &std::pair<int, double>::first);
99 56 }
100
101 46 void Worker(int j_start, int j_end, const SparseMatrixCCS &lhs, const SparseMatrixCCS &rhs,
102 std::vector<std::vector<std::pair<int, double>>> &column_results) {
103 46 std::vector<double> acc(lhs.rows_count, 0.0);
104
1/4
✓ Branch 1 taken 46 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
46 std::vector<int> marker(lhs.rows_count, -1);
105 46 std::vector<int> used_rows;
106
1/2
✓ Branch 1 taken 46 times.
✗ Branch 2 not taken.
46 used_rows.reserve(256);
107
108
2/2
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 46 times.
102 for (int j = j_start; j < j_end; ++j) {
109
1/2
✓ Branch 1 taken 56 times.
✗ Branch 2 not taken.
56 AccumulateColumnProduct(lhs, rhs, j, acc, marker, used_rows, column_results[j]);
110 }
111 46 }
112
113 24 void BuildOutputFromColumns(const std::vector<std::vector<std::pair<int, double>>> &column_results,
114 SparseMatrixCCS &out) {
115 int offset = 0;
116
2/2
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 24 times.
80 for (int col = 0; col < out.cols_count; ++col) {
117
2/2
✓ Branch 0 taken 96 times.
✓ Branch 1 taken 56 times.
152 for (const auto &[row, value] : column_results[col]) {
118
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 72 times.
96 out.row_indices.push_back(row);
119
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 72 times.
96 out.values.push_back(value);
120 96 ++offset;
121 }
122 56 out.col_ptrs[col + 1] = offset;
123 }
124 24 }
125
126 } // namespace
127
128
1/2
✓ Branch 2 taken 24 times.
✗ Branch 3 not taken.
24 DilshodovASpmmDoubleCssStl::DilshodovASpmmDoubleCssStl(const InType &in) {
129 SetTypeOfTask(GetStaticTypeOfTask());
130 GetInput() = in;
131 24 }
132
133
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 bool DilshodovASpmmDoubleCssStl::ValidationImpl() {
134 const auto &lhs = std::get<0>(GetInput());
135 const auto &rhs = std::get<1>(GetInput());
136
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 IsValidCCS(lhs) && IsValidCCS(rhs) && lhs.cols_count == rhs.rows_count;
137 }
138
139 24 bool DilshodovASpmmDoubleCssStl::PreProcessingImpl() {
140 24 GetOutput() = SparseMatrixCCS{};
141 24 return true;
142 }
143
144 24 bool DilshodovASpmmDoubleCssStl::RunImpl() {
145 const auto &lhs = std::get<0>(GetInput());
146 const auto &rhs = std::get<1>(GetInput());
147 auto &out = GetOutput();
148
149 24 out.rows_count = lhs.rows_count;
150 24 out.cols_count = rhs.cols_count;
151
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 24 times.
24 out.col_ptrs.assign(static_cast<size_t>(out.cols_count) + 1, 0);
152 out.row_indices.clear();
153 out.values.clear();
154
155 24 std::vector<std::vector<std::pair<int, double>>> column_results(rhs.cols_count);
156
157
1/2
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
24 int num_threads = ppc::util::GetNumThreads();
158 24 if (num_threads <= 0) {
159 num_threads = 1;
160 }
161
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 14 times.
24 if (num_threads > rhs.cols_count) {
162 num_threads = std::max(1, rhs.cols_count);
163 }
164
165 24 std::vector<std::thread> threads;
166
1/2
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
24 threads.reserve(num_threads);
167
2/2
✓ Branch 0 taken 46 times.
✓ Branch 1 taken 24 times.
70 for (int tid = 0; tid < num_threads; ++tid) {
168 46 const int j_start = (tid * rhs.cols_count) / num_threads;
169 46 const int j_end = ((tid + 1) * rhs.cols_count) / num_threads;
170
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
46 if (j_start >= j_end) {
171 continue;
172 }
173
1/2
✓ Branch 1 taken 46 times.
✗ Branch 2 not taken.
46 threads.emplace_back(Worker, j_start, j_end, std::cref(lhs), std::cref(rhs), std::ref(column_results));
174 }
175
2/2
✓ Branch 0 taken 46 times.
✓ Branch 1 taken 24 times.
70 for (auto &th : threads) {
176
1/2
✓ Branch 1 taken 46 times.
✗ Branch 2 not taken.
46 th.join();
177 }
178
179
1/2
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
24 BuildOutputFromColumns(column_results, out);
180
181 24 out.non_zeros = static_cast<int>(out.values.size());
182 24 return true;
183 24 }
184
185 24 bool DilshodovASpmmDoubleCssStl::PostProcessingImpl() {
186 24 GetOutput().non_zeros = static_cast<int>(GetOutput().values.size());
187 24 return true;
188 }
189
190 } // namespace dilshodov_a_spmm_double_css
191