GCC Code Coverage Report


Directory: ./
File: tasks/kotelnikova_a_double_matr_mult/stl/src/ops_stl.cpp
Date: 2026-05-11 08:26:31
Exec Total Coverage
Lines: 80 81 98.8%
Functions: 10 10 100.0%
Branches: 62 94 66.0%

Line Branch Exec Source
1 #include "kotelnikova_a_double_matr_mult/stl/include/ops_stl.hpp"
2
3 #include <algorithm>
4 #include <cmath>
5 #include <cstddef>
6 #include <thread>
7 #include <vector>
8
9 #include "kotelnikova_a_double_matr_mult/common/include/common.hpp"
10
11 namespace kotelnikova_a_double_matr_mult {
12
13
1/2
✓ Branch 2 taken 40 times.
✗ Branch 3 not taken.
40 KotelnikovaATaskSTL::KotelnikovaATaskSTL(const InType &in) {
14 SetTypeOfTask(GetStaticTypeOfTask());
15 GetInput() = in;
16 40 GetOutput() = SparseMatrixCCS();
17 40 }
18
19 80 bool KotelnikovaATaskSTL::IsMatrixValid(const SparseMatrixCCS &matrix) {
20
2/4
✓ Branch 0 taken 80 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 80 times.
80 if (matrix.rows < 0 || matrix.cols < 0) {
21 return false;
22 }
23
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 80 times.
80 if (matrix.col_ptrs.size() != static_cast<size_t>(matrix.cols) + 1) {
24 return false;
25 }
26
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 80 times.
80 if (matrix.values.size() != matrix.row_indices.size()) {
27 return false;
28 }
29
30
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 80 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 80 times.
80 if (matrix.col_ptrs.empty() || matrix.col_ptrs[0] != 0) {
31 return false;
32 }
33
34
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 80 times.
80 const int total_elements = static_cast<int>(matrix.values.size());
35
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 80 times.
80 if (matrix.col_ptrs[matrix.cols] != total_elements) {
36 return false;
37 }
38
39
2/2
✓ Branch 0 taken 232 times.
✓ Branch 1 taken 80 times.
312 for (size_t i = 0; i < matrix.col_ptrs.size() - 1; ++i) {
40
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 232 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 232 times.
232 if (matrix.col_ptrs[i] > matrix.col_ptrs[i + 1] || matrix.col_ptrs[i] < 0) {
41 return false;
42 }
43 }
44
45
2/2
✓ Branch 0 taken 288 times.
✓ Branch 1 taken 80 times.
368 for (size_t i = 0; i < matrix.row_indices.size(); ++i) {
46
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 288 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 288 times.
288 if (matrix.row_indices[i] < 0 || matrix.row_indices[i] >= matrix.rows) {
47 return false;
48 }
49 }
50
51 return true;
52 }
53
54
1/2
✓ Branch 0 taken 40 times.
✗ Branch 1 not taken.
40 bool KotelnikovaATaskSTL::ValidationImpl() {
55 const auto &[a, b] = GetInput();
56
57
2/4
✓ Branch 0 taken 40 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 40 times.
✗ Branch 3 not taken.
40 if (!IsMatrixValid(a) || !IsMatrixValid(b)) {
58 return false;
59 }
60
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
40 if (a.cols != b.rows) {
61 return false;
62 }
63
64 return true;
65 }
66
67 40 bool KotelnikovaATaskSTL::PreProcessingImpl() {
68 const auto &[a, b] = GetInput();
69 40 GetOutput() = SparseMatrixCCS(a.rows, b.cols);
70 40 return true;
71 }
72
73 namespace {
74
75 224 std::vector<double> ComputeColumn(const SparseMatrixCCS &a, const SparseMatrixCCS &b, int col_idx) {
76 224 std::vector<double> temp(static_cast<size_t>(a.rows), 0.0);
77
78
2/2
✓ Branch 0 taken 224 times.
✓ Branch 1 taken 224 times.
448 for (int b_idx = b.col_ptrs[col_idx]; b_idx < b.col_ptrs[col_idx + 1]; ++b_idx) {
79 224 const int k = b.row_indices[b_idx];
80 224 const double b_val = b.values[b_idx];
81
82
2/2
✓ Branch 0 taken 336 times.
✓ Branch 1 taken 224 times.
560 for (int a_idx = a.col_ptrs[k]; a_idx < a.col_ptrs[k + 1]; ++a_idx) {
83 336 const int i = a.row_indices[a_idx];
84 336 temp[static_cast<size_t>(i)] += a.values[a_idx] * b_val;
85 }
86 }
87
88 224 return temp;
89 }
90
91 int CountNonZero(const std::vector<double> &column, double epsilon) {
92 int count = 0;
93
4/4
✓ Branch 0 taken 168 times.
✓ Branch 1 taken 168 times.
✓ Branch 2 taken 336 times.
✓ Branch 3 taken 112 times.
448 for (double val : column) {
94
2/2
✓ Branch 0 taken 168 times.
✓ Branch 1 taken 168 times.
336 if (std::abs(val) > epsilon) {
95 168 ++count;
96 }
97 }
98 return count;
99 }
100
101 void FillColumn(const std::vector<double> &column, double epsilon, std::vector<int> &row_indices,
102 std::vector<double> &values, int start_pos) {
103 int pos = start_pos;
104
2/2
✓ Branch 0 taken 336 times.
✓ Branch 1 taken 112 times.
448 for (size_t i = 0; i < column.size(); ++i) {
105
2/2
✓ Branch 0 taken 168 times.
✓ Branch 1 taken 168 times.
336 if (std::abs(column[i]) > epsilon) {
106 168 row_indices[static_cast<size_t>(pos)] = static_cast<int>(i);
107 168 values[static_cast<size_t>(pos)] = column[i];
108 168 ++pos;
109 }
110 }
111 }
112
113 } // namespace
114
115 40 SparseMatrixCCS KotelnikovaATaskSTL::MultiplyMatrices(const SparseMatrixCCS &a, const SparseMatrixCCS &b) {
116 40 SparseMatrixCCS result(a.rows, b.cols);
117
118 40 const double epsilon = 1e-10;
119 40 const unsigned int hardware_threads = std::thread::hardware_concurrency();
120 40 const int num_threads = (hardware_threads > 0) ? static_cast<int>(hardware_threads) : 1;
121 40 const int cols_per_thread = (b.cols + num_threads - 1) / num_threads;
122
123
1/2
✓ Branch 1 taken 40 times.
✗ Branch 2 not taken.
40 std::vector<int> col_start(b.cols, 0);
124 40 std::vector<std::thread> threads;
125
126
2/2
✓ Branch 0 taken 160 times.
✓ Branch 1 taken 40 times.
200 for (int thread_idx = 0; thread_idx < num_threads; ++thread_idx) {
127 160 int start_col = thread_idx * cols_per_thread;
128
1/2
✓ Branch 1 taken 160 times.
✗ Branch 2 not taken.
160 int end_col = std::min(start_col + cols_per_thread, b.cols);
129
130
1/2
✓ Branch 1 taken 160 times.
✗ Branch 2 not taken.
160 threads.emplace_back([&, start_col, end_col]() {
131
2/2
✓ Branch 0 taken 112 times.
✓ Branch 1 taken 160 times.
272 for (int j = start_col; j < end_col; ++j) {
132 112 std::vector<double> column = ComputeColumn(a, b, j);
133
1/2
✓ Branch 0 taken 112 times.
✗ Branch 1 not taken.
224 col_start[j] = CountNonZero(column, epsilon);
134 }
135 160 });
136 }
137
138
2/2
✓ Branch 0 taken 160 times.
✓ Branch 1 taken 40 times.
200 for (auto &thread : threads) {
139
1/2
✓ Branch 1 taken 160 times.
✗ Branch 2 not taken.
160 thread.join();
140 }
141
142
1/2
✓ Branch 1 taken 40 times.
✗ Branch 2 not taken.
40 std::vector<int> col_ptr(b.cols + 1, 0);
143
2/2
✓ Branch 0 taken 112 times.
✓ Branch 1 taken 40 times.
152 for (int j = 0; j < b.cols; ++j) {
144 112 col_ptr[j + 1] = col_ptr[j] + col_start[j];
145 }
146
147
1/2
✓ Branch 1 taken 40 times.
✗ Branch 2 not taken.
40 const int total_nnz = col_ptr[b.cols];
148
1/2
✓ Branch 1 taken 40 times.
✗ Branch 2 not taken.
40 result.values.resize(static_cast<size_t>(total_nnz));
149
1/2
✓ Branch 1 taken 40 times.
✗ Branch 2 not taken.
40 result.row_indices.resize(static_cast<size_t>(total_nnz));
150
1/2
✓ Branch 1 taken 40 times.
✗ Branch 2 not taken.
40 result.col_ptrs = col_ptr;
151
152 40 threads.clear();
153
2/2
✓ Branch 0 taken 160 times.
✓ Branch 1 taken 40 times.
200 for (int thread_idx = 0; thread_idx < num_threads; ++thread_idx) {
154 160 int start_col = thread_idx * cols_per_thread;
155
1/2
✓ Branch 1 taken 160 times.
✗ Branch 2 not taken.
160 int end_col = std::min(start_col + cols_per_thread, b.cols);
156
157
1/4
✓ Branch 1 taken 160 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
160 threads.emplace_back([&, start_col, end_col]() {
158
2/2
✓ Branch 0 taken 112 times.
✓ Branch 1 taken 160 times.
272 for (int j = start_col; j < end_col; ++j) {
159 112 std::vector<double> column = ComputeColumn(a, b, j);
160 112 FillColumn(column, epsilon, result.row_indices, result.values, col_ptr[j]);
161 }
162 160 });
163 }
164
165
2/2
✓ Branch 0 taken 160 times.
✓ Branch 1 taken 40 times.
200 for (auto &thread : threads) {
166
1/2
✓ Branch 1 taken 160 times.
✗ Branch 2 not taken.
160 thread.join();
167 }
168
169 40 return result;
170 40 }
171
172 40 bool KotelnikovaATaskSTL::RunImpl() {
173 const auto &[a, b] = GetInput();
174 40 GetOutput() = MultiplyMatrices(a, b);
175 40 return true;
176 }
177
178 40 bool KotelnikovaATaskSTL::PostProcessingImpl() {
179 40 return true;
180 }
181
182 } // namespace kotelnikova_a_double_matr_mult
183