GCC Code Coverage Report


Directory: ./
File: tasks/vinyaikina_e_multidimensional_integrals_simpson_method/omp/src/ops_omp.cpp
Date: 2026-04-02 17:12:27
Exec Total Coverage
Lines: 49 49 100.0%
Functions: 7 7 100.0%
Branches: 35 48 72.9%

Line Branch Exec Source
1 #include "vinyaikina_e_multidimensional_integrals_simpson_method/omp/include/ops_omp.hpp"
2
3 #include <omp.h>
4
5 #include <cmath>
6 #include <cstdlib>
7 #include <cstring>
8 #include <functional>
9 #include <stack>
10 #include <utility>
11 #include <vector>
12
13 #include "util/include/util.hpp"
14 #include "vinyaikina_e_multidimensional_integrals_simpson_method/common/include/common.hpp"
15
16 namespace vinyaikina_e_multidimensional_integrals_simpson_method {
17 namespace {
18
19 192 double CustomRound(double value, double h) {
20 192 h *= 2;
21 192 int tmp = static_cast<int>(1 / h);
22 int decimal_places = 0;
23
3/4
✓ Branch 0 taken 540 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 348 times.
✓ Branch 3 taken 192 times.
540 while (tmp > 0 && tmp % 10 == 0) {
24 348 decimal_places++;
25 348 tmp /= 10;
26 }
27
28 double factor = std::pow(10.0, decimal_places);
29 192 return std::round(value * factor) / factor;
30 }
31
32 double Weight(int i, int steps_count) {
33 double weight = 2.0;
34
2/2
✓ Branch 0 taken 27404 times.
✓ Branch 1 taken 314 times.
27718 if (i == 0 || i == steps_count) {
35 weight = 1.0;
36
4/4
✓ Branch 0 taken 13777 times.
✓ Branch 1 taken 13627 times.
✓ Branch 2 taken 1184496 times.
✓ Branch 3 taken 1145304 times.
2357204 } else if (i % 2 != 0) {
37 weight = 4.0;
38 }
39 return weight;
40 }
41
42 160 double OuntNtIntegral(double left_border, double right_border, double simpson_factor,
43 const std::vector<std::pair<double, double>> &limits, const std::vector<double> &actual_step,
44 const std::function<double(const std::vector<double> &)> &function) {
45 std::stack<std::pair<std::vector<double>, double>> stack;
46 double res = 0.0;
47
48 160 int steps_count_0 = static_cast<int>(lround((right_border - left_border) / actual_step[0]));
49
50
2/2
✓ Branch 0 taken 27718 times.
✓ Branch 1 taken 160 times.
27878 for (int i0 = 0; i0 <= steps_count_0; ++i0) {
51
2/2
✓ Branch 0 taken 27404 times.
✓ Branch 1 taken 314 times.
27718 double x0 = left_border + (i0 * actual_step[0]);
52
53 27718 double weight_0 = Weight(i0, steps_count_0);
54
1/2
✓ Branch 1 taken 27718 times.
✗ Branch 2 not taken.
27718 stack.emplace(std::vector<double>{x0}, weight_0);
55
56
2/2
✓ Branch 0 taken 2435902 times.
✓ Branch 1 taken 27718 times.
2463620 while (!stack.empty()) {
57
1/2
✓ Branch 1 taken 2435902 times.
✗ Branch 2 not taken.
2435902 std::vector<double> point = stack.top().first;
58 2435902 double weight = stack.top().second;
59 stack.pop();
60
61
2/2
✓ Branch 0 taken 2396710 times.
✓ Branch 1 taken 39192 times.
2435902 if (point.size() == limits.size()) {
62
1/2
✓ Branch 0 taken 2396710 times.
✗ Branch 1 not taken.
2396710 res += function(point) * weight * simpson_factor;
63 continue;
64 }
65
66 size_t dim = point.size();
67 39192 double step = actual_step[dim];
68
69 39192 int steps_count = static_cast<int>(lround((limits[dim].second - limits[dim].first) / step));
70
71
2/2
✓ Branch 0 taken 2408184 times.
✓ Branch 1 taken 39192 times.
2447376 for (int i = 0; i <= steps_count; ++i) {
72
2/2
✓ Branch 0 taken 2329800 times.
✓ Branch 1 taken 78384 times.
2408184 double x = limits[dim].first + (i * step);
73
74 double dim_weight = Weight(i, steps_count);
75
76 point.push_back(x);
77
1/4
✓ Branch 1 taken 2408184 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
2408184 stack.emplace(point, weight * dim_weight);
78 point.pop_back();
79 }
80 }
81 }
82
83 160 return res;
84 }
85 }; // namespace
86
87
1/2
✓ Branch 1 taken 64 times.
✗ Branch 2 not taken.
64 VinyaikinaEMultidimIntegrSimpsonOMP::VinyaikinaEMultidimIntegrSimpsonOMP(const InType &in) {
88 SetTypeOfTask(GetStaticTypeOfTask());
89 GetInput() = in;
90 64 }
91
92 64 bool VinyaikinaEMultidimIntegrSimpsonOMP::PreProcessingImpl() {
93 64 return true;
94 }
95
96
1/2
✓ Branch 0 taken 64 times.
✗ Branch 1 not taken.
64 bool VinyaikinaEMultidimIntegrSimpsonOMP::ValidationImpl() {
97 const auto &[h, limits, function] = GetInput();
98
3/6
✓ Branch 0 taken 64 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 64 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 64 times.
64 return !limits.empty() && function && h <= 0.01;
99 }
100
101 64 bool VinyaikinaEMultidimIntegrSimpsonOMP::RunImpl() {
102 const auto &input = GetInput();
103 64 double h = std::get<0>(input);
104 const auto &limits = std::get<1>(input);
105 const auto &function = std::get<2>(input);
106
107 64 const int num_threads = ppc::util::GetNumThreads();
108
109 64 double delta = (limits[0].second - limits[0].first) / num_threads;
110 double res = 0.0;
111
112 64 std::vector<double> actual_step(limits.size());
113 double simpson_factor = 1.0;
114
115
2/2
✓ Branch 0 taken 112 times.
✓ Branch 1 taken 64 times.
176 for (size_t i = 0; i < limits.size(); i++) {
116 112 int quan_steps = static_cast<int>(lround((limits[i].second - limits[i].first) / h));
117
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 96 times.
112 if (quan_steps % 2 != 0) {
118 16 quan_steps++;
119 }
120 112 actual_step[i] = (limits[i].second - limits[i].first) / quan_steps;
121 112 simpson_factor *= actual_step[i] / 3.0;
122 }
123
124 64 #pragma omp parallel num_threads(num_threads) default(none) \
125 shared(limits, simpson_factor, actual_step, delta, function, num_threads) reduction(+ : res)
126 {
127 double left_border = limits[0].first;
128 double right_border = limits[0].second;
129 if (omp_get_thread_num() != 0) {
130 left_border = CustomRound(limits[0].first + (delta * omp_get_thread_num()), actual_step[0]);
131 }
132 if (omp_get_thread_num() != num_threads - 1) {
133 right_border = CustomRound(limits[0].second - (delta * (num_threads - omp_get_thread_num() - 1)), actual_step[0]);
134 }
135
136 res += OuntNtIntegral(left_border, right_border, simpson_factor, limits, actual_step, function);
137 }
138
139
1/2
✓ Branch 0 taken 64 times.
✗ Branch 1 not taken.
64 I_res_ = res;
140
141 64 return true;
142 }
143
144 64 bool VinyaikinaEMultidimIntegrSimpsonOMP::PostProcessingImpl() {
145 64 GetOutput() = I_res_;
146 64 return true;
147 }
148 } // namespace vinyaikina_e_multidimensional_integrals_simpson_method
149