GCC Code Coverage Report


Directory: ./
File: tasks/vinyaikina_e_multidimensional_integrals_simpson_method/all/src/ops_all.cpp
Date: 2026-06-04 20:25:32
Exec Total Coverage
Lines: 62 62 100.0%
Functions: 7 7 100.0%
Branches: 43 60 71.7%

Line Branch Exec Source
1 #include "vinyaikina_e_multidimensional_integrals_simpson_method/all/include/ops_all.hpp"
2
3 #include <mpi.h>
4 #include <omp.h>
5
6 #include <cmath>
7 #include <cstdlib>
8 #include <cstring>
9 #include <functional>
10 #include <stack>
11 #include <utility>
12 #include <vector>
13
14 #include "util/include/util.hpp"
15 #include "vinyaikina_e_multidimensional_integrals_simpson_method/common/include/common.hpp"
16
17 namespace vinyaikina_e_multidimensional_integrals_simpson_method {
18 namespace {
19
20 96 double CustomRound(double value, double h) {
21 96 h *= 2;
22 96 int tmp = static_cast<int>(1 / h);
23 int decimal_places = 0;
24
3/4
✓ Branch 0 taken 264 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 168 times.
✓ Branch 3 taken 96 times.
264 while (tmp > 0 && tmp % 10 == 0) {
25 168 decimal_places++;
26 168 tmp /= 10;
27 }
28
29 double factor = std::pow(10.0, decimal_places);
30 96 return std::round(value * factor) / factor;
31 }
32
33 double Weight(int i, int steps_count) {
34 double weight = 2.0;
35
2/2
✓ Branch 0 taken 6788 times.
✓ Branch 1 taken 123 times.
6911 if (i == 0 || i == steps_count) {
36 weight = 1.0;
37
4/4
✓ Branch 0 taken 3423 times.
✓ Branch 1 taken 3365 times.
✓ Branch 2 taken 184056 times.
✓ Branch 3 taken 177648 times.
368492 } else if (i % 2 != 0) {
38 weight = 4.0;
39 }
40 return weight;
41 }
42
43 64 double OuntNtIntegral(double left_border, double right_border, double simpson_factor,
44 const std::vector<std::pair<double, double>> &limits, const std::vector<double> &actual_step,
45 const std::function<double(const std::vector<double> &)> &function) {
46 std::stack<std::pair<std::vector<double>, double>> stack;
47 double res = 0.0;
48
49 64 int steps_count_0 = static_cast<int>(lround((right_border - left_border) / actual_step[0]));
50
51
2/2
✓ Branch 0 taken 6911 times.
✓ Branch 1 taken 64 times.
6975 for (int i0 = 0; i0 <= steps_count_0; ++i0) {
52
2/2
✓ Branch 0 taken 6788 times.
✓ Branch 1 taken 123 times.
6911 double x0 = left_border + (i0 * actual_step[0]);
53
54 6911 double weight_0 = Weight(i0, steps_count_0);
55
1/2
✓ Branch 1 taken 6911 times.
✗ Branch 2 not taken.
6911 stack.emplace(std::vector<double>{x0}, weight_0);
56
57
2/2
✓ Branch 0 taken 381431 times.
✓ Branch 1 taken 6911 times.
388342 while (!stack.empty()) {
58
1/2
✓ Branch 1 taken 381431 times.
✗ Branch 2 not taken.
381431 std::vector<double> point = stack.top().first;
59 381431 double weight = stack.top().second;
60 stack.pop();
61
62
2/2
✓ Branch 0 taken 375023 times.
✓ Branch 1 taken 6408 times.
381431 if (point.size() == limits.size()) {
63
1/2
✓ Branch 0 taken 375023 times.
✗ Branch 1 not taken.
375023 res += function(point) * weight * simpson_factor;
64 continue;
65 }
66
67 size_t dim = point.size();
68 6408 double step = actual_step[dim];
69
70 6408 int steps_count = static_cast<int>(lround((limits[dim].second - limits[dim].first) / step));
71
72
2/2
✓ Branch 0 taken 374520 times.
✓ Branch 1 taken 6408 times.
380928 for (int i = 0; i <= steps_count; ++i) {
73
2/2
✓ Branch 0 taken 361704 times.
✓ Branch 1 taken 12816 times.
374520 double x = limits[dim].first + (i * step);
74
75 double dim_weight = Weight(i, steps_count);
76
77 point.push_back(x);
78
1/4
✓ Branch 1 taken 374520 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
374520 stack.emplace(point, weight * dim_weight);
79 point.pop_back();
80 }
81 }
82 }
83
84 64 return res;
85 }
86 }; // namespace
87
88
1/2
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
32 VinyaikinaEMultidimIntegrSimpsonALL::VinyaikinaEMultidimIntegrSimpsonALL(const InType &in) {
89 SetTypeOfTask(GetStaticTypeOfTask());
90 GetInput() = in;
91 32 }
92
93 32 bool VinyaikinaEMultidimIntegrSimpsonALL::PreProcessingImpl() {
94 32 return true;
95 }
96
97
1/2
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
32 bool VinyaikinaEMultidimIntegrSimpsonALL::ValidationImpl() {
98 const auto &[h, limits, function] = GetInput();
99
3/6
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 32 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 32 times.
32 return !limits.empty() && function && h <= 0.01;
100 }
101
102 32 bool VinyaikinaEMultidimIntegrSimpsonALL::RunImpl() {
103 const auto &input = GetInput();
104 32 double h = std::get<0>(input);
105 const auto &limits = std::get<1>(input);
106 const auto &function = std::get<2>(input);
107
108 32 const int num_threads = ppc::util::GetNumThreads();
109
110 32 std::vector<double> actual_step(limits.size());
111 double simpson_factor = 1.0;
112
113
2/2
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 32 times.
88 for (size_t i = 0; i < limits.size(); i++) {
114 56 int quan_steps = static_cast<int>(lround((limits[i].second - limits[i].first) / h));
115
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 48 times.
56 if (quan_steps % 2 != 0) {
116 8 quan_steps++;
117 }
118 56 actual_step[i] = (limits[i].second - limits[i].first) / quan_steps;
119 56 simpson_factor *= actual_step[i] / 3.0;
120 }
121
122 32 int mpi_rank = 0;
123 32 int mpi_size = 0;
124
1/2
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
32 MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank);
125
1/2
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
32 MPI_Comm_size(MPI_COMM_WORLD, &mpi_size);
126
127 32 double delta_mpi = (limits[0].second - limits[0].first) / mpi_size;
128
129 double proc_left = limits[0].first;
130 double proc_right = limits[0].second;
131
132
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 16 times.
32 if (mpi_rank != 0) {
133 16 proc_left = CustomRound(limits[0].first + (delta_mpi * mpi_rank), actual_step[0]);
134 }
135
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 16 times.
32 if (mpi_rank != mpi_size - 1) {
136 16 proc_right = CustomRound(limits[0].second - (delta_mpi * (mpi_size - mpi_rank - 1)), actual_step[0]);
137 }
138
139 32 double res = 0.0;
140 32 double delta_omp = (proc_right - proc_left) / num_threads;
141
142 32 #pragma omp parallel num_threads(num_threads) default(none) \
143 shared(proc_left, proc_right, limits, simpson_factor, actual_step, delta_omp, function, num_threads) \
144 reduction(+ : res)
145 {
146 double left_border = proc_left;
147 double right_border = proc_right;
148 int tid = omp_get_thread_num();
149
150 if (tid != 0) {
151 left_border = CustomRound(proc_left + (delta_omp * tid), actual_step[0]);
152 }
153 if (tid != num_threads - 1) {
154 right_border = CustomRound(proc_right - (delta_omp * (num_threads - tid - 1)), actual_step[0]);
155 }
156
157 res += OuntNtIntegral(left_border, right_border, simpson_factor, limits, actual_step, function);
158 }
159
160 32 double global_res = 0.0;
161
1/2
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
32 MPI_Reduce(&res, &global_res, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD);
162
1/2
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
32 MPI_Bcast(&global_res, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
163
164
1/2
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
32 I_res_ = global_res;
165
166 32 return true;
167 }
168
169 32 bool VinyaikinaEMultidimIntegrSimpsonALL::PostProcessingImpl() {
170 32 GetOutput() = I_res_;
171 32 return true;
172 }
173 } // namespace vinyaikina_e_multidimensional_integrals_simpson_method
174