GCC Code Coverage Report


Directory: ./
File: tasks/dilshodov_a_spmm_double_css/omp/src/ops_omp.cpp
Date: 2026-05-11 08:26:31
Exec Total Coverage
Lines: 61 62 98.4%
Functions: 10 10 100.0%
Branches: 50 76 65.8%

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