| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #include "galkin_d_multidim_integrals_rectangles/stl/include/ops_stl.hpp" | ||
| 2 | |||
| 3 | #include <algorithm> | ||
| 4 | #include <climits> | ||
| 5 | #include <cmath> | ||
| 6 | #include <cstddef> | ||
| 7 | #include <cstdint> | ||
| 8 | #include <limits> | ||
| 9 | #include <thread> | ||
| 10 | #include <utility> | ||
| 11 | #include <vector> | ||
| 12 | |||
| 13 | #include "galkin_d_multidim_integrals_rectangles/common/include/common.hpp" | ||
| 14 | #include "util/include/util.hpp" | ||
| 15 | |||
| 16 | namespace { | ||
| 17 | |||
| 18 | using Borders = std::vector<std::pair<double, double>>; | ||
| 19 | |||
| 20 | 184 | bool ComputeGridParams(const Borders &borders, int n, std::vector<double> &h, double &cell_v) { | |
| 21 |
2/2✓ Branch 0 taken 320 times.
✓ Branch 1 taken 184 times.
|
504 | for (std::size_t i = 0; i < borders.size(); ++i) { |
| 22 |
1/2✓ Branch 0 taken 320 times.
✗ Branch 1 not taken.
|
320 | h[i] = (borders[i].second - borders[i].first) / static_cast<double>(n); |
| 23 |
2/4✓ Branch 0 taken 320 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 320 times.
✗ Branch 3 not taken.
|
320 | if (!(h[i] > 0.0) || !std::isfinite(h[i])) { |
| 24 | return false; | ||
| 25 | } | ||
| 26 | 320 | cell_v *= h[i]; | |
| 27 | } | ||
| 28 | return true; | ||
| 29 | } | ||
| 30 | |||
| 31 | bool ComputeTotalCells(std::size_t dim, int n, std::int64_t &out) { | ||
| 32 | std::size_t total = 1; | ||
| 33 |
2/2✓ Branch 0 taken 320 times.
✓ Branch 1 taken 184 times.
|
504 | for (std::size_t i = 0; i < dim; ++i) { |
| 34 |
1/2✓ Branch 0 taken 320 times.
✗ Branch 1 not taken.
|
320 | if (total > (std::numeric_limits<std::size_t>::max() / static_cast<std::size_t>(n))) { |
| 35 | return false; | ||
| 36 | } | ||
| 37 | 320 | total *= static_cast<std::size_t>(n); | |
| 38 | } | ||
| 39 |
1/2✓ Branch 0 taken 184 times.
✗ Branch 1 not taken.
|
184 | if (total > static_cast<std::size_t>(LLONG_MAX)) { |
| 40 | return false; | ||
| 41 | } | ||
| 42 | out = static_cast<std::int64_t>(total); | ||
| 43 | return true; | ||
| 44 | } | ||
| 45 | |||
| 46 | } // namespace | ||
| 47 | |||
| 48 | namespace galkin_d_multidim_integrals_rectangles { | ||
| 49 | |||
| 50 |
1/2✓ Branch 1 taken 184 times.
✗ Branch 2 not taken.
|
184 | GalkinDMultidimIntegralsRectanglesSTL::GalkinDMultidimIntegralsRectanglesSTL(const InType &in) { |
| 51 | SetTypeOfTask(GetStaticTypeOfTask()); | ||
| 52 | GetInput() = in; | ||
| 53 | 184 | GetOutput() = 0.0; | |
| 54 | 184 | } | |
| 55 | |||
| 56 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 184 times.
|
184 | bool GalkinDMultidimIntegralsRectanglesSTL::ValidationImpl() { |
| 57 | const auto &[func, borders, n] = GetInput(); | ||
| 58 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 184 times.
|
184 | if (borders.empty()) { |
| 59 | return false; | ||
| 60 | } | ||
| 61 | |||
| 62 |
2/2✓ Branch 0 taken 320 times.
✓ Branch 1 taken 184 times.
|
504 | for (const auto &[left_border, right_border] : borders) { |
| 63 |
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)) { |
| 64 | return false; | ||
| 65 | } | ||
| 66 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 320 times.
|
320 | if (left_border >= right_border) { |
| 67 | return false; | ||
| 68 | } | ||
| 69 | } | ||
| 70 | |||
| 71 |
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 && (n > 0) && (GetOutput() == 0.0); |
| 72 | } | ||
| 73 | |||
| 74 | 184 | bool GalkinDMultidimIntegralsRectanglesSTL::PreProcessingImpl() { | |
| 75 | 184 | GetOutput() = 0.0; | |
| 76 | 184 | return true; | |
| 77 | } | ||
| 78 | |||
| 79 | 184 | bool GalkinDMultidimIntegralsRectanglesSTL::RunImpl() { | |
| 80 | const auto &[func, borders, n] = GetInput(); | ||
| 81 | 184 | const std::size_t dim = borders.size(); | |
| 82 | |||
| 83 | 184 | std::vector<double> h(dim); | |
| 84 | 184 | double cell_v = 1.0; | |
| 85 |
1/2✓ Branch 1 taken 184 times.
✗ Branch 2 not taken.
|
184 | if (!ComputeGridParams(borders, n, h, cell_v)) { |
| 86 | return false; | ||
| 87 | } | ||
| 88 | |||
| 89 | std::int64_t total_i64 = 0; | ||
| 90 | 184 | if (!ComputeTotalCells(dim, n, total_i64)) { | |
| 91 | return false; | ||
| 92 | } | ||
| 93 |
1/2✓ Branch 1 taken 184 times.
✗ Branch 2 not taken.
|
184 | const int requested = ppc::util::GetNumThreads(); |
| 94 | 184 | const int positive = (requested > 0) ? requested : 1; | |
| 95 |
1/2✓ Branch 1 taken 184 times.
✗ Branch 2 not taken.
|
184 | const int cap = (total_i64 > static_cast<std::int64_t>(std::numeric_limits<int>::max())) |
| 96 |
1/2✓ Branch 0 taken 184 times.
✗ Branch 1 not taken.
|
184 | ? std::numeric_limits<int>::max() |
| 97 | : static_cast<int>(total_i64); | ||
| 98 | const int num_threads = std::min(positive, cap); | ||
| 99 | |||
| 100 |
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(num_threads, 0.0); |
| 101 | 184 | const std::int64_t chunk = total_i64 / num_threads; | |
| 102 | 184 | const std::int64_t remainder = total_i64 % num_threads; | |
| 103 | |||
| 104 | 460 | auto worker = [&](int tid) { | |
| 105 | const std::int64_t begin = | ||
| 106 |
2/2✓ Branch 0 taken 212 times.
✓ Branch 1 taken 248 times.
|
460 | (static_cast<std::int64_t>(tid) * chunk) + std::min(static_cast<std::int64_t>(tid), remainder); |
| 107 |
2/2✓ Branch 0 taken 396 times.
✓ Branch 1 taken 64 times.
|
460 | const std::int64_t end = begin + chunk + (static_cast<std::int64_t>(tid) < remainder ? 1 : 0); |
| 108 | 460 | std::vector<double> x(dim); | |
| 109 | double local_sum = 0.0; | ||
| 110 |
2/2✓ Branch 0 taken 20406000 times.
✓ Branch 1 taken 460 times.
|
20406460 | for (std::int64_t linear_idx = begin; linear_idx < end; ++linear_idx) { |
| 111 | 20406000 | auto tmp = static_cast<std::size_t>(linear_idx); | |
| 112 |
2/2✓ Branch 0 taken 66364400 times.
✓ Branch 1 taken 20406000 times.
|
86770400 | for (std::size_t i = 0; i < dim; ++i) { |
| 113 | 66364400 | const std::size_t idx_i = tmp % static_cast<std::size_t>(n); | |
| 114 | 66364400 | tmp /= static_cast<std::size_t>(n); | |
| 115 | 66364400 | x[i] = borders[i].first + ((static_cast<double>(idx_i) + 0.5) * h[i]); | |
| 116 | } | ||
| 117 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 20406000 times.
|
40812000 | local_sum += func(x); |
| 118 | } | ||
| 119 |
1/2✓ Branch 0 taken 460 times.
✗ Branch 1 not taken.
|
460 | partial_sums[tid] = local_sum; |
| 120 | 460 | }; | |
| 121 | |||
| 122 |
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(num_threads - 1); |
| 123 |
2/2✓ Branch 0 taken 276 times.
✓ Branch 1 taken 184 times.
|
460 | for (int ti = 1; ti < num_threads; ++ti) { |
| 124 |
2/4✓ Branch 1 taken 276 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 276 times.
|
276 | threads[ti - 1] = std::thread(worker, ti); |
| 125 | } | ||
| 126 |
1/2✓ Branch 1 taken 184 times.
✗ Branch 2 not taken.
|
184 | worker(0); |
| 127 | |||
| 128 | 184 | double sum = partial_sums[0]; | |
| 129 |
2/2✓ Branch 0 taken 276 times.
✓ Branch 1 taken 184 times.
|
460 | for (int ti = 1; ti < num_threads; ++ti) { |
| 130 |
1/2✓ Branch 1 taken 276 times.
✗ Branch 2 not taken.
|
276 | threads[ti - 1].join(); |
| 131 | 276 | sum += partial_sums[ti]; | |
| 132 | } | ||
| 133 | |||
| 134 | 184 | GetOutput() = sum * cell_v; | |
| 135 | return std::isfinite(GetOutput()); | ||
| 136 | 184 | } | |
| 137 | |||
| 138 | 184 | bool GalkinDMultidimIntegralsRectanglesSTL::PostProcessingImpl() { | |
| 139 | 184 | return std::isfinite(GetOutput()); | |
| 140 | } | ||
| 141 | |||
| 142 | } // namespace galkin_d_multidim_integrals_rectangles | ||
| 143 |