| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #include "sannikov_i_integrals_rectangle_method/stl/include/ops_stl.hpp" | ||
| 2 | |||
| 3 | #include <algorithm> | ||
| 4 | #include <cmath> | ||
| 5 | #include <cstddef> | ||
| 6 | #include <cstdint> | ||
| 7 | #include <functional> | ||
| 8 | #include <thread> | ||
| 9 | #include <utility> | ||
| 10 | #include <vector> | ||
| 11 | |||
| 12 | #include "sannikov_i_integrals_rectangle_method/common/include/common.hpp" | ||
| 13 | |||
| 14 | namespace sannikov_i_integrals_rectangle_method { | ||
| 15 | |||
| 16 |
1/2✓ Branch 1 taken 184 times.
✗ Branch 2 not taken.
|
184 | SannikovIIntegralsRectangleMethodSTL::SannikovIIntegralsRectangleMethodSTL(const InType &in) { |
| 17 | SetTypeOfTask(GetStaticTypeOfTask()); | ||
| 18 | GetInput() = in; | ||
| 19 | 184 | GetOutput() = 0.0; | |
| 20 | 184 | } | |
| 21 | |||
| 22 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 184 times.
|
184 | bool SannikovIIntegralsRectangleMethodSTL::ValidationImpl() { |
| 23 | const auto &[func, borders, num] = GetInput(); | ||
| 24 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 184 times.
|
184 | if (borders.empty()) { |
| 25 | return false; | ||
| 26 | } | ||
| 27 |
2/2✓ Branch 0 taken 320 times.
✓ Branch 1 taken 184 times.
|
504 | for (const auto &[left_border, right_border] : borders) { |
| 28 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 320 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 320 times.
|
320 | if (!std::isfinite(left_border) || !std::isfinite(right_border)) { |
| 29 | return false; | ||
| 30 | } | ||
| 31 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 320 times.
|
320 | if (left_border >= right_border) { |
| 32 | return false; | ||
| 33 | } | ||
| 34 | } | ||
| 35 | |||
| 36 |
3/6✗ Branch 0 not taken.
✓ Branch 1 taken 184 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 184 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 184 times.
|
184 | return func && (num > 0) && (GetOutput() == 0.0); |
| 37 | } | ||
| 38 | |||
| 39 | 184 | bool SannikovIIntegralsRectangleMethodSTL::PreProcessingImpl() { | |
| 40 | 184 | GetOutput() = 0.0; | |
| 41 | 184 | return true; | |
| 42 | } | ||
| 43 | |||
| 44 | namespace { | ||
| 45 | |||
| 46 | 26080 | bool ComputeSlice(const std::function<double(const std::vector<double> &)> &funcx, | |
| 47 | const std::vector<std::pair<double, double>> &brd, const std::vector<double> &sz, | ||
| 48 | std::size_t outer_dim, int64_t inner_cells, int num_splits, int outer, std::vector<int> &idx, | ||
| 49 | std::vector<double> &x_vec, double &local_sum) { | ||
| 50 |
2/2✓ Branch 0 taken 12720 times.
✓ Branch 1 taken 26080 times.
|
38800 | for (std::size_t i = 0; i < outer_dim; ++i) { |
| 51 | 12720 | idx[i] = 0; | |
| 52 | } | ||
| 53 | 26080 | idx[outer_dim] = outer; | |
| 54 | 26080 | x_vec[outer_dim] = brd[outer_dim].first + ((static_cast<double>(outer) + 0.5) * sz[outer_dim]); | |
| 55 | |||
| 56 |
2/2✓ Branch 0 taken 20406000 times.
✓ Branch 1 taken 26080 times.
|
20432080 | for (int64_t cell = 0; cell < inner_cells; ++cell) { |
| 57 |
2/2✓ Branch 0 taken 45958400 times.
✓ Branch 1 taken 20406000 times.
|
66364400 | for (std::size_t i = 0; i < outer_dim; ++i) { |
| 58 | 45958400 | x_vec[i] = brd[i].first + ((static_cast<double>(idx[i]) + 0.5) * sz[i]); | |
| 59 | } | ||
| 60 | |||
| 61 | const double func_x = funcx(x_vec); | ||
| 62 |
1/2✓ Branch 0 taken 20406000 times.
✗ Branch 1 not taken.
|
20406000 | if (!std::isfinite(func_x)) { |
| 63 | return false; | ||
| 64 | } | ||
| 65 | |||
| 66 | 20406000 | local_sum += func_x; | |
| 67 | |||
| 68 |
2/2✓ Branch 0 taken 20757600 times.
✓ Branch 1 taken 26080 times.
|
20783680 | for (std::size_t position = 0; position < outer_dim; ++position) { |
| 69 |
2/2✓ Branch 0 taken 377680 times.
✓ Branch 1 taken 20379920 times.
|
20757600 | if (++idx[position] < num_splits) { |
| 70 | break; | ||
| 71 | } | ||
| 72 | 377680 | idx[position] = 0; | |
| 73 | } | ||
| 74 | } | ||
| 75 | return true; | ||
| 76 | } | ||
| 77 | |||
| 78 | 736 | void ThreadWorker(const std::function<double(const std::vector<double> &)> &funcx, | |
| 79 | const std::vector<std::pair<double, double>> &brd, const std::vector<double> &sz, std::size_t dim, | ||
| 80 | std::size_t outer_dim, int64_t inner_cells, int num_splits, int start, int end, double &partial_sum, | ||
| 81 | int &error_flag) { | ||
| 82 | 736 | std::vector<int> idx(dim, 0); | |
| 83 |
1/4✓ Branch 1 taken 736 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
736 | std::vector<double> x_vec(dim); |
| 84 | double thread_sum = 0.0; | ||
| 85 | |||
| 86 |
2/2✓ Branch 0 taken 26080 times.
✓ Branch 1 taken 736 times.
|
26816 | for (int outer = start; outer < end; ++outer) { |
| 87 | 26080 | double local_sum = 0.0; | |
| 88 |
2/4✓ Branch 1 taken 26080 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 26080 times.
|
26080 | if (!ComputeSlice(funcx, brd, sz, outer_dim, inner_cells, num_splits, outer, idx, x_vec, local_sum)) { |
| 89 | ✗ | error_flag = 1; | |
| 90 | ✗ | return; | |
| 91 | } | ||
| 92 | 26080 | thread_sum += local_sum; | |
| 93 | } | ||
| 94 | |||
| 95 |
1/2✓ Branch 0 taken 736 times.
✗ Branch 1 not taken.
|
736 | partial_sum = thread_sum; |
| 96 | } | ||
| 97 | |||
| 98 | } // namespace | ||
| 99 | |||
| 100 | 184 | bool SannikovIIntegralsRectangleMethodSTL::RunImpl() { | |
| 101 | const auto &[func, borders, num] = GetInput(); | ||
| 102 | const std::size_t dim = borders.size(); | ||
| 103 | |||
| 104 | const auto &funcx = func; | ||
| 105 | const auto &brd = borders; | ||
| 106 | 184 | const int num_splits = num; | |
| 107 | |||
| 108 | 184 | std::vector<double> sz(dim); | |
| 109 | double cell_v = 1.0; | ||
| 110 | |||
| 111 |
2/2✓ Branch 0 taken 320 times.
✓ Branch 1 taken 184 times.
|
504 | for (std::size_t i = 0; i < dim; ++i) { |
| 112 |
1/2✓ Branch 0 taken 320 times.
✗ Branch 1 not taken.
|
320 | sz[i] = (brd[i].second - brd[i].first) / static_cast<double>(num_splits); |
| 113 |
2/4✓ Branch 0 taken 320 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 320 times.
✗ Branch 3 not taken.
|
320 | if (!(sz[i] > 0.0) || !std::isfinite(sz[i])) { |
| 114 | return false; | ||
| 115 | } | ||
| 116 | 320 | cell_v *= sz[i]; | |
| 117 | } | ||
| 118 | |||
| 119 | 184 | const std::size_t outer_dim = dim - 1; | |
| 120 | |||
| 121 | int64_t inner_cells = 1; | ||
| 122 |
2/2✓ Branch 0 taken 136 times.
✓ Branch 1 taken 184 times.
|
320 | for (std::size_t i = 0; i < outer_dim; ++i) { |
| 123 | 136 | inner_cells *= num_splits; | |
| 124 | } | ||
| 125 | |||
| 126 | 184 | const int num_threads = static_cast<int>(std::thread::hardware_concurrency()); | |
| 127 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 184 times.
|
184 | const int actual_threads = std::min(num_threads > 0 ? num_threads : 4, num_splits); |
| 128 | |||
| 129 |
1/4✓ Branch 1 taken 184 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
184 | std::vector<double> partial_sums(actual_threads, 0.0); |
| 130 |
1/4✓ Branch 1 taken 184 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
184 | std::vector<int> error_flags(actual_threads, 0); |
| 131 |
1/4✓ Branch 1 taken 184 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
184 | std::vector<std::thread> threads(actual_threads); |
| 132 | |||
| 133 |
2/2✓ Branch 0 taken 736 times.
✓ Branch 1 taken 184 times.
|
920 | for (int tid = 0; tid < actual_threads; ++tid) { |
| 134 | 736 | const int chunk = num_splits / actual_threads; | |
| 135 | 736 | const int rem = num_splits % actual_threads; | |
| 136 |
2/2✓ Branch 0 taken 704 times.
✓ Branch 1 taken 32 times.
|
736 | const int start = (tid * chunk) + std::min(tid, rem); |
| 137 |
2/2✓ Branch 0 taken 704 times.
✓ Branch 1 taken 32 times.
|
736 | const int end = start + chunk + (tid < rem ? 1 : 0); |
| 138 | |||
| 139 | 736 | threads[tid] = std::thread([&funcx, &brd, &sz, dim, outer_dim, inner_cells, num_splits, start, end, | |
| 140 |
1/2✓ Branch 1 taken 736 times.
✗ Branch 2 not taken.
|
736 | &partial_sum = partial_sums[tid], &error_flag = error_flags[tid]]() { |
| 141 | 736 | ThreadWorker(funcx, brd, sz, dim, outer_dim, inner_cells, num_splits, start, end, partial_sum, error_flag); | |
| 142 |
1/2✓ Branch 1 taken 736 times.
✗ Branch 2 not taken.
|
736 | }); |
| 143 | } | ||
| 144 | |||
| 145 |
2/2✓ Branch 0 taken 736 times.
✓ Branch 1 taken 184 times.
|
920 | for (auto &thr : threads) { |
| 146 |
1/2✓ Branch 1 taken 736 times.
✗ Branch 2 not taken.
|
736 | thr.join(); |
| 147 | } | ||
| 148 | |||
| 149 |
2/2✓ Branch 0 taken 736 times.
✓ Branch 1 taken 184 times.
|
920 | for (int tid = 0; tid < actual_threads; ++tid) { |
| 150 |
1/2✓ Branch 0 taken 736 times.
✗ Branch 1 not taken.
|
736 | if (error_flags[tid] != 0) { |
| 151 | return false; | ||
| 152 | } | ||
| 153 | } | ||
| 154 | |||
| 155 | double sum = 0.0; | ||
| 156 |
2/2✓ Branch 0 taken 736 times.
✓ Branch 1 taken 184 times.
|
920 | for (int tid = 0; tid < actual_threads; ++tid) { |
| 157 | 736 | sum += partial_sums[tid]; | |
| 158 | } | ||
| 159 | |||
| 160 | 184 | GetOutput() = sum * cell_v; | |
| 161 | 184 | return std::isfinite(GetOutput()); | |
| 162 | 184 | } | |
| 163 | |||
| 164 | 184 | bool SannikovIIntegralsRectangleMethodSTL::PostProcessingImpl() { | |
| 165 | 184 | return std::isfinite(GetOutput()); | |
| 166 | } | ||
| 167 | |||
| 168 | } // namespace sannikov_i_integrals_rectangle_method | ||
| 169 |