GCC Code Coverage Report


Directory: ./
File: tasks/kotelnikova_a_double_matr_mult/omp/src/ops_omp.cpp
Date: 2026-04-02 17:12:27
Exec Total Coverage
Lines: 47 49 95.9%
Functions: 8 8 100.0%
Branches: 34 60 56.7%

Line Branch Exec Source
1 #include "kotelnikova_a_double_matr_mult/omp/include/ops_omp.hpp"
2
3 #include <omp.h>
4
5 #include <cmath>
6 #include <cstddef>
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 20 times.
✗ Branch 3 not taken.
20 KotelnikovaATaskOMP::KotelnikovaATaskOMP(const InType &in) {
14 SetTypeOfTask(GetStaticTypeOfTask());
15 GetInput() = in;
16 20 GetOutput() = SparseMatrixCCS();
17 20 }
18
19 40 bool KotelnikovaATaskOMP::IsMatrixValid(const SparseMatrixCCS &matrix) {
20
2/4
✓ Branch 0 taken 40 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 40 times.
40 if (matrix.rows < 0 || matrix.cols < 0) {
21 return false;
22 }
23
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
40 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 40 times.
40 if (matrix.values.size() != matrix.row_indices.size()) {
27 return false;
28 }
29
30
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 40 times.
40 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 40 times.
40 const int total_elements = static_cast<int>(matrix.values.size());
35
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
40 if (matrix.col_ptrs[matrix.cols] != total_elements) {
36 return false;
37 }
38
39
2/2
✓ Branch 0 taken 116 times.
✓ Branch 1 taken 40 times.
156 for (size_t i = 0; i < matrix.col_ptrs.size() - 1; ++i) {
40
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 116 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 116 times.
116 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 144 times.
✓ Branch 1 taken 40 times.
184 for (size_t i = 0; i < matrix.row_indices.size(); ++i) {
46
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 144 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 144 times.
144 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 20 times.
✗ Branch 1 not taken.
20 bool KotelnikovaATaskOMP::ValidationImpl() {
55 const auto &[a, b] = GetInput();
56
57
2/4
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
20 if (!IsMatrixValid(a) || !IsMatrixValid(b)) {
58 return false;
59 }
60
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 if (a.cols != b.rows) {
61 return false;
62 }
63
64 return true;
65 }
66
67 20 bool KotelnikovaATaskOMP::PreProcessingImpl() {
68 const auto &[a, b] = GetInput();
69 20 GetOutput() = SparseMatrixCCS(a.rows, b.cols);
70 20 return true;
71 }
72
73 namespace {
74 112 std::vector<double> ComputeColumn(const SparseMatrixCCS &a, const SparseMatrixCCS &b, int col_idx) {
75 112 std::vector<double> temp(a.rows, 0.0);
76
77
2/2
✓ Branch 0 taken 112 times.
✓ Branch 1 taken 112 times.
224 for (int b_idx = b.col_ptrs[col_idx]; b_idx < b.col_ptrs[col_idx + 1]; ++b_idx) {
78 112 const int k = b.row_indices[b_idx];
79 112 const double b_val = b.values[b_idx];
80
81
2/2
✓ Branch 0 taken 168 times.
✓ Branch 1 taken 112 times.
280 for (int a_idx = a.col_ptrs[k]; a_idx < a.col_ptrs[k + 1]; ++a_idx) {
82 168 const int i = a.row_indices[a_idx];
83 168 temp[i] += a.values[a_idx] * b_val;
84 }
85 }
86
87 112 return temp;
88 }
89
90 int CountNonZero(const std::vector<double> &column, double epsilon) {
91 int count = 0;
92 for (double val : column) {
93 if (std::abs(val) > epsilon) {
94 ++count;
95 }
96 }
97 return count;
98 }
99
100 void FillColumn(const std::vector<double> &column, double epsilon, std::vector<int> &row_indices,
101 std::vector<double> &values, int start_pos) {
102 int pos = start_pos;
103 for (size_t i = 0; i < column.size(); ++i) {
104 if (std::abs(column[i]) > epsilon) {
105 row_indices[pos] = static_cast<int>(i);
106 values[pos] = column[i];
107 ++pos;
108 }
109 }
110 }
111
112 } // namespace
113
114 20 SparseMatrixCCS KotelnikovaATaskOMP::MultiplyMatrices(const SparseMatrixCCS &a, const SparseMatrixCCS &b) {
115 20 SparseMatrixCCS result(a.rows, b.cols);
116
117 const double epsilon = 1e-10;
118
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 std::vector<int> col_start(b.cols, 0);
119
120 20 #pragma omp parallel for default(none) shared(a, b, col_start, epsilon) schedule(dynamic, 8)
121 for (int j = 0; j < b.cols; ++j) {
122 std::vector<double> column = ComputeColumn(a, b, j);
123 col_start[j] = CountNonZero(column, epsilon);
124 }
125
126
1/4
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
20 std::vector<int> col_ptr(b.cols + 1, 0);
127
2/2
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 20 times.
76 for (int j = 0; j < b.cols; ++j) {
128 56 col_ptr[j + 1] = col_ptr[j] + col_start[j];
129 }
130
131
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 const int total_nnz = col_ptr[b.cols];
132
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 result.values.resize(total_nnz);
133
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 result.row_indices.resize(total_nnz);
134
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 result.col_ptrs = col_ptr;
135
136
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 #pragma omp parallel for default(none) shared(a, b, result, col_ptr, epsilon) schedule(dynamic, 8)
137 for (int j = 0; j < b.cols; ++j) {
138 std::vector<double> column = ComputeColumn(a, b, j);
139 FillColumn(column, epsilon, result.row_indices, result.values, col_ptr[j]);
140 }
141
142 20 return result;
143 }
144
145 20 bool KotelnikovaATaskOMP::RunImpl() {
146 const auto &[a, b] = GetInput();
147 20 GetOutput() = MultiplyMatrices(a, b);
148 20 return true;
149 }
150
151 20 bool KotelnikovaATaskOMP::PostProcessingImpl() {
152 20 return true;
153 }
154
155 } // namespace kotelnikova_a_double_matr_mult
156