GCC Code Coverage Report


Directory: ./
File: tasks/borunov_v_complex_ccs/tbb/src/ops_tbb.cpp
Date: 2026-05-11 08:26:31
Exec Total Coverage
Lines: 81 82 98.8%
Functions: 11 11 100.0%
Branches: 57 82 69.5%

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