GCC Code Coverage Report


Directory: ./
File: tasks/agafonov_i_matrix_ccs_seq/stl/src/ops_stl.cpp
Date: 2026-06-04 20:25:32
Exec Total Coverage
Lines: 0 64 0.0%
Functions: 0 7 0.0%
Branches: 0 64 0.0%

Line Branch Exec Source
1 #include "agafonov_i_matrix_ccs_seq/stl/include/ops_stl.hpp"
2
3 #include <algorithm>
4 #include <cmath>
5 #include <cstddef>
6 #include <thread>
7 #include <utility>
8 #include <vector>
9
10 #include "agafonov_i_matrix_ccs_seq/common/include/common.hpp"
11 #include "util/include/util.hpp"
12
13 namespace agafonov_i_matrix_ccs_seq {
14
15 AgafonovIMatrixCCSSTL::AgafonovIMatrixCCSSTL(const InType &in) {
16 SetTypeOfTask(GetStaticTypeOfTask());
17 GetInput() = in;
18 }
19
20 bool AgafonovIMatrixCCSSTL::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 AgafonovIMatrixCCSSTL::PreProcessingImpl() {
28 GetOutput().vals.clear();
29 GetOutput().row_inds.clear();
30 return true;
31 }
32
33 void AgafonovIMatrixCCSSTL::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 AgafonovIMatrixCCSSTL::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 int num_threads = ppc::util::GetNumThreads();
85 if (num_threads <= 0) {
86 num_threads = static_cast<int>(std::thread::hardware_concurrency());
87 if (num_threads <= 0) {
88 num_threads = 1;
89 }
90 }
91
92 num_threads = std::min(num_threads, static_cast<int>(b.cols_num));
93
94 std::vector<std::thread> threads;
95 threads.reserve(num_threads);
96
97 const size_t chunk_size = b.cols_num / num_threads;
98 const size_t remainder = b.cols_num % num_threads;
99 size_t current_start = 0;
100
101 for (int i = 0; i < num_threads; ++i) {
102 size_t current_end = current_start + chunk_size + (std::cmp_less(i, remainder) ? 1 : 0);
103
104 threads.emplace_back([&, current_start, current_end]() {
105 std::vector<double> accumulator(a.rows_num, 0.0);
106 std::vector<size_t> active_rows;
107 std::vector<bool> row_mask(a.rows_num, false);
108
109 for (size_t j = current_start; j < current_end; ++j) {
110 ProcessColumn(j, a, b, accumulator, active_rows, row_mask, local_vals[j], local_rows[j]);
111 }
112 });
113
114 current_start = current_end;
115 }
116
117 for (auto &t : threads) {
118 t.join();
119 }
120
121 int current_nnz = 0;
122 for (size_t j = 0; j < b.cols_num; ++j) {
123 c.col_ptrs[j] = current_nnz;
124 c.vals.insert(c.vals.end(), local_vals[j].begin(), local_vals[j].end());
125 c.row_inds.insert(c.row_inds.end(), local_rows[j].begin(), local_rows[j].end());
126 current_nnz += static_cast<int>(local_vals[j].size());
127 }
128 c.col_ptrs[b.cols_num] = current_nnz;
129 c.nnz = current_nnz;
130 return true;
131 }
132
133 bool AgafonovIMatrixCCSSTL::PostProcessingImpl() {
134 return true;
135 }
136
137 } // namespace agafonov_i_matrix_ccs_seq
138