GCC Code Coverage Report


Directory: ./
File: tasks/ovchinnikov_m_multidim_integrals_rectangle/mpi/src/ops_mpi.cpp
Date: 2026-01-27 01:59:34
Exec Total Coverage
Lines: 96 96 100.0%
Functions: 7 7 100.0%
Branches: 56 100 56.0%

Line Branch Exec Source
1 #include "ovchinnikov_m_multidim_integrals_rectangle/mpi/include/ops_mpi.hpp"
2
3 #include <mpi.h>
4
5 #include <array>
6 #include <cmath>
7 #include <cstddef>
8 #include <functional>
9 #include <vector>
10
11 #include "ovchinnikov_m_multidim_integrals_rectangle/common/include/common.hpp"
12
13 namespace ovchinnikov_m_multidim_integrals_rectangle {
14
15 namespace {
16 59756 double DefaultFunction(const std::vector<double> &point) {
17 double sum = 0.0;
18
2/2
✓ Branch 0 taken 195447 times.
✓ Branch 1 taken 59756 times.
255203 for (double coord : point) {
19 195447 sum += coord * coord;
20 }
21 59756 return sum;
22 }
23 54 double ComputePartialIntegral(const std::function<double(const std::vector<double> &)> &func, int n, int dim,
24 const std::vector<double> &lower_bounds, const std::vector<double> &steps,
25 double cell_volume, int start_point, int end_point) {
26 double partial_integral = 0.0;
27
28
1/2
✓ Branch 0 taken 54 times.
✗ Branch 1 not taken.
54 if (start_point >= end_point) {
29 return partial_integral;
30 }
31 54 std::vector<int> indices(dim);
32
1/4
✓ Branch 1 taken 54 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
54 std::vector<double> point(dim);
33
2/2
✓ Branch 0 taken 59756 times.
✓ Branch 1 taken 54 times.
59810 for (int idx = start_point; idx < end_point; idx++) {
34 int temp = idx;
35
2/2
✓ Branch 0 taken 195447 times.
✓ Branch 1 taken 59756 times.
255203 for (int i = dim - 1; i >= 0; i--) {
36 195447 indices[i] = temp % n;
37 195447 temp /= n;
38 }
39
40
2/2
✓ Branch 0 taken 195447 times.
✓ Branch 1 taken 59756 times.
255203 for (int i = 0; i < dim; i++) {
41 195447 point[i] = lower_bounds[i] + ((indices[i] + 0.5) * steps[i]);
42 }
43 59756 partial_integral += func(point) * cell_volume;
44 }
45
46 return partial_integral;
47 }
48
49 } // namespace
50
51
1/2
✓ Branch 1 taken 54 times.
✗ Branch 2 not taken.
54 OvchinnikovMMultiDimIntegralsRectangleMPI::OvchinnikovMMultiDimIntegralsRectangleMPI(const InType &in) {
52 SetTypeOfTask(GetStaticTypeOfTask());
53 GetInput() = in;
54 54 GetOutput() = 0.0;
55 54 }
56
57 54 bool OvchinnikovMMultiDimIntegralsRectangleMPI::ValidationImpl() {
58 const auto &input = GetInput();
59
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
54 if (std::get<0>(input) <= 0) {
60 return false;
61 }
62
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
54 if (std::get<1>(input) <= 0) {
63 return false;
64 }
65
66 const auto &lower_bounds = std::get<2>(input);
67 const auto &upper_bounds = std::get<3>(input);
68 int dim = std::get<1>(input);
69
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
54 if (lower_bounds.size() != static_cast<size_t>(dim)) {
70 return false;
71 }
72
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
54 if (upper_bounds.size() != static_cast<size_t>(dim)) {
73 return false;
74 }
75
76
2/2
✓ Branch 0 taken 136 times.
✓ Branch 1 taken 54 times.
190 for (int i = 0; i < dim; i++) {
77
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 136 times.
136 if (lower_bounds[i] >= upper_bounds[i]) {
78 return false;
79 }
80 }
81 return true;
82 }
83
84 54 bool OvchinnikovMMultiDimIntegralsRectangleMPI::PreProcessingImpl() {
85 54 return true;
86 }
87
88 54 bool OvchinnikovMMultiDimIntegralsRectangleMPI::RunImpl() {
89 54 int rank = 0;
90 54 int size = 0;
91 54 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
92 54 MPI_Comm_size(MPI_COMM_WORLD, &size);
93
94 const auto &input = GetInput();
95 54 int n = std::get<0>(input);
96
1/2
✓ Branch 1 taken 54 times.
✗ Branch 2 not taken.
54 int dim = std::get<1>(input);
97 const auto &lower_bounds = std::get<2>(input);
98 const auto &upper_bounds = std::get<3>(input);
99
100 std::function<double(const std::vector<double> &)> func = DefaultFunction;
101
102
1/4
✓ Branch 1 taken 54 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
54 std::vector<double> steps(dim);
103 54 double cell_volume = 1.0;
104
105
2/2
✓ Branch 0 taken 136 times.
✓ Branch 1 taken 54 times.
190 for (int i = 0; i < dim; i++) {
106 136 steps[i] = (upper_bounds[i] - lower_bounds[i]) / n;
107 136 cell_volume *= steps[i];
108 }
109
110 54 int total_points = static_cast<int>(std::pow(n, dim));
111
112 54 double local_integral = 0.0;
113 54 double global_integral = 0.0;
114
115
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 27 times.
54 if (rank == 0) {
116 27 std::array<int, 2> params = {n, dim};
117
1/2
✓ Branch 1 taken 27 times.
✗ Branch 2 not taken.
27 MPI_Bcast(params.data(), 2, MPI_INT, 0, MPI_COMM_WORLD);
118
1/2
✓ Branch 1 taken 27 times.
✗ Branch 2 not taken.
27 std::vector<double> all_bounds;
119
1/2
✓ Branch 1 taken 27 times.
✗ Branch 2 not taken.
27 all_bounds.insert(all_bounds.end(), lower_bounds.begin(), lower_bounds.end());
120 27 all_bounds.insert(all_bounds.end(), upper_bounds.begin(), upper_bounds.end());
121
122
1/2
✓ Branch 1 taken 27 times.
✗ Branch 2 not taken.
27 MPI_Bcast(all_bounds.data(), 2 * dim, MPI_DOUBLE, 0, MPI_COMM_WORLD);
123
1/2
✓ Branch 1 taken 27 times.
✗ Branch 2 not taken.
27 MPI_Bcast(&cell_volume, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
124
125 27 int points_per_process = total_points / size;
126 27 int remainder = total_points % size;
127
128 int start_point = 0;
129 27 int extra_points = static_cast<int>(remainder > 0);
130 27 int end_point = points_per_process + extra_points;
131
1/2
✓ Branch 1 taken 27 times.
✗ Branch 2 not taken.
27 local_integral = ComputePartialIntegral(func, n, dim, lower_bounds, steps, cell_volume, start_point, end_point);
132
133
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 27 times.
54 for (int i = 1; i < size; i++) {
134 start_point = 0;
135
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 27 times.
54 for (int j = 0; j < i; j++) {
136 27 int extra_points_for_j = static_cast<int>(j < remainder);
137 27 int points_for_j = points_per_process + extra_points_for_j;
138 27 start_point += points_for_j;
139 }
140 27 extra_points = static_cast<int>(i < remainder);
141 27 end_point = start_point + points_per_process + extra_points;
142
143 27 std::array<int, 2> range = {start_point, end_point};
144
1/2
✓ Branch 1 taken 27 times.
✗ Branch 2 not taken.
27 MPI_Send(range.data(), 2, MPI_INT, i, 0, MPI_COMM_WORLD);
145 }
146 27 global_integral = local_integral;
147
148
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 27 times.
54 for (int i = 1; i < size; i++) {
149 27 double partial_result = 0.0;
150
1/2
✓ Branch 1 taken 27 times.
✗ Branch 2 not taken.
27 MPI_Recv(&partial_result, 1, MPI_DOUBLE, i, 1, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
151 27 global_integral += partial_result;
152 }
153
154 27 GetOutput() = global_integral;
155
156
1/2
✓ Branch 1 taken 27 times.
✗ Branch 2 not taken.
27 MPI_Bcast(&global_integral, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
157 }
158
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 27 times.
54 if (rank != 0) {
159 27 std::array<int, 2> params{{0, 0}};
160
1/2
✓ Branch 1 taken 27 times.
✗ Branch 2 not taken.
27 MPI_Bcast(params.data(), 2, MPI_INT, 0, MPI_COMM_WORLD);
161 27 n = params[0];
162 27 dim = params[1];
163
164
1/4
✓ Branch 1 taken 27 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
27 std::vector<double> all_bounds(static_cast<size_t>(2) * dim);
165
1/2
✓ Branch 1 taken 27 times.
✗ Branch 2 not taken.
27 MPI_Bcast(all_bounds.data(), 2 * dim, MPI_DOUBLE, 0, MPI_COMM_WORLD);
166
167
2/6
✓ Branch 1 taken 27 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 27 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
27 std::vector<double> local_lower_bounds(all_bounds.begin(), all_bounds.begin() + dim);
168
1/4
✓ Branch 1 taken 27 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
27 std::vector<double> local_upper_bounds(all_bounds.begin() + dim, all_bounds.end());
169
170
1/2
✓ Branch 1 taken 27 times.
✗ Branch 2 not taken.
27 MPI_Bcast(&cell_volume, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
171
172
1/4
✓ Branch 1 taken 27 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
27 std::vector<double> local_steps(dim);
173
2/2
✓ Branch 0 taken 68 times.
✓ Branch 1 taken 27 times.
95 for (int i = 0; i < dim; i++) {
174 68 local_steps[i] = (local_upper_bounds[i] - local_lower_bounds[i]) / n;
175 }
176
177 27 std::array<int, 2> range{{0, 0}};
178
1/2
✓ Branch 1 taken 27 times.
✗ Branch 2 not taken.
27 MPI_Recv(range.data(), 2, MPI_INT, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
179
180 27 int start_point = range[0];
181 27 int end_point = range[1];
182
183 27 local_integral =
184
1/2
✓ Branch 1 taken 27 times.
✗ Branch 2 not taken.
27 ComputePartialIntegral(func, n, dim, local_lower_bounds, local_steps, cell_volume, start_point, end_point);
185
186
1/2
✓ Branch 1 taken 27 times.
✗ Branch 2 not taken.
27 MPI_Send(&local_integral, 1, MPI_DOUBLE, 0, 1, MPI_COMM_WORLD);
187
188
1/2
✓ Branch 1 taken 27 times.
✗ Branch 2 not taken.
27 MPI_Bcast(&global_integral, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
189
190
1/2
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
27 GetOutput() = global_integral;
191 }
192
193 54 return true;
194 }
195
196 54 bool OvchinnikovMMultiDimIntegralsRectangleMPI::PostProcessingImpl() {
197 54 return true;
198 }
199
200 } // namespace ovchinnikov_m_multidim_integrals_rectangle
201