GCC Code Coverage Report


Directory: ./
File: tasks/sannikov_i_integrals_rectangle_method/stl/src/ops_stl.cpp
Date: 2026-05-11 08:26:31
Exec Total Coverage
Lines: 68 70 97.1%
Functions: 8 8 100.0%
Branches: 55 90 61.1%

Line Branch Exec Source
1 #include "sannikov_i_integrals_rectangle_method/stl/include/ops_stl.hpp"
2
3 #include <algorithm>
4 #include <cmath>
5 #include <cstddef>
6 #include <cstdint>
7 #include <functional>
8 #include <thread>
9 #include <utility>
10 #include <vector>
11
12 #include "sannikov_i_integrals_rectangle_method/common/include/common.hpp"
13
14 namespace sannikov_i_integrals_rectangle_method {
15
16
1/2
✓ Branch 1 taken 184 times.
✗ Branch 2 not taken.
184 SannikovIIntegralsRectangleMethodSTL::SannikovIIntegralsRectangleMethodSTL(const InType &in) {
17 SetTypeOfTask(GetStaticTypeOfTask());
18 GetInput() = in;
19 184 GetOutput() = 0.0;
20 184 }
21
22
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 184 times.
184 bool SannikovIIntegralsRectangleMethodSTL::ValidationImpl() {
23 const auto &[func, borders, num] = GetInput();
24
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 184 times.
184 if (borders.empty()) {
25 return false;
26 }
27
2/2
✓ Branch 0 taken 320 times.
✓ Branch 1 taken 184 times.
504 for (const auto &[left_border, right_border] : borders) {
28
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 320 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 320 times.
320 if (!std::isfinite(left_border) || !std::isfinite(right_border)) {
29 return false;
30 }
31
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 320 times.
320 if (left_border >= right_border) {
32 return false;
33 }
34 }
35
36
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 184 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 184 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 184 times.
184 return func && (num > 0) && (GetOutput() == 0.0);
37 }
38
39 184 bool SannikovIIntegralsRectangleMethodSTL::PreProcessingImpl() {
40 184 GetOutput() = 0.0;
41 184 return true;
42 }
43
44 namespace {
45
46 26080 bool ComputeSlice(const std::function<double(const std::vector<double> &)> &funcx,
47 const std::vector<std::pair<double, double>> &brd, const std::vector<double> &sz,
48 std::size_t outer_dim, int64_t inner_cells, int num_splits, int outer, std::vector<int> &idx,
49 std::vector<double> &x_vec, double &local_sum) {
50
2/2
✓ Branch 0 taken 12720 times.
✓ Branch 1 taken 26080 times.
38800 for (std::size_t i = 0; i < outer_dim; ++i) {
51 12720 idx[i] = 0;
52 }
53 26080 idx[outer_dim] = outer;
54 26080 x_vec[outer_dim] = brd[outer_dim].first + ((static_cast<double>(outer) + 0.5) * sz[outer_dim]);
55
56
2/2
✓ Branch 0 taken 20406000 times.
✓ Branch 1 taken 26080 times.
20432080 for (int64_t cell = 0; cell < inner_cells; ++cell) {
57
2/2
✓ Branch 0 taken 45958400 times.
✓ Branch 1 taken 20406000 times.
66364400 for (std::size_t i = 0; i < outer_dim; ++i) {
58 45958400 x_vec[i] = brd[i].first + ((static_cast<double>(idx[i]) + 0.5) * sz[i]);
59 }
60
61 const double func_x = funcx(x_vec);
62
1/2
✓ Branch 0 taken 20406000 times.
✗ Branch 1 not taken.
20406000 if (!std::isfinite(func_x)) {
63 return false;
64 }
65
66 20406000 local_sum += func_x;
67
68
2/2
✓ Branch 0 taken 20757600 times.
✓ Branch 1 taken 26080 times.
20783680 for (std::size_t position = 0; position < outer_dim; ++position) {
69
2/2
✓ Branch 0 taken 377680 times.
✓ Branch 1 taken 20379920 times.
20757600 if (++idx[position] < num_splits) {
70 break;
71 }
72 377680 idx[position] = 0;
73 }
74 }
75 return true;
76 }
77
78 736 void ThreadWorker(const std::function<double(const std::vector<double> &)> &funcx,
79 const std::vector<std::pair<double, double>> &brd, const std::vector<double> &sz, std::size_t dim,
80 std::size_t outer_dim, int64_t inner_cells, int num_splits, int start, int end, double &partial_sum,
81 int &error_flag) {
82 736 std::vector<int> idx(dim, 0);
83
1/4
✓ Branch 1 taken 736 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
736 std::vector<double> x_vec(dim);
84 double thread_sum = 0.0;
85
86
2/2
✓ Branch 0 taken 26080 times.
✓ Branch 1 taken 736 times.
26816 for (int outer = start; outer < end; ++outer) {
87 26080 double local_sum = 0.0;
88
2/4
✓ Branch 1 taken 26080 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 26080 times.
26080 if (!ComputeSlice(funcx, brd, sz, outer_dim, inner_cells, num_splits, outer, idx, x_vec, local_sum)) {
89 error_flag = 1;
90 return;
91 }
92 26080 thread_sum += local_sum;
93 }
94
95
1/2
✓ Branch 0 taken 736 times.
✗ Branch 1 not taken.
736 partial_sum = thread_sum;
96 }
97
98 } // namespace
99
100 184 bool SannikovIIntegralsRectangleMethodSTL::RunImpl() {
101 const auto &[func, borders, num] = GetInput();
102 const std::size_t dim = borders.size();
103
104 const auto &funcx = func;
105 const auto &brd = borders;
106 184 const int num_splits = num;
107
108 184 std::vector<double> sz(dim);
109 double cell_v = 1.0;
110
111
2/2
✓ Branch 0 taken 320 times.
✓ Branch 1 taken 184 times.
504 for (std::size_t i = 0; i < dim; ++i) {
112
1/2
✓ Branch 0 taken 320 times.
✗ Branch 1 not taken.
320 sz[i] = (brd[i].second - brd[i].first) / static_cast<double>(num_splits);
113
2/4
✓ Branch 0 taken 320 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 320 times.
✗ Branch 3 not taken.
320 if (!(sz[i] > 0.0) || !std::isfinite(sz[i])) {
114 return false;
115 }
116 320 cell_v *= sz[i];
117 }
118
119 184 const std::size_t outer_dim = dim - 1;
120
121 int64_t inner_cells = 1;
122
2/2
✓ Branch 0 taken 136 times.
✓ Branch 1 taken 184 times.
320 for (std::size_t i = 0; i < outer_dim; ++i) {
123 136 inner_cells *= num_splits;
124 }
125
126 184 const int num_threads = static_cast<int>(std::thread::hardware_concurrency());
127
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 184 times.
184 const int actual_threads = std::min(num_threads > 0 ? num_threads : 4, num_splits);
128
129
1/4
✓ Branch 1 taken 184 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
184 std::vector<double> partial_sums(actual_threads, 0.0);
130
1/4
✓ Branch 1 taken 184 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
184 std::vector<int> error_flags(actual_threads, 0);
131
1/4
✓ Branch 1 taken 184 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
184 std::vector<std::thread> threads(actual_threads);
132
133
2/2
✓ Branch 0 taken 736 times.
✓ Branch 1 taken 184 times.
920 for (int tid = 0; tid < actual_threads; ++tid) {
134 736 const int chunk = num_splits / actual_threads;
135 736 const int rem = num_splits % actual_threads;
136
2/2
✓ Branch 0 taken 704 times.
✓ Branch 1 taken 32 times.
736 const int start = (tid * chunk) + std::min(tid, rem);
137
2/2
✓ Branch 0 taken 704 times.
✓ Branch 1 taken 32 times.
736 const int end = start + chunk + (tid < rem ? 1 : 0);
138
139 736 threads[tid] = std::thread([&funcx, &brd, &sz, dim, outer_dim, inner_cells, num_splits, start, end,
140
1/2
✓ Branch 1 taken 736 times.
✗ Branch 2 not taken.
736 &partial_sum = partial_sums[tid], &error_flag = error_flags[tid]]() {
141 736 ThreadWorker(funcx, brd, sz, dim, outer_dim, inner_cells, num_splits, start, end, partial_sum, error_flag);
142
1/2
✓ Branch 1 taken 736 times.
✗ Branch 2 not taken.
736 });
143 }
144
145
2/2
✓ Branch 0 taken 736 times.
✓ Branch 1 taken 184 times.
920 for (auto &thr : threads) {
146
1/2
✓ Branch 1 taken 736 times.
✗ Branch 2 not taken.
736 thr.join();
147 }
148
149
2/2
✓ Branch 0 taken 736 times.
✓ Branch 1 taken 184 times.
920 for (int tid = 0; tid < actual_threads; ++tid) {
150
1/2
✓ Branch 0 taken 736 times.
✗ Branch 1 not taken.
736 if (error_flags[tid] != 0) {
151 return false;
152 }
153 }
154
155 double sum = 0.0;
156
2/2
✓ Branch 0 taken 736 times.
✓ Branch 1 taken 184 times.
920 for (int tid = 0; tid < actual_threads; ++tid) {
157 736 sum += partial_sums[tid];
158 }
159
160 184 GetOutput() = sum * cell_v;
161 184 return std::isfinite(GetOutput());
162 184 }
163
164 184 bool SannikovIIntegralsRectangleMethodSTL::PostProcessingImpl() {
165 184 return std::isfinite(GetOutput());
166 }
167
168 } // namespace sannikov_i_integrals_rectangle_method
169