GCC Code Coverage Report


Directory: ./
File: tasks/sannikov_i_integrals_rectangle_method/omp/src/ops_omp.cpp
Date: 2026-05-11 08:26:31
Exec Total Coverage
Lines: 45 45 100.0%
Functions: 6 6 100.0%
Branches: 34 54 63.0%

Line Branch Exec Source
1 #include "sannikov_i_integrals_rectangle_method/omp/include/ops_omp.hpp"
2
3 #include <omp.h>
4
5 #include <cmath>
6 #include <cstddef>
7 #include <cstdint>
8 #include <functional>
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 92 times.
✗ Branch 2 not taken.
92 SannikovIIntegralsRectangleMethodOMP::SannikovIIntegralsRectangleMethodOMP(const InType &in) {
17 SetTypeOfTask(GetStaticTypeOfTask());
18 GetInput() = in;
19 92 GetOutput() = 0.0;
20 92 }
21
22
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 92 times.
92 bool SannikovIIntegralsRectangleMethodOMP::ValidationImpl() {
23 const auto &[func, borders, n] = GetInput();
24
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 92 times.
92 if (borders.empty()) {
25 return false;
26 }
27
2/2
✓ Branch 0 taken 160 times.
✓ Branch 1 taken 92 times.
252 for (const auto &[left_border, right_border] : borders) {
28
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 160 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 160 times.
160 if (!std::isfinite(left_border) || !std::isfinite(right_border)) {
29 return false;
30 }
31
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 160 times.
160 if (left_border >= right_border) {
32 return false;
33 }
34 }
35
36
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 92 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 92 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 92 times.
92 return func && (n > 0) && (GetOutput() == 0.0);
37 }
38
39 92 bool SannikovIIntegralsRectangleMethodOMP::PreProcessingImpl() {
40 92 GetOutput() = 0.0;
41 92 return true;
42 }
43
44 namespace {
45
46 13040 bool ComputeSlice(const std::function<double(const std::vector<double> &)> &f,
47 const std::vector<std::pair<double, double>> &brd, const std::vector<double> &h,
48 std::size_t outer_dim, int64_t inner_cells, int num_splits, int outer, std::vector<int> &idx,
49 std::vector<double> &x, double &local_sum) {
50
2/2
✓ Branch 0 taken 6360 times.
✓ Branch 1 taken 13040 times.
19400 for (std::size_t i = 0; i < outer_dim; ++i) {
51 6360 idx[i] = 0;
52 }
53 13040 idx[outer_dim] = outer;
54 13040 x[outer_dim] = brd[outer_dim].first + ((static_cast<double>(outer) + 0.5) * h[outer_dim]);
55
56
2/2
✓ Branch 0 taken 10203000 times.
✓ Branch 1 taken 13040 times.
10216040 for (int64_t cell = 0; cell < inner_cells; ++cell) {
57
2/2
✓ Branch 0 taken 22979200 times.
✓ Branch 1 taken 10203000 times.
33182200 for (std::size_t i = 0; i < outer_dim; ++i) {
58 22979200 x[i] = brd[i].first + ((static_cast<double>(idx[i]) + 0.5) * h[i]);
59 }
60
61 const double fx = f(x);
62
1/2
✓ Branch 0 taken 10203000 times.
✗ Branch 1 not taken.
10203000 if (!std::isfinite(fx)) {
63 return false;
64 }
65
66 10203000 local_sum += fx;
67
68
2/2
✓ Branch 0 taken 10378800 times.
✓ Branch 1 taken 13040 times.
10391840 for (std::size_t pos = 0; pos < outer_dim; ++pos) {
69
2/2
✓ Branch 0 taken 188840 times.
✓ Branch 1 taken 10189960 times.
10378800 if (++idx[pos] < num_splits) {
70 break;
71 }
72 188840 idx[pos] = 0;
73 }
74 }
75 return true;
76 }
77
78 } // namespace
79
80 92 bool SannikovIIntegralsRectangleMethodOMP::RunImpl() {
81 const auto &[func, borders, n] = GetInput();
82 const std::size_t dim = borders.size();
83
84 const auto &f = func;
85 const auto &brd = borders;
86 92 const int num_splits = n;
87
88 92 std::vector<double> h(dim);
89 double cell_v = 1.0;
90
91
2/2
✓ Branch 0 taken 160 times.
✓ Branch 1 taken 92 times.
252 for (std::size_t i = 0; i < dim; ++i) {
92
1/2
✓ Branch 0 taken 160 times.
✗ Branch 1 not taken.
160 h[i] = (brd[i].second - brd[i].first) / static_cast<double>(num_splits);
93
2/4
✓ Branch 0 taken 160 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 160 times.
✗ Branch 3 not taken.
160 if (!(h[i] > 0.0) || !std::isfinite(h[i])) {
94 return false;
95 }
96 160 cell_v *= h[i];
97 }
98
99 92 const std::size_t outer_dim = dim - 1;
100
101 int64_t inner_cells = 1;
102
2/2
✓ Branch 0 taken 68 times.
✓ Branch 1 taken 92 times.
160 for (std::size_t i = 0; i < outer_dim; ++i) {
103 68 inner_cells *= num_splits;
104 }
105
106 92 const int max_threads = omp_get_max_threads();
107
2/6
✓ Branch 1 taken 92 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 92 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
92 std::vector<std::vector<int>> all_idx(max_threads, std::vector<int>(dim, 0));
108
2/4
✓ Branch 1 taken 92 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 92 times.
✗ Branch 5 not taken.
92 std::vector<std::vector<double>> all_x(max_threads, std::vector<double>(dim));
109
110 double sum = 0.0;
111 bool error_flag = false;
112
113 92 #pragma omp parallel for schedule(static) reduction(+ : sum) shared(error_flag) default(none) \
114 shared(f, brd, h, outer_dim, inner_cells, num_splits, all_idx, all_x)
115 for (int outer = 0; outer < num_splits; ++outer) {
116 if (error_flag) {
117 continue;
118 }
119
120 const int tid = omp_get_thread_num();
121 double local_sum = 0.0;
122
123 if (!ComputeSlice(f, brd, h, outer_dim, inner_cells, num_splits, outer, all_idx[tid], all_x[tid], local_sum)) {
124 error_flag = true;
125 }
126
127 sum += local_sum;
128 }
129
130
1/2
✓ Branch 0 taken 92 times.
✗ Branch 1 not taken.
92 if (error_flag) {
131 return false;
132 }
133
134 92 GetOutput() = sum * cell_v;
135 92 return std::isfinite(GetOutput());
136 92 }
137
138 92 bool SannikovIIntegralsRectangleMethodOMP::PostProcessingImpl() {
139 92 return std::isfinite(GetOutput());
140 }
141
142 } // namespace sannikov_i_integrals_rectangle_method
143