GCC Code Coverage Report


Directory: ./
File: tasks/tochilin_e_integral_trapezium/mpi/src/ops_mpi.cpp
Date: 2026-01-27 01:59:34
Exec Total Coverage
Lines: 87 87 100.0%
Functions: 6 6 100.0%
Branches: 50 70 71.4%

Line Branch Exec Source
1 #include "tochilin_e_integral_trapezium/mpi/include/ops_mpi.hpp"
2
3 #include <mpi.h>
4
5 #include <cstddef>
6 #include <vector>
7
8 #include "tochilin_e_integral_trapezium/common/include/common.hpp"
9
10 namespace tochilin_e_integral_trapezium {
11
12
1/2
✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
30 TochilinEIntegralTrapeziumMPI::TochilinEIntegralTrapeziumMPI(const InType &in) {
13 SetTypeOfTask(GetStaticTypeOfTask());
14
1/2
✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
30 GetInput() = in;
15 30 GetOutput() = 0.0;
16 30 }
17
18 30 bool TochilinEIntegralTrapeziumMPI::ValidationImpl() {
19 30 int rank = 0;
20 30 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
21
22
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 15 times.
30 if (rank == 0) {
23 const auto &input = GetInput();
24
25
2/4
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 15 times.
15 if (input.lower_bounds.empty() || input.upper_bounds.empty()) {
26 return false;
27 }
28
29
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if (input.lower_bounds.size() != input.upper_bounds.size()) {
30 return false;
31 }
32
33
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if (input.num_steps <= 0) {
34 return false;
35 }
36
37
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if (!input.func) {
38 return false;
39 }
40
41
2/2
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 15 times.
40 for (std::size_t idx = 0; idx < input.lower_bounds.size(); ++idx) {
42
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 if (input.lower_bounds[idx] > input.upper_bounds[idx]) {
43 return false;
44 }
45 }
46 }
47
48 return true;
49 }
50
51 30 bool TochilinEIntegralTrapeziumMPI::PreProcessingImpl() {
52 30 int rank = 0;
53 30 int size = 0;
54 30 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
55 30 MPI_Comm_size(MPI_COMM_WORLD, &size);
56
57 30 int dimensions = 0;
58
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 15 times.
30 if (rank == 0) {
59 const auto &input = GetInput();
60 15 lower_bounds_ = input.lower_bounds;
61 15 upper_bounds_ = input.upper_bounds;
62 15 num_steps_ = input.num_steps;
63 15 func_ = input.func;
64 15 dimensions = static_cast<int>(lower_bounds_.size());
65 }
66
67 30 MPI_Bcast(&dimensions, 1, MPI_INT, 0, MPI_COMM_WORLD);
68 30 MPI_Bcast(&num_steps_, 1, MPI_INT, 0, MPI_COMM_WORLD);
69
70
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 15 times.
30 if (rank != 0) {
71 15 lower_bounds_.resize(dimensions);
72 15 upper_bounds_.resize(dimensions);
73 15 func_ = GetInput().func;
74 }
75
76 30 MPI_Bcast(lower_bounds_.data(), dimensions, MPI_DOUBLE, 0, MPI_COMM_WORLD);
77 30 MPI_Bcast(upper_bounds_.data(), dimensions, MPI_DOUBLE, 0, MPI_COMM_WORLD);
78
79 int total_points = 1;
80
2/2
✓ Branch 0 taken 50 times.
✓ Branch 1 taken 30 times.
80 for (int idx = 0; idx < dimensions; ++idx) {
81 50 total_points *= (num_steps_ + 1);
82 }
83
84 30 int base_points_per_proc = total_points / size;
85 30 int remainder = total_points % size;
86
87 30 std::vector<int> counts(size);
88
1/4
✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
30 std::vector<int> displs(size);
89 int offset = 0;
90
2/2
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 30 times.
90 for (int idx = 0; idx < size; ++idx) {
91
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 28 times.
92 counts[idx] = base_points_per_proc + (idx < remainder ? 1 : 0);
92 60 displs[idx] = offset;
93 60 offset += counts[idx];
94 }
95
96
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 15 times.
30 if (rank == 0) {
97
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 15 times.
30 for (int dest = 1; dest < size; ++dest) {
98
1/2
✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
15 MPI_Send(&counts[dest], 1, MPI_INT, dest, 0, MPI_COMM_WORLD);
99
1/2
✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
15 MPI_Send(&displs[dest], 1, MPI_INT, dest, 1, MPI_COMM_WORLD);
100 }
101 15 start_idx_ = displs[0];
102 15 end_idx_ = displs[0] + counts[0];
103 } else {
104 15 int local_count = 0;
105 15 int local_displ = 0;
106
1/2
✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
15 MPI_Recv(&local_count, 1, MPI_INT, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
107
1/2
✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
15 MPI_Recv(&local_displ, 1, MPI_INT, 0, 1, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
108 15 start_idx_ = local_displ;
109 15 end_idx_ = local_displ + local_count;
110 }
111
112
1/2
✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
30 result_ = 0.0;
113 30 return true;
114 }
115
116 30 double TochilinEIntegralTrapeziumMPI::ComputePartialIntegral(int start_idx, int end_idx) {
117 std::size_t dimensions = lower_bounds_.size();
118 30 std::vector<double> step_sizes(dimensions);
119
2/2
✓ Branch 0 taken 50 times.
✓ Branch 1 taken 30 times.
80 for (std::size_t idx = 0; idx < dimensions; ++idx) {
120 50 step_sizes[idx] = (upper_bounds_[idx] - lower_bounds_[idx]) / num_steps_;
121 }
122
123 double sum = 0.0;
124
1/4
✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
30 std::vector<double> point(dimensions);
125
126
2/2
✓ Branch 0 taken 93866 times.
✓ Branch 1 taken 30 times.
93896 for (int idx = start_idx; idx < end_idx; ++idx) {
127 int temp = idx;
128 double weight = 1.0;
129
130
2/2
✓ Branch 0 taken 225576 times.
✓ Branch 1 taken 93866 times.
319442 for (std::size_t dim = 0; dim < dimensions; ++dim) {
131 225576 int grid_idx = temp % (num_steps_ + 1);
132
2/2
✓ Branch 0 taken 220251 times.
✓ Branch 1 taken 5325 times.
225576 temp /= (num_steps_ + 1);
133 225576 point[dim] = lower_bounds_[dim] + (grid_idx * step_sizes[dim]);
134
135
4/4
✓ Branch 0 taken 220251 times.
✓ Branch 1 taken 5325 times.
✓ Branch 2 taken 5325 times.
✓ Branch 3 taken 214926 times.
225576 if (grid_idx == 0 || grid_idx == num_steps_) {
136 10650 weight *= 0.5;
137 }
138 }
139
140 93866 sum += weight * func_(point);
141 }
142
143 double volume = 1.0;
144
2/2
✓ Branch 0 taken 50 times.
✓ Branch 1 taken 30 times.
80 for (std::size_t idx = 0; idx < dimensions; ++idx) {
145 50 volume *= step_sizes[idx];
146 }
147
148
1/2
✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
60 return sum * volume;
149 }
150
151 30 bool TochilinEIntegralTrapeziumMPI::RunImpl() {
152 30 double local_result = ComputePartialIntegral(start_idx_, end_idx_);
153
154 30 double global_result = 0.0;
155 30 MPI_Reduce(&local_result, &global_result, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD);
156
157 30 int rank = 0;
158 30 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
159
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 15 times.
30 if (rank == 0) {
160 15 result_ = global_result;
161 }
162
163 30 return true;
164 }
165
166 30 bool TochilinEIntegralTrapeziumMPI::PostProcessingImpl() {
167 30 MPI_Bcast(&result_, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
168 30 GetOutput() = result_;
169 30 return true;
170 }
171
172 } // namespace tochilin_e_integral_trapezium
173