GCC Code Coverage Report


Directory: ./
File: tasks/liulin_y_complex_ccs/stl/src/ops_stl.cpp
Date: 2026-06-04 20:25:32
Exec Total Coverage
Lines: 97 102 95.1%
Functions: 11 11 100.0%
Branches: 55 84 65.5%

Line Branch Exec Source
1 #include "liulin_y_complex_ccs/stl/include/ops_stl.hpp"
2
3 #include <algorithm>
4 #include <cmath>
5 #include <complex>
6 #include <cstddef>
7 #include <functional>
8 #include <map>
9 #include <thread>
10 #include <utility>
11 #include <vector>
12
13 #include "liulin_y_complex_ccs/common/include/common.hpp"
14
15 namespace liulin_y_complex_ccs {
16
17 namespace {
18
19 constexpr double kEpsilon = 1e-10;
20
21 using LocalDict = std::map<std::pair<int, int>, std::complex<double>>;
22
23 96 bool IsValidCCS(const CCSMatrix &mat) {
24
2/4
✓ Branch 0 taken 96 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 96 times.
✗ Branch 3 not taken.
96 if (mat.count_rows <= 0 || mat.count_cols <= 0) {
25 return false;
26 }
27
1/2
✓ Branch 0 taken 96 times.
✗ Branch 1 not taken.
96 if (mat.col_index.size() != static_cast<size_t>(mat.count_cols) + 1) {
28 return false;
29 }
30
1/2
✓ Branch 0 taken 96 times.
✗ Branch 1 not taken.
96 if (mat.col_index[0] != 0) {
31 return false;
32 }
33
1/2
✓ Branch 0 taken 96 times.
✗ Branch 1 not taken.
96 if (mat.values.size() != mat.row_index.size()) {
34 return false;
35 }
36
1/2
✓ Branch 0 taken 96 times.
✗ Branch 1 not taken.
96 if (std::cmp_not_equal(mat.col_index.back(), mat.values.size())) {
37 return false;
38 }
39 return true;
40 }
41
42 48 void TransposeCCS(const CCSMatrix &mat, CCSMatrix &mat_t) {
43 48 mat_t.count_rows = mat.count_cols;
44 48 mat_t.count_cols = mat.count_rows;
45 const size_t nnz = mat.values.size();
46 48 mat_t.values.resize(nnz);
47 48 mat_t.row_index.resize(nnz);
48 48 mat_t.col_index.assign(static_cast<size_t>(mat_t.count_cols) + 1, 0);
49
50
2/2
✓ Branch 0 taken 80 times.
✓ Branch 1 taken 48 times.
128 for (size_t i = 0; i < nnz; ++i) {
51 80 mat_t.col_index[static_cast<size_t>(mat.row_index[i]) + 1]++;
52 }
53
2/2
✓ Branch 0 taken 104 times.
✓ Branch 1 taken 48 times.
152 for (int i = 0; i < mat_t.count_cols; ++i) {
54 104 mat_t.col_index[static_cast<size_t>(i) + 1] += mat_t.col_index[static_cast<size_t>(i)];
55 }
56
57 48 std::vector<int> current_pos(mat_t.col_index.begin(), mat_t.col_index.end());
58
2/2
✓ Branch 0 taken 96 times.
✓ Branch 1 taken 48 times.
144 for (int j = 0; j < mat.count_cols; ++j) {
59
2/2
✓ Branch 0 taken 80 times.
✓ Branch 1 taken 96 times.
176 for (int k = mat.col_index[static_cast<size_t>(j)]; k < mat.col_index[static_cast<size_t>(j) + 1]; ++k) {
60 80 const int row = mat.row_index[static_cast<size_t>(k)];
61 80 const int dest = current_pos[static_cast<size_t>(row)]++;
62 80 mat_t.row_index[static_cast<size_t>(dest)] = j;
63 80 mat_t.values[static_cast<size_t>(dest)] = mat.values[static_cast<size_t>(k)];
64 }
65 }
66 48 }
67
68 48 std::vector<int> BuildColumnIndices(const CCSMatrix &mat_a) {
69 48 std::vector<int> a_cols(mat_a.values.size());
70
2/2
✓ Branch 0 taken 104 times.
✓ Branch 1 taken 48 times.
152 for (int j = 0; j < mat_a.count_cols; ++j) {
71
2/2
✓ Branch 0 taken 120 times.
✓ Branch 1 taken 104 times.
224 for (int k = mat_a.col_index[static_cast<size_t>(j)]; k < mat_a.col_index[static_cast<size_t>(j) + 1]; ++k) {
72 120 a_cols[static_cast<size_t>(k)] = j;
73 }
74 }
75 48 return a_cols;
76 }
77
78 120 void ProcessChunk(int start_idx, int end_idx, const CCSMatrix &mat_a, const std::vector<int> &a_cols,
79 const CCSMatrix &mat_b_t, LocalDict &local_map) {
80
2/2
✓ Branch 0 taken 120 times.
✓ Branch 1 taken 120 times.
240 for (int k = start_idx; k < end_idx; ++k) {
81 120 const int row_left = mat_a.row_index[static_cast<size_t>(k)];
82 120 const int col_left = a_cols[static_cast<size_t>(k)];
83 120 const std::complex<double> val_left = mat_a.values[static_cast<size_t>(k)];
84
85 120 const int b_start = mat_b_t.col_index[static_cast<size_t>(col_left)];
86 120 const int b_end = mat_b_t.col_index[static_cast<size_t>(col_left) + 1];
87
88
2/2
✓ Branch 0 taken 80 times.
✓ Branch 1 taken 120 times.
200 for (int idx_p = b_start; idx_p < b_end; ++idx_p) {
89 80 const int col_right = mat_b_t.row_index[static_cast<size_t>(idx_p)];
90 80 const std::complex<double> val_right = mat_b_t.values[static_cast<size_t>(idx_p)];
91
92 80 local_map[{col_right, row_left}] += val_left * val_right;
93 }
94 }
95 120 }
96
97 48 void AggregateLocalMaps(const std::vector<LocalDict> &local_maps, LocalDict &global_map) {
98
2/2
✓ Branch 0 taken 120 times.
✓ Branch 1 taken 48 times.
168 for (const auto &local_map : local_maps) {
99
2/2
✓ Branch 0 taken 80 times.
✓ Branch 1 taken 120 times.
200 for (const auto &[key, value] : local_map) {
100 80 global_map[key] += value;
101 }
102 }
103 48 }
104
105 48 void ConstructResultMatrix(const LocalDict &global_map, int rows, int cols, CCSMatrix &mat_res) {
106 48 mat_res.count_rows = rows;
107
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 mat_res.count_cols = cols;
108 mat_res.values.clear();
109 mat_res.row_index.clear();
110 48 mat_res.col_index.assign(static_cast<size_t>(cols) + 1, 0);
111
112
2/2
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 48 times.
120 for (const auto &[key, value] : global_map) {
113
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
72 if (std::abs(value.real()) > kEpsilon || std::abs(value.imag()) > kEpsilon) {
114 72 const int col = key.first;
115 72 const int row = key.second;
116
117
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 mat_res.values.push_back(value);
118
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 mat_res.row_index.push_back(row);
119 72 mat_res.col_index[static_cast<size_t>(col) + 1]++;
120 }
121 }
122
123
2/2
✓ Branch 0 taken 96 times.
✓ Branch 1 taken 48 times.
144 for (int i = 0; i < cols; ++i) {
124 96 mat_res.col_index[static_cast<size_t>(i) + 1] += mat_res.col_index[static_cast<size_t>(i)];
125 }
126 48 }
127
128 } // namespace
129
130
1/2
✓ Branch 2 taken 48 times.
✗ Branch 3 not taken.
48 LiulinYComplexCcsStl::LiulinYComplexCcsStl(const InType &in) : BaseTask() {
131 SetTypeOfTask(GetStaticTypeOfTask());
132 GetInput() = in;
133 48 }
134
135 48 bool LiulinYComplexCcsStl::ValidationImpl() {
136 48 const auto &mat_a = GetInput().first;
137 48 const auto &mat_b = GetInput().second;
138
3/6
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 48 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 48 times.
48 return IsValidCCS(mat_a) && IsValidCCS(mat_b) && (mat_a.count_cols == mat_b.count_rows);
139 }
140
141 48 bool LiulinYComplexCcsStl::PreProcessingImpl() {
142 48 return true;
143 }
144
145 48 bool LiulinYComplexCcsStl::RunImpl() {
146 48 const auto &mat_a = GetInput().first;
147
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 const auto &mat_b = GetInput().second;
148 auto &mat_res = GetOutput();
149
150 48 const int nnz_a = static_cast<int>(mat_a.values.size());
151
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 if (nnz_a == 0) {
152 mat_res.count_rows = mat_a.count_rows;
153 mat_res.count_cols = mat_b.count_cols;
154 mat_res.col_index.assign(static_cast<size_t>(mat_res.count_cols) + 1, 0);
155 return true;
156 }
157
158 48 CCSMatrix mat_b_t;
159
1/2
✓ Branch 1 taken 48 times.
✗ Branch 2 not taken.
48 TransposeCCS(mat_b, mat_b_t);
160
1/2
✓ Branch 1 taken 48 times.
✗ Branch 2 not taken.
48 std::vector<int> a_cols = BuildColumnIndices(mat_a);
161
162 48 unsigned int hw = std::thread::hardware_concurrency();
163
1/2
✓ Branch 1 taken 48 times.
✗ Branch 2 not taken.
48 int num_threads = std::min(nnz_a, (hw == 0) ? 1 : static_cast<int>(hw));
164
165 48 std::vector<std::thread> threads;
166
1/2
✓ Branch 1 taken 48 times.
✗ Branch 2 not taken.
48 std::vector<LocalDict> local_maps(static_cast<size_t>(num_threads));
167 48 int chunk = nnz_a / num_threads;
168 48 int rem = nnz_a % num_threads;
169
170 48 int start = 0;
171
2/2
✓ Branch 0 taken 120 times.
✓ Branch 1 taken 48 times.
168 for (int i = 0; i < num_threads; ++i) {
172
1/2
✓ Branch 0 taken 120 times.
✗ Branch 1 not taken.
120 int end = start + chunk + (i < rem ? 1 : 0);
173
1/2
✓ Branch 1 taken 120 times.
✗ Branch 2 not taken.
120 threads.emplace_back(ProcessChunk, start, end, std::ref(mat_a), std::ref(a_cols), std::ref(mat_b_t),
174
1/2
✓ Branch 1 taken 120 times.
✗ Branch 2 not taken.
120 std::ref(local_maps[static_cast<size_t>(i)]));
175 120 start = end;
176 }
177
178
2/2
✓ Branch 0 taken 120 times.
✓ Branch 1 taken 48 times.
168 for (auto &t : threads) {
179
1/2
✓ Branch 0 taken 120 times.
✗ Branch 1 not taken.
120 if (t.joinable()) {
180
1/2
✓ Branch 1 taken 120 times.
✗ Branch 2 not taken.
120 t.join();
181 }
182 }
183
184 LocalDict global_map;
185
1/2
✓ Branch 1 taken 48 times.
✗ Branch 2 not taken.
48 AggregateLocalMaps(local_maps, global_map);
186
1/2
✓ Branch 1 taken 48 times.
✗ Branch 2 not taken.
48 ConstructResultMatrix(global_map, mat_a.count_rows, mat_b.count_cols, mat_res);
187
188 return true;
189 96 }
190
191 48 bool LiulinYComplexCcsStl::PostProcessingImpl() {
192 48 return true;
193 }
194
195 } // namespace liulin_y_complex_ccs
196