GCC Code Coverage Report


Directory: ./
File: tasks/agafonov_i_matrix_ccs_seq/tbb/src/ops_tbb.cpp
Date: 2026-06-04 20:25:32
Exec Total Coverage
Lines: 0 50 0.0%
Functions: 0 7 0.0%
Branches: 0 46 0.0%

Line Branch Exec Source
1 #include "agafonov_i_matrix_ccs_seq/tbb/include/ops_tbb.hpp"
2
3 #include <tbb/blocked_range.h>
4 #include <tbb/parallel_for.h>
5
6 #include <algorithm>
7 #include <cmath>
8 #include <cstddef>
9 #include <vector>
10
11 #include "agafonov_i_matrix_ccs_seq/common/include/common.hpp"
12
13 namespace agafonov_i_matrix_ccs_seq {
14
15 AgafonovIMatrixCCSTBB::AgafonovIMatrixCCSTBB(const InType &in) {
16 SetTypeOfTask(GetStaticTypeOfTask());
17 GetInput() = in;
18 }
19
20 bool AgafonovIMatrixCCSTBB::ValidationImpl() {
21 const auto &left = GetInput().first;
22 const auto &right = GetInput().second;
23 return (left.cols_num == right.rows_num) && (left.col_ptrs.size() == left.cols_num + 1) &&
24 (right.col_ptrs.size() == right.cols_num + 1);
25 }
26
27 bool AgafonovIMatrixCCSTBB::PreProcessingImpl() {
28 GetOutput().vals.clear();
29 GetOutput().row_inds.clear();
30 return true;
31 }
32
33 void AgafonovIMatrixCCSTBB::ProcessColumn(size_t j, const InType::first_type &a, const InType::second_type &b,
34 std::vector<double> &accumulator, std::vector<size_t> &active_rows,
35 std::vector<bool> &row_mask, std::vector<double> &local_v,
36 std::vector<int> &local_r) {
37 const auto b_col_start = static_cast<size_t>(b.col_ptrs[j]);
38 const auto b_col_end = static_cast<size_t>(b.col_ptrs[j + 1]);
39 if (b_col_start == b_col_end) {
40 return;
41 }
42
43 for (size_t kb = b_col_start; kb < b_col_end; ++kb) {
44 const auto k = static_cast<size_t>(b.row_inds[kb]);
45 const double v_b = b.vals[kb];
46 const auto a_col_start = static_cast<size_t>(a.col_ptrs[k]);
47 const auto a_col_end = static_cast<size_t>(a.col_ptrs[k + 1]);
48
49 for (size_t ka = a_col_start; ka < a_col_end; ++ka) {
50 const auto i = static_cast<size_t>(a.row_inds[ka]);
51 if (!row_mask[i]) {
52 row_mask[i] = true;
53 active_rows.push_back(i);
54 }
55 accumulator[i] += a.vals[ka] * v_b;
56 }
57 }
58
59 std::ranges::sort(active_rows);
60
61 for (const auto row_idx : active_rows) {
62 if (std::abs(accumulator[row_idx]) > 1e-15) {
63 local_v.push_back(accumulator[row_idx]);
64 local_r.push_back(static_cast<int>(row_idx));
65 }
66 row_mask[row_idx] = false;
67 accumulator[row_idx] = 0.0;
68 }
69 active_rows.clear();
70 }
71
72 bool AgafonovIMatrixCCSTBB::RunImpl() {
73 const auto &a = GetInput().first;
74 const auto &b = GetInput().second;
75 auto &c = GetOutput();
76
77 c.rows_num = a.rows_num;
78 c.cols_num = b.cols_num;
79 c.col_ptrs.assign(c.cols_num + 1, 0);
80
81 std::vector<std::vector<double>> local_vals(b.cols_num);
82 std::vector<std::vector<int>> local_rows(b.cols_num);
83
84 tbb::parallel_for(tbb::blocked_range<size_t>(0, b.cols_num), [&](const tbb::blocked_range<size_t> &range) {
85 std::vector<double> accumulator(a.rows_num, 0.0);
86 std::vector<size_t> active_rows;
87 std::vector<bool> row_mask(a.rows_num, false);
88
89 for (size_t j = range.begin(); j < range.end(); ++j) {
90 ProcessColumn(j, a, b, accumulator, active_rows, row_mask, local_vals[j], local_rows[j]);
91 }
92 });
93
94 int current_nnz = 0;
95 for (size_t j = 0; j < b.cols_num; ++j) {
96 c.col_ptrs[j] = current_nnz;
97 c.vals.insert(c.vals.end(), local_vals[j].begin(), local_vals[j].end());
98 c.row_inds.insert(c.row_inds.end(), local_rows[j].begin(), local_rows[j].end());
99 current_nnz += static_cast<int>(local_vals[j].size());
100 }
101 c.col_ptrs[b.cols_num] = current_nnz;
102 c.nnz = current_nnz;
103 return true;
104 }
105
106 bool AgafonovIMatrixCCSTBB::PostProcessingImpl() {
107 return true;
108 }
109
110 } // namespace agafonov_i_matrix_ccs_seq
111