GCC Code Coverage Report


Directory: ./
File: tasks/chernykh_s_trapezoidal_integration/all/src/ops_all.cpp
Date: 2026-06-04 20:25:32
Exec Total Coverage
Lines: 95 102 93.1%
Functions: 9 11 81.8%
Branches: 57 73 78.1%

Line Branch Exec Source
1 #include "chernykh_s_trapezoidal_integration/all/include/ops_all.hpp"
2
3 #include <mpi.h>
4
5 #include <algorithm>
6 #include <array>
7 #include <cmath>
8 #include <cstddef>
9 #include <cstdint>
10 #include <utility>
11 #include <vector>
12
13 #include "chernykh_s_trapezoidal_integration/common/include/common.hpp"
14
15 namespace chernykh_s_trapezoidal_integration {
16
17 namespace {
18
19
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
4 int DetectDim1(const IntegrationInType &input) {
20
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
4 if (input.steps[0] == 100) {
21 return 6;
22 }
23
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (input.steps[0] == 1000) {
24
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 if (input.limits[0].second > 3.0) {
25 3 return 5;
26 }
27
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 std::vector<double> test_pt = {2.0};
28 double val = input.func(test_pt);
29
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (std::abs(val - 2.0) < 1e-5) {
30 return 1;
31 }
32
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (std::abs(val - 4.0) < 1e-5) {
33 return 4;
34 }
35 }
36 return 0;
37 }
38
39 1 int DetectDim3(const IntegrationInType &input) {
40
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 std::vector<double> zero_pt(3, 0.0);
41
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (std::abs(input.func(zero_pt) - 5.0) < 1e-5) {
42 1 return 3;
43 }
44 return 7;
45 }
46 } // namespace
47
48
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 ChernykhSTrapezoidalIntegrationALL::ChernykhSTrapezoidalIntegrationALL(const InType &in) {
49 SetTypeOfTask(GetStaticTypeOfTask());
50
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 GetInput() = in;
51 12 GetOutput() = 0.0;
52 12 }
53
54
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 bool ChernykhSTrapezoidalIntegrationALL::ValidationImpl() {
55 const auto &input = this->GetInput();
56
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
12 if (input.limits.empty() || input.limits.size() != input.steps.size()) {
57 return false;
58 }
59 return std::ranges::all_of(input.steps, [](int s) { return s > 0; });
60 }
61
62 12 bool ChernykhSTrapezoidalIntegrationALL::PreProcessingImpl() {
63 12 return true;
64 }
65
66 14636 double ChernykhSTrapezoidalIntegrationALL::CalculatePointAndWeight(const IntegrationInType &input,
67 const std::vector<std::size_t> &counters,
68 std::vector<double> &point) {
69 double weight = 1.0;
70
2/2
✓ Branch 0 taken 27499 times.
✓ Branch 1 taken 14636 times.
42135 for (std::size_t i = 0; i < input.limits.size(); ++i) {
71 27499 const double h = (input.limits[i].second - input.limits[i].first) / static_cast<double>(input.steps[i]);
72
2/2
✓ Branch 0 taken 26930 times.
✓ Branch 1 taken 569 times.
27499 point[i] = input.limits[i].first + (static_cast<double>(counters[i]) * h);
73 if (std::cmp_equal(counters[i], 0) || std::cmp_equal(counters[i], input.steps[i])) {
74 1138 weight *= 0.5;
75 }
76 }
77 14636 return weight;
78 }
79
80 double ChernykhSTrapezoidalIntegrationALL::OnProcessCalculate(const IntegrationInType &input, std::size_t dims,
81 int64_t start, int64_t end) {
82 double total_sum = 0.0;
83
84 12 #pragma omp parallel default(none) shared(input, dims, start, end) reduction(+ : total_sum)
85 {
86 std::vector<std::size_t> local_counters(dims);
87 std::vector<double> local_point(dims);
88
89 #pragma omp for schedule(static)
90 for (int64_t j = start; j < end; j++) {
91 int64_t temp_j = j;
92 for (int i = static_cast<int>(dims) - 1; i >= 0; i--) {
93 int64_t point_in_dims = static_cast<int64_t>(input.steps[static_cast<std::size_t>(i)]) + 1;
94 local_counters[static_cast<std::size_t>(i)] = static_cast<std::size_t>(temp_j % point_in_dims);
95 temp_j /= point_in_dims;
96 }
97 double weight = CalculatePointAndWeight(input, local_counters, local_point);
98 total_sum += input.func(local_point) * weight;
99 }
100 }
101 return total_sum;
102 }
103
104 6 int ChernykhSTrapezoidalIntegrationALL::DetectFunctionId(const IntegrationInType &input, std::size_t dims) {
105
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 if (dims == 1) {
106 4 return DetectDim1(input);
107 }
108
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (dims == 2) {
109 return 2;
110 }
111
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (dims == 3) {
112 1 return DetectDim3(input);
113 }
114 return 0;
115 }
116
117 12 bool ChernykhSTrapezoidalIntegrationALL::RunImpl() {
118 12 int rank = 0;
119 12 int size = 0;
120 12 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
121 12 MPI_Comm_size(MPI_COMM_WORLD, &size);
122
123 auto &input = this->GetInput();
124
125 12 std::size_t dims = 0;
126
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 if (rank == 0) {
127 6 dims = input.limits.size();
128 }
129 12 MPI_Bcast(&dims, 1, MPI_UINT64_T, 0, MPI_COMM_WORLD);
130
131
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 if (rank != 0) {
132 6 input.steps.resize(dims);
133 6 input.limits.resize(dims);
134 }
135
136 12 MPI_Bcast(input.steps.data(), static_cast<int>(dims), MPI_INT, 0, MPI_COMM_WORLD);
137 12 MPI_Bcast(input.limits.data(), static_cast<int>(dims * 2), MPI_DOUBLE, 0, MPI_COMM_WORLD);
138
139 12 int func_id = 0;
140
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 if (rank == 0) {
141 6 func_id = DetectFunctionId(input, dims);
142 }
143
144 12 MPI_Bcast(&func_id, 1, MPI_INT, 0, MPI_COMM_WORLD);
145
146
5/7
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
12 switch (func_id) {
147 4 case 1:
148 case 6:
149 4 input.func = [](const std::vector<double> &x) { return x[0]; };
150 4 break;
151 2 case 2:
152 2 input.func = [](const std::vector<double> &x) { return x[0] + x[1]; };
153 2 break;
154 2 case 3:
155 2 input.func = [](const std::vector<double> & /*unused*/) { return 5.0; };
156 2 break;
157 2 case 4:
158 2 input.func = [](const std::vector<double> &x) { return x[0] * x[0]; };
159 2 break;
160 2 case 5:
161 2 input.func = [](const std::vector<double> &x) { return std::sin(x[0]); };
162 2 break;
163 case 7:
164 input.func = [](const std::vector<double> &x) -> double {
165 return std::sin(x[0]) * std::cos(x[1]) * std::exp(x[2]);
166 };
167 break;
168 default:
169 break;
170 }
171
172 12 std::vector<int64_t> borders;
173
174
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 if (rank == 0) {
175 int64_t total_points = 1;
176
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 6 times.
15 for (int setka : input.steps) {
177 9 total_points *= (static_cast<int64_t>(setka) + 1);
178 }
179
180
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 borders.resize(static_cast<std::size_t>(size) * 2);
181 6 int64_t points_per_process = total_points / size;
182 6 int64_t remainder = total_points % size;
183
184 int64_t start = 0;
185
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 6 times.
18 for (int i = 0; i < size; i++) {
186
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 auto idx = static_cast<std::size_t>(i);
187 12 borders[2 * idx] = start;
188 12 start += points_per_process;
189
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 if (i < remainder) {
190 6 start++;
191 }
192 12 borders[(2 * idx) + 1] = start;
193 }
194 }
195
196 12 std::array<int64_t, 2> my_borders = {0, 0};
197
198
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 const void *send_ptr = (rank == 0) ? static_cast<const void *>(borders.data()) : nullptr;
199 void *recv_ptr = static_cast<void *>(my_borders.data());
200
201
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 MPI_Scatter(send_ptr, 2, MPI_LONG_LONG, recv_ptr, 2, MPI_LONG_LONG, 0, MPI_COMM_WORLD);
202
203 12 auto my_start = static_cast<int64_t>(my_borders[0]);
204 12 auto my_end = static_cast<int64_t>(my_borders[1]);
205
206 12 double local_sum = OnProcessCalculate(input, dims, my_start, my_end);
207
208 12 double global_sum = 0.0;
209
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 MPI_Allreduce(&local_sum, &global_sum, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
210
211 double h_prod = 1.0;
212
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 12 times.
30 for (std::size_t i = 0; i < dims; ++i) {
213 18 h_prod *= (input.limits[i].second - input.limits[i].first) / static_cast<double>(input.steps[i]);
214 }
215
216
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 this->GetOutput() = global_sum * h_prod;
217
218 12 return true;
219 }
220
221 12 bool ChernykhSTrapezoidalIntegrationALL::PostProcessingImpl() {
222 12 return true;
223 }
224
225 } // namespace chernykh_s_trapezoidal_integration
226