GCC Code Coverage Report


Directory: ./
File: tasks/borunov_v_complex_ccs/omp/src/ops_omp.cpp
Date: 2026-05-11 08:26:31
Exec Total Coverage
Lines: 64 65 98.5%
Functions: 8 8 100.0%
Branches: 42 54 77.8%

Line Branch Exec Source
1 #include "borunov_v_complex_ccs/omp/include/ops_omp.hpp"
2
3 #include <omp.h>
4
5 #include <cmath>
6 #include <complex>
7 #include <cstddef>
8 #include <vector>
9
10 #include "borunov_v_complex_ccs/common/include/common.hpp"
11 #include "util/include/util.hpp"
12
13 namespace borunov_v_complex_ccs {
14
15
1/2
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
12 BorunovVComplexCcsOMP::BorunovVComplexCcsOMP(const InType &in) {
16 SetTypeOfTask(GetStaticTypeOfTask());
17 GetInput() = in;
18
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 GetOutput().resize(1);
19 12 }
20
21 12 bool BorunovVComplexCcsOMP::ValidationImpl() {
22 const auto &a = GetInput().first;
23 const auto &b = GetInput().second;
24
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 if (a.num_cols != b.num_rows) {
25 return false;
26 }
27
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 if (a.col_ptrs.size() != static_cast<std::size_t>(a.num_cols) + 1 ||
28
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 b.col_ptrs.size() != static_cast<std::size_t>(b.num_cols) + 1) {
29 return false;
30 }
31 return true;
32 }
33
34 12 bool BorunovVComplexCcsOMP::PreProcessingImpl() {
35 const auto &a = GetInput().first;
36 const auto &b = GetInput().second;
37 auto &c = GetOutput()[0];
38
39 12 c.num_rows = a.num_rows;
40 12 c.num_cols = b.num_cols;
41
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
12 c.col_ptrs.assign(c.num_cols + 1, 0);
42 c.values.clear();
43 c.row_indices.clear();
44
45 12 return true;
46 }
47
48 namespace {
49
50 160 void CustomShellSort(std::vector<int> &touched) {
51
2/2
✓ Branch 0 taken 400 times.
✓ Branch 1 taken 160 times.
560 for (std::size_t gap = touched.size() / 2; gap > 0; gap /= 2) {
52
2/2
✓ Branch 0 taken 2816 times.
✓ Branch 1 taken 400 times.
3216 for (std::size_t i = gap; i < touched.size(); ++i) {
53 2816 int temp = touched[i];
54 std::size_t j = i;
55
4/4
✓ Branch 0 taken 3632 times.
✓ Branch 1 taken 432 times.
✓ Branch 2 taken 1248 times.
✓ Branch 3 taken 2384 times.
4064 while (j >= gap && touched[j - gap] > temp) {
56 1248 touched[j] = touched[j - gap];
57 j -= gap;
58 }
59 2816 touched[j] = temp;
60 }
61 }
62 160 }
63
64
2/2
✓ Branch 0 taken 127 times.
✓ Branch 1 taken 33 times.
160 void ProcessColumn(int j, const SparseMatrix &a, const SparseMatrix &b, int tid, int jstart,
65 std::vector<std::complex<double>> &acc, std::vector<int> &marker, std::vector<int> &touched,
66 std::vector<std::vector<std::complex<double>>> &t_values,
67 std::vector<std::vector<int>> &t_row_indices, std::vector<std::vector<int>> &t_col_nnz) {
68 touched.clear();
69
70
2/2
✓ Branch 0 taken 616 times.
✓ Branch 1 taken 160 times.
776 for (int bk = b.col_ptrs[j]; bk < b.col_ptrs[j + 1]; ++bk) {
71 616 const int p = b.row_indices[bk];
72 616 const std::complex<double> bval = b.values[bk];
73
74
2/2
✓ Branch 0 taken 1892 times.
✓ Branch 1 taken 616 times.
2508 for (int ak = a.col_ptrs[p]; ak < a.col_ptrs[p + 1]; ++ak) {
75
2/2
✓ Branch 0 taken 1336 times.
✓ Branch 1 taken 556 times.
1892 const int i = a.row_indices[ak];
76
2/2
✓ Branch 0 taken 1336 times.
✓ Branch 1 taken 556 times.
1892 acc[i] += a.values[ak] * bval;
77
2/2
✓ Branch 0 taken 1336 times.
✓ Branch 1 taken 556 times.
1892 if (marker[i] != j) {
78
1/2
✓ Branch 0 taken 1336 times.
✗ Branch 1 not taken.
1336 marker[i] = j;
79 touched.push_back(i);
80 }
81 }
82 }
83
84 160 CustomShellSort(touched);
85
86
2/2
✓ Branch 0 taken 1336 times.
✓ Branch 1 taken 160 times.
1496 for (int i : touched) {
87
1/2
✓ Branch 0 taken 1336 times.
✗ Branch 1 not taken.
1336 if (std::abs(acc[i]) > 1e-9) {
88
2/2
✓ Branch 0 taken 1160 times.
✓ Branch 1 taken 176 times.
1336 t_values[tid].push_back(acc[i]);
89 t_row_indices[tid].push_back(i);
90 1336 ++t_col_nnz[tid][j - jstart];
91 }
92 1336 acc[i] = {0.0, 0.0};
93 }
94 160 }
95
96 12 void MergeResults(int num_threads, int bc, SparseMatrix &c,
97 const std::vector<std::vector<std::complex<double>>> &t_values,
98 const std::vector<std::vector<int>> &t_row_indices, const std::vector<std::vector<int>> &t_col_nnz) {
99
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 12 times.
42 for (int tid = 0; tid < num_threads; ++tid) {
100 30 const int jstart = (tid * bc) / num_threads;
101 30 const int jend = ((tid + 1) * bc) / num_threads;
102
2/2
✓ Branch 0 taken 160 times.
✓ Branch 1 taken 30 times.
190 for (int j = jstart; j < jend; ++j) {
103 160 c.col_ptrs[j + 1] = c.col_ptrs[j] + t_col_nnz[tid][j - jstart];
104 }
105 }
106
107 12 const int total_nnz = c.col_ptrs[bc];
108 12 c.values.reserve(static_cast<std::size_t>(total_nnz));
109 12 c.row_indices.reserve(static_cast<std::size_t>(total_nnz));
110
111
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 12 times.
42 for (int tid = 0; tid < num_threads; ++tid) {
112 30 c.values.insert(c.values.end(), t_values[tid].begin(), t_values[tid].end());
113 30 c.row_indices.insert(c.row_indices.end(), t_row_indices[tid].begin(), t_row_indices[tid].end());
114 }
115 12 }
116
117 } // namespace
118
119 12 bool BorunovVComplexCcsOMP::RunImpl() {
120 12 const auto &a = GetInput().first;
121 12 const auto &b = GetInput().second;
122 auto &c = GetOutput()[0];
123
124 12 const int num_threads = ppc::util::GetNumThreads();
125 12 const int bc = b.num_cols;
126
127 12 std::vector<std::vector<std::complex<double>>> t_values(num_threads);
128
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 std::vector<std::vector<int>> t_row_indices(num_threads);
129
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 std::vector<std::vector<int>> t_col_nnz(num_threads);
130
131 12 #pragma omp parallel default(none) shared(a, b, bc, t_values, t_row_indices, t_col_nnz) \
132
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 num_threads(ppc::util::GetNumThreads())
133 {
134 const int tid = omp_get_thread_num();
135 const int nt = omp_get_num_threads();
136 const int jstart = (tid * bc) / nt;
137 const int jend = ((tid + 1) * bc) / nt;
138
139 t_col_nnz[tid].assign(jend - jstart, 0);
140
141 std::vector<std::complex<double>> acc(a.num_rows, {0.0, 0.0});
142 std::vector<int> marker(a.num_rows, -1);
143 std::vector<int> touched;
144 touched.reserve(static_cast<std::size_t>(a.num_rows));
145
146 for (int j = jstart; j < jend; ++j) {
147 ProcessColumn(j, a, b, tid, jstart, acc, marker, touched, t_values, t_row_indices, t_col_nnz);
148 }
149 }
150
151
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 MergeResults(num_threads, bc, c, t_values, t_row_indices, t_col_nnz);
152
153 12 return true;
154 12 }
155
156 12 bool BorunovVComplexCcsOMP::PostProcessingImpl() {
157 12 return true;
158 }
159
160 } // namespace borunov_v_complex_ccs
161