GCC Code Coverage Report


Directory: ./
File: tasks/viderman_a_sparse_matrix_mult_crs_complex/tbb/src/ops_tbb.cpp
Date: 2026-06-04 20:25:32
Exec Total Coverage
Lines: 56 56 100.0%
Functions: 9 9 100.0%
Branches: 34 54 63.0%

Line Branch Exec Source
1 #include "viderman_a_sparse_matrix_mult_crs_complex/tbb/include/ops_tbb.hpp"
2
3 #include <algorithm>
4 #include <cmath>
5 #include <cstddef>
6 #include <vector>
7
8 #include "oneapi/tbb/enumerable_thread_specific.h"
9 #include "oneapi/tbb/parallel_for.h"
10 #include "viderman_a_sparse_matrix_mult_crs_complex/common/include/common.hpp"
11
12 namespace viderman_a_sparse_matrix_mult_crs_complex {
13 namespace {
14
15
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 36 times.
40 void ProcessRow(const CRSMatrix &a, const CRSMatrix &b, int row, std::vector<Complex> &accumulator,
16 std::vector<int> &marker, std::vector<int> &current_row_indices, std::vector<int> &dst_cols,
17 std::vector<Complex> &dst_vals) {
18 current_row_indices.clear();
19
20
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 40 times.
68 for (int j = a.row_ptr[row]; j < a.row_ptr[row + 1]; ++j) {
21 28 const int col_a = a.col_indices[j];
22 28 const Complex val_a = a.values[j];
23
24
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 28 times.
56 for (int k = b.row_ptr[col_a]; k < b.row_ptr[col_a + 1]; ++k) {
25
1/2
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
28 const int col_b = b.col_indices[k];
26
1/2
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
28 accumulator[col_b] += val_a * b.values[k];
27
28
1/2
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
28 if (marker[col_b] != row) {
29 current_row_indices.push_back(col_b);
30 28 marker[col_b] = row;
31 }
32 }
33 }
34
35 std::ranges::sort(current_row_indices);
36
37 dst_cols.clear();
38 dst_vals.clear();
39 40 dst_cols.reserve(current_row_indices.size());
40 40 dst_vals.reserve(current_row_indices.size());
41
42
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 40 times.
68 for (const int idx : current_row_indices) {
43
1/2
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
28 if (std::abs(accumulator[idx]) > kEpsilon) {
44 dst_cols.push_back(idx);
45 dst_vals.push_back(accumulator[idx]);
46 }
47 28 accumulator[idx] = Complex(0.0, 0.0);
48 }
49 40 }
50
51 struct ThreadBuffers {
52 std::vector<Complex> accumulator;
53 std::vector<int> marker;
54 std::vector<int> current_row_indices;
55 };
56
57 } // namespace
58
59
1/2
✓ Branch 2 taken 24 times.
✗ Branch 3 not taken.
24 VidermanASparseMatrixMultCRSComplexTBB::VidermanASparseMatrixMultCRSComplexTBB(const InType &in) {
60 SetTypeOfTask(GetStaticTypeOfTask());
61 GetInput() = in;
62 24 GetOutput() = CRSMatrix();
63 24 }
64
65
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 bool VidermanASparseMatrixMultCRSComplexTBB::ValidationImpl() {
66 const auto &input = GetInput();
67 const auto &a = std::get<0>(input);
68 const auto &b = std::get<1>(input);
69
70
2/4
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 24 times.
✗ Branch 3 not taken.
24 if (!a.IsValid() || !b.IsValid()) {
71 return false;
72 }
73
74
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 20 times.
24 if (a.cols != b.rows) {
75 4 return false;
76 }
77
78 return true;
79 }
80
81 20 bool VidermanASparseMatrixMultCRSComplexTBB::PreProcessingImpl() {
82 const auto &input = GetInput();
83
84 20 a_ = &std::get<0>(input);
85 20 b_ = &std::get<1>(input);
86
87 20 return true;
88 }
89
90 20 void VidermanASparseMatrixMultCRSComplexTBB::Multiply(const CRSMatrix &a, const CRSMatrix &b, CRSMatrix &c) {
91 20 c.rows = a.rows;
92 20 c.cols = b.cols;
93
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
20 c.row_ptr.assign(a.rows + 1, 0);
94 c.col_indices.clear();
95 c.values.clear();
96
97 20 std::vector<std::vector<int>> row_cols(a.rows);
98
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 std::vector<std::vector<Complex>> row_vals(a.rows);
99
100 24 oneapi::tbb::enumerable_thread_specific<ThreadBuffers> tls([&b] {
101 24 ThreadBuffers buffers;
102
1/2
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
24 buffers.accumulator.assign(b.cols, Complex(0.0, 0.0));
103
1/2
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
24 buffers.marker.assign(b.cols, -1);
104 24 return buffers;
105
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 });
106
107
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 oneapi::tbb::parallel_for(0, a.rows, [&](int i) {
108 40 auto &buffers = tls.local();
109 40 ProcessRow(a, b, i, buffers.accumulator, buffers.marker, buffers.current_row_indices, row_cols[i], row_vals[i]);
110 40 });
111
112
2/2
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 20 times.
60 for (int i = 0; i < a.rows; ++i) {
113 40 c.row_ptr[i + 1] = c.row_ptr[i] + static_cast<int>(row_cols[i].size());
114 }
115
116
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 c.col_indices.reserve(static_cast<std::size_t>(c.row_ptr[a.rows]));
117
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 c.values.reserve(static_cast<std::size_t>(c.row_ptr[a.rows]));
118
2/2
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 20 times.
60 for (int i = 0; i < a.rows; ++i) {
119
2/4
✓ Branch 1 taken 40 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 40 times.
✗ Branch 5 not taken.
40 c.col_indices.insert(c.col_indices.end(), row_cols[i].begin(), row_cols[i].end());
120 40 c.values.insert(c.values.end(), row_vals[i].begin(), row_vals[i].end());
121 }
122 20 }
123
124 20 bool VidermanASparseMatrixMultCRSComplexTBB::RunImpl() {
125
2/4
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
20 if (a_ == nullptr || b_ == nullptr) {
126 return false;
127 }
128
129 CRSMatrix &c = GetOutput();
130 20 Multiply(*a_, *b_, c);
131
132 20 return true;
133 }
134
135 20 bool VidermanASparseMatrixMultCRSComplexTBB::PostProcessingImpl() {
136 CRSMatrix &c = GetOutput();
137 20 return c.IsValid();
138 }
139
140 } // namespace viderman_a_sparse_matrix_mult_crs_complex
141