Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#pragma once

#include "task/include/task.hpp"
#include "vinyaikina_e_multidimensional_integrals_simpson_method/common/include/common.hpp"

namespace vinyaikina_e_multidimensional_integrals_simpson_method {

class VinyaikinaEMultidimIntegrSimpsonSTL : public BaseTask {
public:
static constexpr ppc::task::TypeOfTask GetStaticTypeOfTask() {
return ppc::task::TypeOfTask::kSTL;
}
explicit VinyaikinaEMultidimIntegrSimpsonSTL(const InType &in);

private:
bool ValidationImpl() override;
bool PreProcessingImpl() override;
bool RunImpl() override;
bool PostProcessingImpl() override;

double I_res_{0.0};
};

} // namespace vinyaikina_e_multidimensional_integrals_simpson_method
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
#include "vinyaikina_e_multidimensional_integrals_simpson_method/stl/include/ops_stl.hpp"

#include <cmath>
#include <cstdlib>
#include <cstring>
#include <functional>
#include <numeric>
#include <stack>
#include <thread>
#include <utility>
#include <vector>

#include "util/include/util.hpp"
#include "vinyaikina_e_multidimensional_integrals_simpson_method/common/include/common.hpp"

namespace vinyaikina_e_multidimensional_integrals_simpson_method {
namespace {

double CustomRound(double value, double h) {
h *= 2;
int tmp = static_cast<int>(1 / h);
int decimal_places = 0;
while (tmp > 0 && tmp % 10 == 0) {
decimal_places++;
tmp /= 10;
}

double factor = std::pow(10.0, decimal_places);
return std::round(value * factor) / factor;
}

double Weight(int i, int steps_count) {
double weight = 2.0;
if (i == 0 || i == steps_count) {
weight = 1.0;
} else if (i % 2 != 0) {
weight = 4.0;
}
return weight;
}

double OuntNtIntegral(double left_border, double right_border, double simpson_factor,
const std::vector<std::pair<double, double>> &limits, const std::vector<double> &actual_step,
const std::function<double(const std::vector<double> &)> &function) {
std::stack<std::pair<std::vector<double>, double>> stack;
double res = 0.0;

int steps_count_0 = static_cast<int>(lround((right_border - left_border) / actual_step[0]));

for (int i0 = 0; i0 <= steps_count_0; ++i0) {
double x0 = left_border + (i0 * actual_step[0]);

double weight_0 = Weight(i0, steps_count_0);
stack.emplace(std::vector<double>{x0}, weight_0);

while (!stack.empty()) {
std::vector<double> point = stack.top().first;
double weight = stack.top().second;
stack.pop();

if (point.size() == limits.size()) {
res += function(point) * weight * simpson_factor;
continue;
}

size_t dim = point.size();
double step = actual_step[dim];

int steps_count = static_cast<int>(lround((limits[dim].second - limits[dim].first) / step));

for (int i = 0; i <= steps_count; ++i) {
double x = limits[dim].first + (i * step);

double dim_weight = Weight(i, steps_count);

point.push_back(x);
stack.emplace(point, weight * dim_weight);
point.pop_back();
}
}
}

return res;
}
}; // namespace

VinyaikinaEMultidimIntegrSimpsonSTL::VinyaikinaEMultidimIntegrSimpsonSTL(const InType &in) {
SetTypeOfTask(GetStaticTypeOfTask());
GetInput() = in;
}

bool VinyaikinaEMultidimIntegrSimpsonSTL::PreProcessingImpl() {
return true;
}

bool VinyaikinaEMultidimIntegrSimpsonSTL::ValidationImpl() {
const auto &[h, limits, function] = GetInput();
return !limits.empty() && function && h <= 0.01;
}

bool VinyaikinaEMultidimIntegrSimpsonSTL::RunImpl() {
const auto &input = GetInput();
double h = std::get<0>(input);
const auto &limits = std::get<1>(input);
const auto &function = std::get<2>(input);

const int num_threads = ppc::util::GetNumThreads();

double delta = (limits[0].second - limits[0].first) / num_threads;

std::vector<double> actual_step(limits.size());
double simpson_factor = 1.0;

for (size_t i = 0; i < limits.size(); i++) {
int quan_steps = static_cast<int>(lround((limits[i].second - limits[i].first) / h));
if (quan_steps % 2 != 0) {
quan_steps++;
}
actual_step[i] = (limits[i].second - limits[i].first) / quan_steps;
simpson_factor *= actual_step[i] / 3.0;
}

std::vector<double> results(num_threads, 0.0);
std::vector<std::thread> threads;
threads.reserve(num_threads);

for (int i = 0; i < num_threads; ++i) {
threads.emplace_back([i, num_threads, delta, &limits, &actual_step, &function, simpson_factor, &results]() {
double left = limits[0].first;
double right = limits[0].second;

if (i != 0) {
left = CustomRound(limits[0].first + (delta * i), actual_step[0]);
}
if (i != num_threads - 1) {
right = CustomRound(limits[0].second - (delta * (num_threads - i - 1)), actual_step[0]);
}

results[i] = OuntNtIntegral(left, right, simpson_factor, limits, actual_step, function);
});
}

for (auto &t : threads) {
t.join();
}

I_res_ = std::accumulate(results.begin(), results.end(), 0.0);

return true;
}

bool VinyaikinaEMultidimIntegrSimpsonSTL::PostProcessingImpl() {
GetOutput() = I_res_;
return true;
}
} // namespace vinyaikina_e_multidimensional_integrals_simpson_method
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "vinyaikina_e_multidimensional_integrals_simpson_method/common/include/common.hpp"
#include "vinyaikina_e_multidimensional_integrals_simpson_method/omp/include/ops_omp.hpp"
#include "vinyaikina_e_multidimensional_integrals_simpson_method/seq/include/ops_seq.hpp"
#include "vinyaikina_e_multidimensional_integrals_simpson_method/stl/include/ops_stl.hpp"
#include "vinyaikina_e_multidimensional_integrals_simpson_method/tbb/include/ops_tbb.hpp"

namespace vinyaikina_e_multidimensional_integrals_simpson_method {
Expand Down Expand Up @@ -159,22 +160,23 @@ const std::array<TestType, 16> kTests = {{

TestType{"x2_y2d_0_1_x_0_1", InType{0.005, {{0.0, 1.0}, {0.0, 1.0}}, x2_y2d}, Intx2y2d(0.0, 1.0, 0.0, 1.0)},

TestType{"xyz_3d_0_1_x3", InType{0.005, {{0.0, 0.25}, {0.0, 0.25}, {0.0, 0.25}}, xyz_3d},
Intxyz3d(0.0, 0.25, 0.0, 0.25, 0.0, 0.25)},
TestType{"xyz_3d_0_1_x3", InType{0.005, {{0.0, 0.20}, {0.0, 0.20}, {0.0, 0.20}}, xyz_3d},
Intxyz3d(0.0, 0.20, 0.0, 0.20, 0.0, 0.20)},

TestType{"x2_y2_z2_3d_0_1_x3", InType{0.01, {{0.0, 0.25}, {0.0, 0.25}, {0.0, 0.25}}, x2_y2_z2_3d},
Intx2Y2Z23d(0.0, 0.25, 0.0, 0.25, 0.0, 0.25)},
TestType{"x2_y2_z2_3d_0_1_x3", InType{0.01, {{0.0, 0.20}, {0.0, 0.20}, {0.0, 0.20}}, x2_y2_z2_3d},
Intx2Y2Z23d(0.0, 0.20, 0.0, 0.20, 0.0, 0.20)},

TestType{"exp_sum_3d_0_05_x3", InType{0.005, {{0.0, 0.25}, {0.0, 0.25}, {0.0, 0.25}}, exp_sum_3d},
IntexpSum3d(0.0, 0.25, 0.0, 0.25, 0.0, 0.25)},
TestType{"exp_sum_3d_0_05_x3", InType{0.005, {{0.0, 0.20}, {0.0, 0.20}, {0.0, 0.20}}, exp_sum_3d},
IntexpSum3d(0.0, 0.20, 0.0, 0.20, 0.0, 0.20)},
}};

const auto kTaskName = PPC_SETTINGS_vinyaikina_e_multidimensional_integrals_simpson_method;

const auto kTestTasksList =
std::tuple_cat(ppc::util::AddFuncTask<VinyaikinaEMultidimIntegrSimpsonSEQ, InType>(kTests, kTaskName),
ppc::util::AddFuncTask<VinyaikinaEMultidimIntegrSimpsonOMP, InType>(kTests, kTaskName),
ppc::util::AddFuncTask<VinyaikinaEMultidimIntegrSimpsonTBB, InType>(kTests, kTaskName));
ppc::util::AddFuncTask<VinyaikinaEMultidimIntegrSimpsonTBB, InType>(kTests, kTaskName),
ppc::util::AddFuncTask<VinyaikinaEMultidimIntegrSimpsonSTL, InType>(kTests, kTaskName));

const auto kGtestValues = ppc::util::ExpandToValues(kTestTasksList);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "vinyaikina_e_multidimensional_integrals_simpson_method/common/include/common.hpp"
#include "vinyaikina_e_multidimensional_integrals_simpson_method/omp/include/ops_omp.hpp"
#include "vinyaikina_e_multidimensional_integrals_simpson_method/seq/include/ops_seq.hpp"
#include "vinyaikina_e_multidimensional_integrals_simpson_method/stl/include/ops_stl.hpp"
#include "vinyaikina_e_multidimensional_integrals_simpson_method/tbb/include/ops_tbb.hpp"

namespace vinyaikina_e_multidimensional_integrals_simpson_method {
Expand Down Expand Up @@ -44,7 +45,8 @@ const auto kPerfTaskName = PPC_SETTINGS_vinyaikina_e_multidimensional_integrals_

const auto kAllPerfTasks =
ppc::util::MakeAllPerfTasks<InType, VinyaikinaEMultidimIntegrSimpsonSEQ, VinyaikinaEMultidimIntegrSimpsonOMP,
VinyaikinaEMultidimIntegrSimpsonTBB>(kPerfTaskName);
VinyaikinaEMultidimIntegrSimpsonTBB, VinyaikinaEMultidimIntegrSimpsonSTL>(
kPerfTaskName);

const auto kGtestValues = ppc::util::TupleToGTestValues(kAllPerfTasks);

Expand Down
Loading