GCC Code Coverage Report


Directory: ./
File: tasks/sannikov_i_integrals_rectangle_method/all/src/ops_all.cpp
Date: 2026-06-04 20:25:32
Exec Total Coverage
Lines: 60 60 100.0%
Functions: 6 6 100.0%
Branches: 44 74 59.5%

Line Branch Exec Source
1 #include "sannikov_i_integrals_rectangle_method/all/include/ops_all.hpp"
2
3 #include <mpi.h>
4 #include <omp.h>
5
6 #include <algorithm>
7 #include <cmath>
8 #include <cstddef>
9 #include <cstdint>
10 #include <functional>
11 #include <utility>
12 #include <vector>
13
14 #include "sannikov_i_integrals_rectangle_method/common/include/common.hpp"
15 #include "util/include/util.hpp"
16
17 namespace sannikov_i_integrals_rectangle_method {
18
19
1/2
✓ Branch 1 taken 46 times.
✗ Branch 2 not taken.
46 SannikovIIntegralsRectangleMethodALL::SannikovIIntegralsRectangleMethodALL(const InType &in) {
20 SetTypeOfTask(GetStaticTypeOfTask());
21 GetInput() = in;
22 46 GetOutput() = 0.0;
23 46 }
24
25
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
46 bool SannikovIIntegralsRectangleMethodALL::ValidationImpl() {
26 const auto &[func, borders, num] = GetInput();
27
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
46 if (borders.empty()) {
28 return false;
29 }
30
2/2
✓ Branch 0 taken 80 times.
✓ Branch 1 taken 46 times.
126 for (const auto &[left_border, right_border] : borders) {
31
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 80 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 80 times.
80 if (!std::isfinite(left_border) || !std::isfinite(right_border)) {
32 return false;
33 }
34
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 80 times.
80 if (left_border >= right_border) {
35 return false;
36 }
37 }
38
39
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 46 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 46 times.
46 return func && (num > 0) && (GetOutput() == 0.0);
40 }
41
42 46 bool SannikovIIntegralsRectangleMethodALL::PreProcessingImpl() {
43 46 GetOutput() = 0.0;
44 46 return true;
45 }
46
47 namespace {
48
49 3260 bool ComputeSlice(const std::function<double(const std::vector<double> &)> &funcx,
50 const std::vector<std::pair<double, double>> &brd, const std::vector<double> &h_vec,
51 std::size_t outer_dim, int64_t inner_cells, int num_splits, int outer, std::vector<int> &idx,
52 std::vector<double> &x, double &local_sum) {
53
2/2
✓ Branch 0 taken 1590 times.
✓ Branch 1 taken 3260 times.
4850 for (std::size_t i = 0; i < outer_dim; ++i) {
54 1590 idx[i] = 0;
55 }
56 3260 idx[outer_dim] = outer;
57 3260 x[outer_dim] = brd[outer_dim].first + ((static_cast<double>(outer) + 0.5) * h_vec[outer_dim]);
58
59
2/2
✓ Branch 0 taken 2550750 times.
✓ Branch 1 taken 3260 times.
2554010 for (int64_t cell = 0; cell < inner_cells; ++cell) {
60
2/2
✓ Branch 0 taken 5744800 times.
✓ Branch 1 taken 2550750 times.
8295550 for (std::size_t i = 0; i < outer_dim; ++i) {
61 5744800 x[i] = brd[i].first + ((static_cast<double>(idx[i]) + 0.5) * h_vec[i]);
62 }
63
64 const double fx = funcx(x);
65
1/2
✓ Branch 0 taken 2550750 times.
✗ Branch 1 not taken.
2550750 if (!std::isfinite(fx)) {
66 return false;
67 }
68
69 2550750 local_sum += fx;
70
71
2/2
✓ Branch 0 taken 2594700 times.
✓ Branch 1 taken 3260 times.
2597960 for (std::size_t pos = 0; pos < outer_dim; ++pos) {
72
2/2
✓ Branch 0 taken 47210 times.
✓ Branch 1 taken 2547490 times.
2594700 if (++idx[pos] < num_splits) {
73 break;
74 }
75 47210 idx[pos] = 0;
76 }
77 }
78 return true;
79 }
80
81 } // namespace
82
83 46 bool SannikovIIntegralsRectangleMethodALL::RunImpl() {
84 const auto &[func, borders, num] = GetInput();
85 const std::size_t dim = borders.size();
86
87 const auto &funcx = func;
88 const auto &brd = borders;
89 46 const int num_splits = num;
90
91 46 std::vector<double> h_vec(dim);
92 double cell_v = 1.0;
93
94
2/2
✓ Branch 0 taken 80 times.
✓ Branch 1 taken 46 times.
126 for (std::size_t i = 0; i < dim; ++i) {
95
1/2
✓ Branch 0 taken 80 times.
✗ Branch 1 not taken.
80 h_vec[i] = (brd[i].second - brd[i].first) / static_cast<double>(num_splits);
96
2/4
✓ Branch 0 taken 80 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 80 times.
✗ Branch 3 not taken.
80 if (!(h_vec[i] > 0.0) || !std::isfinite(h_vec[i])) {
97 return false;
98 }
99 80 cell_v *= h_vec[i];
100 }
101
102 46 const std::size_t outer_dim = dim - 1;
103
104 int64_t inner_cells = 1;
105
2/2
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 46 times.
80 for (std::size_t i = 0; i < outer_dim; ++i) {
106 34 inner_cells *= num_splits;
107 }
108
109 46 int rank = 0;
110 46 int num_procs = 1;
111
1/2
✓ Branch 1 taken 46 times.
✗ Branch 2 not taken.
46 const bool is_mpi = ppc::util::IsUnderMpirun();
112
113
1/2
✓ Branch 0 taken 46 times.
✗ Branch 1 not taken.
46 if (is_mpi) {
114
1/2
✓ Branch 1 taken 46 times.
✗ Branch 2 not taken.
46 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
115
1/2
✓ Branch 1 taken 46 times.
✗ Branch 2 not taken.
46 MPI_Comm_size(MPI_COMM_WORLD, &num_procs);
116 }
117
118 46 const int chunk = num_splits / num_procs;
119 46 const int rem = num_splits % num_procs;
120
1/2
✓ Branch 0 taken 46 times.
✗ Branch 1 not taken.
46 const int start = (rank * chunk) + std::min(rank, rem);
121
1/2
✓ Branch 0 taken 46 times.
✗ Branch 1 not taken.
46 const int end = start + chunk + (rank < rem ? 1 : 0);
122 46 const int local_n = end - start;
123
124 46 double local_sum = 0.0;
125 bool error_flag = false;
126
127
2/4
✓ Branch 1 taken 46 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 46 times.
✗ Branch 5 not taken.
46 const int num_threads = ppc::util::GetNumThreads();
128 const int max_threads = std::min(num_threads, local_n);
129
2/6
✓ Branch 1 taken 46 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 46 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
46 std::vector<std::vector<int>> all_idx(max_threads, std::vector<int>(dim, 0));
130
2/4
✓ Branch 1 taken 46 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 46 times.
✗ Branch 5 not taken.
46 std::vector<std::vector<double>> all_x(max_threads, std::vector<double>(dim));
131
132 46 #pragma omp parallel for schedule(static) num_threads(max_threads) reduction(+ : local_sum) \
133 shared(error_flag) default(none) \
134 shared(funcx, brd, h_vec, outer_dim, inner_cells, num_splits, start, end, all_idx, all_x)
135 for (int outer = start; outer < end; ++outer) {
136 if (error_flag) {
137 continue;
138 }
139
140 const int tid = omp_get_thread_num();
141 double slice_sum = 0.0;
142
143 if (!ComputeSlice(funcx, brd, h_vec, outer_dim, inner_cells, num_splits, outer, all_idx[tid], all_x[tid],
144 slice_sum)) {
145 error_flag = true;
146 }
147
148 local_sum += slice_sum;
149 }
150
151 46 double global_sum = local_sum;
152
1/2
✓ Branch 0 taken 46 times.
✗ Branch 1 not taken.
46 if (is_mpi) {
153
1/2
✓ Branch 1 taken 46 times.
✗ Branch 2 not taken.
46 MPI_Allreduce(&local_sum, &global_sum, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
154 }
155
156
1/2
✓ Branch 0 taken 46 times.
✗ Branch 1 not taken.
46 if (error_flag) {
157 return false;
158 }
159
160 46 GetOutput() = global_sum * cell_v;
161 46 return std::isfinite(GetOutput());
162 46 }
163
164 46 bool SannikovIIntegralsRectangleMethodALL::PostProcessingImpl() {
165 46 return std::isfinite(GetOutput());
166 }
167
168 } // namespace sannikov_i_integrals_rectangle_method
169