GCC Code Coverage Report


Directory: ./
File: tasks/kruglova_a_conjugate_gradient_sle/stl/src/ops_stl.cpp
Date: 2026-06-04 20:25:32
Exec Total Coverage
Lines: 57 67 85.1%
Functions: 13 13 100.0%
Branches: 28 64 43.8%

Line Branch Exec Source
1 #include "kruglova_a_conjugate_gradient_sle/stl/include/ops_stl.hpp"
2
3 #include <algorithm>
4 #include <cmath>
5 #include <cstddef>
6 #include <numeric>
7 #include <thread>
8 #include <vector>
9
10 #include "kruglova_a_conjugate_gradient_sle/common/include/common.hpp"
11
12 namespace kruglova_a_conjugate_gradient_sle {
13
14 namespace {
15
16 template <typename Func>
17 2016 void LaunchParallel(int total, int num_threads, const Func &func) {
18
1/2
✓ Branch 0 taken 1008 times.
✗ Branch 1 not taken.
2016 if (num_threads <= 1) {
19 1056 func(0, total, 0);
20 2016 return;
21 }
22 std::vector<std::thread> workers;
23 workers.reserve(num_threads);
24 int chunk = total / num_threads;
25 for (int i = 0; i < num_threads; ++i) {
26 int start = i * chunk;
27 int end = (i == num_threads - 1) ? total : (i + 1) * chunk;
28 workers.emplace_back(func, start, end, i);
29 }
30 for (auto &w : workers) {
31 w.join();
32 }
33 }
34
35 void MatVec(int n, int num_threads, const std::vector<double> &a, const std::vector<double> &p,
36 std::vector<double> &ap) {
37
1/2
✓ Branch 1 taken 264 times.
✗ Branch 2 not taken.
264 LaunchParallel(n, num_threads, [&](int start, int end, int) {
38
2/2
✓ Branch 0 taken 11016 times.
✓ Branch 1 taken 264 times.
11280 for (int i = start; i < end; ++i) {
39 double sum = 0.0;
40
2/2
✓ Branch 0 taken 841144 times.
✓ Branch 1 taken 11016 times.
852160 for (int j = 0; j < n; ++j) {
41 841144 sum += a[(static_cast<size_t>(i) * n) + j] * p[j];
42 }
43 11016 ap[i] = sum;
44 }
45 264 });
46 }
47
48 264 double Dot(int n, int num_threads, const std::vector<double> &v1, const std::vector<double> &v2,
49 std::vector<double> &buffer) {
50 264 LaunchParallel(n, num_threads, [&](int start, int end, int tid) {
51 double local = 0.0;
52
2/4
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 11016 times.
✓ Branch 3 taken 264 times.
11280 for (int i = start; i < end; ++i) {
53 11016 local += v1[i] * v2[i];
54 }
55 264 buffer[tid] = local;
56 });
57 264 return std::accumulate(buffer.begin(), buffer.begin() + num_threads, 0.0);
58 }
59
60 264 double UpdateXR(int n, int num_threads, double alpha, const std::vector<double> &p, const std::vector<double> &ap,
61 std::vector<double> &x, std::vector<double> &r, std::vector<double> &buffer) {
62 264 LaunchParallel(n, num_threads, [&](int start, int end, int tid) {
63 double local_rs = 0.0;
64
2/2
✓ Branch 0 taken 11016 times.
✓ Branch 1 taken 264 times.
11280 for (int i = start; i < end; ++i) {
65 11016 x[i] += alpha * p[i];
66 11016 r[i] -= alpha * ap[i];
67 11016 local_rs += r[i] * r[i];
68 }
69 264 buffer[tid] = local_rs;
70 264 });
71 264 return std::accumulate(buffer.begin(), buffer.begin() + num_threads, 0.0);
72 }
73
74 void UpdateP(int n, int num_threads, double beta, const std::vector<double> &r, std::vector<double> &p) {
75 432 LaunchParallel(n, num_threads, [&](int start, int end, int) {
76
2/4
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 9656 times.
✓ Branch 3 taken 216 times.
9872 for (int i = start; i < end; ++i) {
77 9656 p[i] = r[i] + (beta * p[i]);
78 }
79 });
80 }
81
82 } // namespace
83
84
1/2
✓ Branch 1 taken 48 times.
✗ Branch 2 not taken.
48 KruglovaAConjGradSleSTL::KruglovaAConjGradSleSTL(const InType &in) {
85 SetTypeOfTask(GetStaticTypeOfTask());
86 GetInput() = in;
87 48 }
88
89 48 bool KruglovaAConjGradSleSTL::ValidationImpl() {
90 const auto &in = GetInput();
91
3/6
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 48 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 48 times.
48 return in.size > 0 && in.A.size() == static_cast<size_t>(in.size) * in.size &&
92 48 in.b.size() == static_cast<size_t>(in.size);
93 }
94
95 48 bool KruglovaAConjGradSleSTL::PreProcessingImpl() {
96 48 GetOutput().assign(GetInput().size, 0.0);
97 48 return true;
98 }
99
100 48 bool KruglovaAConjGradSleSTL::RunImpl() {
101 const auto &input = GetInput();
102 48 const auto &a = input.A;
103 48 const auto &b = input.b;
104 48 const int n = input.size;
105
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
48 if (n <= 0) {
106 return true;
107 }
108
109
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 int num_threads = (n >= 250) ? static_cast<int>(std::thread::hardware_concurrency()) : 1;
110 48 num_threads = std::max(num_threads, 1);
111
112 auto &x = GetOutput();
113 48 std::vector<double> r = b;
114
1/2
✓ Branch 1 taken 48 times.
✗ Branch 2 not taken.
48 std::vector<double> p = r;
115
1/4
✓ Branch 1 taken 48 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
48 std::vector<double> ap(n, 0.0);
116
1/4
✓ Branch 1 taken 48 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
48 std::vector<double> partial_buffer(num_threads);
117
118 double rsold = std::inner_product(r.begin(), r.end(), r.begin(), 0.0);
119 const double tolerance = 1e-8;
120
121
1/2
✓ Branch 0 taken 264 times.
✗ Branch 1 not taken.
264 for (int iter = 0; iter < n; ++iter) {
122 264 MatVec(n, num_threads, a, p, ap);
123
124
1/2
✓ Branch 1 taken 264 times.
✗ Branch 2 not taken.
264 double p_ap = Dot(n, num_threads, p, ap, partial_buffer);
125
1/2
✓ Branch 0 taken 264 times.
✗ Branch 1 not taken.
264 if (std::abs(p_ap) < 1e-16) {
126 break;
127 }
128
129 264 const double alpha = rsold / p_ap;
130
1/2
✓ Branch 1 taken 264 times.
✗ Branch 2 not taken.
264 double rsnew = UpdateXR(n, num_threads, alpha, p, ap, x, r, partial_buffer);
131
132
2/2
✓ Branch 0 taken 216 times.
✓ Branch 1 taken 48 times.
264 if (std::sqrt(rsnew) < tolerance) {
133 break;
134 }
135
136
1/2
✓ Branch 1 taken 216 times.
✗ Branch 2 not taken.
216 UpdateP(n, num_threads, (rsnew / rsold), r, p);
137 rsold = rsnew;
138 }
139 return true;
140 }
141
142 48 bool KruglovaAConjGradSleSTL::PostProcessingImpl() {
143 48 return true;
144 }
145
146 } // namespace kruglova_a_conjugate_gradient_sle
147