GCC Code Coverage Report


Directory: ./
File: tasks/nikitin_a_monte_carlo/tbb/src/ops_tbb.cpp
Date: 2026-05-11 08:26:31
Exec Total Coverage
Lines: 47 47 100.0%
Functions: 8 8 100.0%
Branches: 27 42 64.3%

Line Branch Exec Source
1 #include "nikitin_a_monte_carlo/tbb/include/ops_tbb.hpp"
2
3 #include <oneapi/tbb.h> // Современный include для oneTBB
4 // Альтернатива: #include <tbb/tbb.h> для старой версии
5
6 #include <array>
7 #include <cmath>
8 #include <cstddef>
9 #include <vector>
10
11 #include "nikitin_a_monte_carlo/common/include/common.hpp"
12
13 namespace nikitin_a_monte_carlo {
14
15 namespace {
16 // Вспомогательная функция для вычисления значения тестовой функции
17
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2004400 times.
2004400 double EvaluateFunction(const std::vector<double> &point, FunctionType type) {
18
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2004400 times.
2004400 if (point.empty()) {
19 return 0.0;
20 }
21
22
5/6
✗ Branch 0 not taken.
✓ Branch 1 taken 600000 times.
✓ Branch 2 taken 200000 times.
✓ Branch 3 taken 120000 times.
✓ Branch 4 taken 80000 times.
✓ Branch 5 taken 1004400 times.
2004400 switch (type) {
23 case FunctionType::kConstant:
24 return 1.0;
25 case FunctionType::kLinear:
26 600000 return point.at(0);
27 case FunctionType::kProduct:
28
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 200000 times.
200000 if (point.size() < 2) {
29 return 0.0;
30 }
31 200000 return point.at(0) * point.at(1);
32 case FunctionType::kQuadratic:
33
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 120000 times.
120000 if (point.size() < 2) {
34 return 0.0;
35 }
36 120000 return (point.at(0) * point.at(0)) + (point.at(1) * point.at(1));
37 case FunctionType::kExponential:
38 80000 return std::exp(point.at(0));
39 default:
40 return 0.0;
41 }
42 }
43
44 // Генерация квазислучайной последовательности Кронекера
45 4448800 double KroneckerSequence(int index, int dimension) {
46 4448800 const std::array<double, 10> primes = {2.0, 3.0, 5.0, 7.0, 11.0, 13.0, 17.0, 19.0, 23.0, 29.0};
47
1/2
✓ Branch 0 taken 4448800 times.
✗ Branch 1 not taken.
4448800 double alpha = std::sqrt(primes.at(static_cast<std::size_t>(dimension % 10)));
48 4448800 alpha = alpha - std::floor(alpha);
49 4448800 return std::fmod(index * alpha, 1.0);
50 }
51 } // namespace
52
53
1/2
✓ Branch 1 taken 88 times.
✗ Branch 2 not taken.
88 NikitinAMonteCarloTBB::NikitinAMonteCarloTBB(const InType &in) {
54 SetTypeOfTask(GetStaticTypeOfTask());
55 GetInput() = in;
56 88 GetOutput() = 0.0;
57 88 }
58
59
1/2
✓ Branch 0 taken 88 times.
✗ Branch 1 not taken.
88 bool NikitinAMonteCarloTBB::ValidationImpl() {
60 const auto &[lower_bounds, upper_bounds, num_points, func_type] = GetInput();
61
62
2/4
✓ Branch 0 taken 88 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 88 times.
88 if (lower_bounds.empty() || upper_bounds.empty()) {
63 return false;
64 }
65
66
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 88 times.
88 if (lower_bounds.size() != upper_bounds.size()) {
67 return false;
68 }
69
70
2/2
✓ Branch 0 taken 156 times.
✓ Branch 1 taken 88 times.
244 for (std::size_t i = 0; i < lower_bounds.size(); ++i) {
71
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 156 times.
156 if (lower_bounds[i] >= upper_bounds[i]) {
72 return false;
73 }
74 }
75
76 88 return num_points > 0;
77 }
78
79 88 bool NikitinAMonteCarloTBB::PreProcessingImpl() {
80 88 return true;
81 }
82
83 88 bool NikitinAMonteCarloTBB::RunImpl() {
84 // Получаем входные данные и распаковываем их в обычные переменные
85 const auto input = GetInput();
86 const auto &lower_bounds = std::get<0>(input);
87 const auto &upper_bounds = std::get<1>(input);
88 88 const int num_points = std::get<2>(input);
89 88 const FunctionType func_type = std::get<3>(input);
90
91 88 std::size_t dim = lower_bounds.size();
92
93 // Вычисление объема области интегрирования
94 double volume = 1.0;
95
2/2
✓ Branch 0 taken 156 times.
✓ Branch 1 taken 88 times.
244 for (std::size_t i = 0; i < dim; ++i) {
96 156 volume *= (upper_bounds[i] - lower_bounds[i]);
97 }
98
99 88 double sum = tbb::parallel_reduce(tbb::blocked_range<int>(0, num_points),
100 176 0.0, // Начальное значение редукции
101
102 // Лямбда для вычисления суммы в каждом поддиапазоне
103
1/2
✓ Branch 1 taken 88 times.
✗ Branch 2 not taken.
88 [&](const tbb::blocked_range<int> &range, double local_sum) -> double {
104 // Локальный буфер для точки (может быть оптимизирован через TLS)
105 26743 std::vector<double> point(dim);
106
107
2/2
✓ Branch 0 taken 2004400 times.
✓ Branch 1 taken 26743 times.
2031143 for (int i = range.begin(); i != range.end(); ++i) {
108 // Заполняем точку для текущего i
109
2/2
✓ Branch 0 taken 4448800 times.
✓ Branch 1 taken 2004400 times.
6453200 for (std::size_t j = 0; j < dim; ++j) {
110
1/2
✓ Branch 1 taken 4448800 times.
✗ Branch 2 not taken.
4448800 double u = KroneckerSequence(i, static_cast<int>(j));
111 4448800 point[j] = lower_bounds[j] + (u * (upper_bounds[j] - lower_bounds[j]));
112 }
113
1/2
✓ Branch 1 taken 2004400 times.
✗ Branch 2 not taken.
2004400 local_sum += EvaluateFunction(point, func_type);
114 }
115 26743 return local_sum;
116 },
117
118 // Функция объединения результатов от разных потоков
119 723 [](double x, double y) -> double { return x + y; });
120
121 88 double result = volume * sum / static_cast<double>(num_points);
122 88 GetOutput() = result;
123
124 88 return true;
125 }
126
127 88 bool NikitinAMonteCarloTBB::PostProcessingImpl() {
128 88 return true;
129 }
130
131 } // namespace nikitin_a_monte_carlo
132