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
Expand Up @@ -5,7 +5,7 @@

#include "task/include/task.hpp"

namespace orehov_n_jarvis_pass_seq {
namespace orehov_n_jarvis_pass {

struct Point {
double x;
Expand All @@ -27,4 +27,4 @@ using OutType = std::vector<Point>;
using TestType = int;
using BaseTask = ppc::task::Task<InType, OutType>;

} // namespace orehov_n_jarvis_pass_seq
} // namespace orehov_n_jarvis_pass
31 changes: 31 additions & 0 deletions tasks/orehov_n_jarvis_pass/omp/include/ops_omp.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#pragma once

#include <cstddef>
#include <vector>

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

namespace orehov_n_jarvis_pass {

class OrehovNJarvisPassOMP : public ppc::task::Task<std::vector<Point>, std::vector<Point>> {
public:
static constexpr ppc::task::TypeOfTask GetStaticTypeOfTask() {
return ppc::task::TypeOfTask::kOMP;
}
explicit OrehovNJarvisPassOMP(const std::vector<Point> &in);

private:
static double CheckLeft(Point a, Point b, Point c);
static double DistanceSquared(Point a, Point b);

Point FindFirstElem(const std::vector<Point> &input) const;
Point FindNext(Point current, const std::vector<Point> &input) const;

bool ValidationImpl() override;
bool PreProcessingImpl() override;
bool RunImpl() override;
bool PostProcessingImpl() override;
};

} // namespace orehov_n_jarvis_pass
123 changes: 123 additions & 0 deletions tasks/orehov_n_jarvis_pass/omp/src/ops_omp.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
#include "orehov_n_jarvis_pass/omp/include/ops_omp.hpp"

#include <omp.h>

#include <cmath>
#include <cstddef>
#include <vector>

#include "orehov_n_jarvis_pass/common/include/common.hpp"

namespace orehov_n_jarvis_pass {

OrehovNJarvisPassOMP::OrehovNJarvisPassOMP(const InType &in) {
SetTypeOfTask(GetStaticTypeOfTask());
GetInput() = in;
GetOutput() = std::vector<Point>();
}

bool OrehovNJarvisPassOMP::ValidationImpl() {
return !GetInput().empty();
}

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

bool OrehovNJarvisPassOMP::RunImpl() {
const auto &input = GetInput();

if (input.size() == 1 || input.size() == 2) {
GetOutput() = input;
return true;
}

Point current = FindFirstElem(input);
GetOutput().push_back(current);

while (true) {
Point next = FindNext(current, input);
if (next == GetOutput()[0]) {
break;
}

current = next;
GetOutput().push_back(next);
}

return true;
}

Point OrehovNJarvisPassOMP::FindNext(Point current, const std::vector<Point> &input) const {
const size_t n = input.size();
Point initial_candidate = (current == input[0]) ? input[1] : input[0];

int max_threads = omp_get_max_threads();
std::vector<Point> local_bests(max_threads, initial_candidate);
const int n_int = static_cast<int>(n);

#pragma omp parallel default(none) shared(input, n_int, current, local_bests)
{
int tid = omp_get_thread_num();
Point thread_local_best = local_bests[tid];

#pragma omp for nowait
for (int i = 0; i < n_int; ++i) {
const Point &point = input[i];
if (current == point) {
continue;
}

double orient = CheckLeft(current, thread_local_best, point);

if (orient > 0) {
thread_local_best = point;
} else if (std::abs(orient) < 1e-9) {
if (DistanceSquared(current, point) > DistanceSquared(current, thread_local_best)) {
thread_local_best = point;
}
}
}
local_bests[tid] = thread_local_best;
}

Point global_next = local_bests[0];
for (int i = 1; i < max_threads; ++i) {
double orient = CheckLeft(current, global_next, local_bests[i]);
if (orient > 0) {
global_next = local_bests[i];
} else if (std::abs(orient) < 1e-9) {
if (DistanceSquared(current, local_bests[i]) > DistanceSquared(current, global_next)) {
global_next = local_bests[i];
}
}
}

return global_next;
}

double OrehovNJarvisPassOMP::CheckLeft(Point a, Point b, Point c) {
return ((b.x - a.x) * (c.y - a.y)) - ((b.y - a.y) * (c.x - a.x));
}

Point OrehovNJarvisPassOMP::FindFirstElem(const std::vector<Point> &input) const {
Point current = input[0];
for (const auto &f : input) {
if (f.x < current.x || (f.y < current.y && f.x == current.x)) {
current = f;
}
}
return current;
}

double OrehovNJarvisPassOMP::DistanceSquared(Point a, Point b) {
double dx = a.x - b.x;
double dy = a.y - b.y;
return dx * dx + dy * dy;
}

bool OrehovNJarvisPassOMP::PostProcessingImpl() {
return true;
}

} // namespace orehov_n_jarvis_pass
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@

#include <vector>

#include "orehov_n_jarvis_pass_seq/common/include/common.hpp"
#include "orehov_n_jarvis_pass/common/include/common.hpp"
#include "task/include/task.hpp"

namespace orehov_n_jarvis_pass_seq {
namespace orehov_n_jarvis_pass {

class OrehovNJarvisPassSEQ : public BaseTask {
public:
Expand All @@ -29,4 +29,4 @@ class OrehovNJarvisPassSEQ : public BaseTask {
std::vector<Point> input_;
};

} // namespace orehov_n_jarvis_pass_seq
} // namespace orehov_n_jarvis_pass
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
#include "orehov_n_jarvis_pass_seq/seq/include/ops_seq.hpp"
#include "orehov_n_jarvis_pass/seq/include/ops_seq.hpp"

#include <cmath>
#include <set>
#include <vector>

#include "orehov_n_jarvis_pass_seq/common/include/common.hpp"
#include "orehov_n_jarvis_pass/common/include/common.hpp"

namespace orehov_n_jarvis_pass_seq {
namespace orehov_n_jarvis_pass {

OrehovNJarvisPassSEQ::OrehovNJarvisPassSEQ(const InType &in) {
SetTypeOfTask(GetStaticTypeOfTask());
Expand Down Expand Up @@ -88,4 +88,4 @@ bool OrehovNJarvisPassSEQ::PostProcessingImpl() {
return true;
}

} // namespace orehov_n_jarvis_pass_seq
} // namespace orehov_n_jarvis_pass
32 changes: 32 additions & 0 deletions tasks/orehov_n_jarvis_pass/tbb/include/ops_tbb.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#pragma once

#include <vector>

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

namespace orehov_n_jarvis_pass {

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

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

[[nodiscard]] static double CheckLeft(Point a, Point b, Point c);
[[nodiscard]] Point FindFirstElem() const;
[[nodiscard]] static double Distance(Point a, Point b);
[[nodiscard]] Point FindNext(Point current) const;

std::vector<Point> res_;
std::vector<Point> input_;
};

} // namespace orehov_n_jarvis_pass
126 changes: 126 additions & 0 deletions tasks/orehov_n_jarvis_pass/tbb/src/ops_tbb.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
#include "orehov_n_jarvis_pass/tbb/include/ops_tbb.hpp"

#include <cmath>
#include <cstddef>
#include <set>
#include <vector>

#include "oneapi/tbb.h"
#include "orehov_n_jarvis_pass/common/include/common.hpp"

namespace orehov_n_jarvis_pass {

OrehovNJarvisPassTBB::OrehovNJarvisPassTBB(const InType &in) {
SetTypeOfTask(GetStaticTypeOfTask());
GetInput() = in;
GetOutput() = std::vector<Point>();
}

bool OrehovNJarvisPassTBB::ValidationImpl() {
return (!GetInput().empty());
}

bool OrehovNJarvisPassTBB::PreProcessingImpl() {
std::set<Point> tmp(GetInput().begin(), GetInput().end());
input_.assign(tmp.begin(), tmp.end());
return true;
}

bool OrehovNJarvisPassTBB::RunImpl() {
if (input_.size() == 1 || input_.size() == 2) {
res_ = input_;
return true;
}

Point current = FindFirstElem();
res_.push_back(current);

while (true) {
Point next = FindNext(current);
if (next == res_[0]) {
break;
}

current = next;
res_.push_back(next);
}

return true;
}

Point OrehovNJarvisPassTBB::FindNext(Point current) const {
const size_t n = input_.size();
const auto &input = input_;

struct Body {
const Point &current;
const std::vector<Point> &input;
Point best_point;

Body(const Point &c, const std::vector<Point> &in)
: current(c), input(in), best_point((current == in[0]) ? in[1] : in[0]) {}

Body(Body &other, tbb::split) : current(other.current), input(other.input), best_point(other.best_point) {}

void operator()(const tbb::blocked_range<size_t> &range) {
for (size_t i = range.begin(); i != range.end(); ++i) {
const Point &point = input[i];
if (current == point) {
continue;
}

double orient = OrehovNJarvisPassTBB::CheckLeft(current, best_point, point);

if (orient > 0) {
best_point = point;
} else if (orient == 0) {
if (OrehovNJarvisPassTBB::Distance(current, point) > OrehovNJarvisPassTBB::Distance(current, best_point)) {
best_point = point;
}
}
}
}

void join(const Body &other) {
double global_orient = OrehovNJarvisPassTBB::CheckLeft(current, best_point, other.best_point);
if (global_orient > 0) {
best_point = other.best_point;
} else if (global_orient == 0) {
if (OrehovNJarvisPassTBB::Distance(current, other.best_point) >
OrehovNJarvisPassTBB::Distance(current, best_point)) {
best_point = other.best_point;
}
}
}
};

Body body(current, input);
tbb::parallel_reduce(tbb::blocked_range<size_t>(0, n), body);

return body.best_point;
}

double OrehovNJarvisPassTBB::CheckLeft(Point a, Point b, Point c) {
return ((b.x - a.x) * (c.y - a.y)) - ((b.y - a.y) * (c.x - a.x));
}

Point OrehovNJarvisPassTBB::FindFirstElem() const {
Point current = input_[0];
for (auto f : input_) {
if (f.x < current.x || (f.y < current.y && f.x == current.x)) {
current = f;
}
}
return current;
}

double OrehovNJarvisPassTBB::Distance(Point a, Point b) {
return std::sqrt(std::pow(a.y - b.y, 2) + std::pow(a.x - b.x, 2));
}

bool OrehovNJarvisPassTBB::PostProcessingImpl() {
GetOutput() = res_;
return true;
}

} // namespace orehov_n_jarvis_pass
Loading
Loading