GCC Code Coverage Report


Directory: ./
File: tasks/peterson_r_graham_scan/all/src/ops_all.cpp
Date: 2026-06-04 20:25:32
Exec Total Coverage
Lines: 62 84 73.8%
Functions: 10 14 71.4%
Branches: 28 54 51.9%

Line Branch Exec Source
1 #include "peterson_r_graham_scan/all/include/ops_all.hpp"
2
3 #include <tbb/tbb.h>
4
5 #include <atomic>
6 #include <cmath>
7 #include <cstddef>
8 #include <numbers>
9 #include <utility>
10 #include <vector>
11
12 #include "peterson_r_graham_scan/all/include/common.hpp"
13
14 namespace peterson_r_graham_scan_all {
15
16 namespace {
17 constexpr double kTolerance = 0.0;
18
19 double CalculateOrientation(const Point2D &origin, const Point2D &a, const Point2D &b) {
20 46 return ((a.coord_x - origin.coord_x) * (b.coord_y - origin.coord_y)) -
21 46 ((a.coord_y - origin.coord_y) * (b.coord_x - origin.coord_x));
22 }
23
24 double CalculateSquaredDistance(const Point2D &first, const Point2D &second) {
25 const double dx = first.coord_x - second.coord_x;
26 const double dy = first.coord_y - second.coord_y;
27 return (dx * dx) + (dy * dy);
28 }
29
30 class PointComparator {
31 public:
32 6 explicit PointComparator(const Point2D *reference) : origin_ptr_(reference) {}
33
34 28 bool operator()(const Point2D &lhs, const Point2D &rhs) const {
35
1/2
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
28 const double orientation = CalculateOrientation(*origin_ptr_, lhs, rhs);
36
1/2
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
28 if (std::abs(orientation) > kTolerance) {
37 28 return orientation > 0;
38 }
39 return CalculateSquaredDistance(*origin_ptr_, lhs) < CalculateSquaredDistance(*origin_ptr_, rhs);
40 }
41
42 private:
43 const Point2D *origin_ptr_;
44 };
45 } // namespace
46
47 6 PetersonGrahamScannerALL::PetersonGrahamScannerALL(const InputValue &in) {
48 SetTypeOfTask(GetStaticTypeOfTask());
49 6 GetInput() = in;
50 GetOutput() = 0;
51 6 }
52
53 void PetersonGrahamScannerALL::LoadPoints(const PointSet &points) {
54 input_points_ = points;
55 external_data_provided_ = true;
56 }
57
58 PointSet PetersonGrahamScannerALL::GetConvexHull() const {
59 return hull_points_;
60 }
61
62 6 bool PetersonGrahamScannerALL::ValidationImpl() {
63 6 return GetInput() >= 0;
64 }
65
66
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 bool PetersonGrahamScannerALL::PreProcessingImpl() {
67 hull_points_.clear();
68
69
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (!external_data_provided_) {
70 input_points_.clear();
71 6 const int count = GetInput();
72
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (count <= 0) {
73 return true;
74 }
75
76 6 input_points_.resize(count);
77 6 const double angle_step = 2.0 * std::numbers::pi / count;
78
79
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 6 times.
36 for (int i = 0; i < count; ++i) {
80 30 const double angle = angle_step * i;
81 30 input_points_[i] = Point2D(std::cos(angle), std::sin(angle));
82 }
83 }
84
85 return true;
86 }
87
88
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 bool PetersonGrahamScannerALL::AreAllPointsIdentical(const PointSet &points) {
89
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (points.empty()) {
90 return true;
91 }
92
93 const Point2D &reference = points[0];
94 6 std::atomic<bool> all_identical{true};
95
96 6 tbb::parallel_for(tbb::blocked_range<std::size_t>(1, points.size()),
97 30 [&points, &reference, &all_identical](const tbb::blocked_range<std::size_t> &range) {
98
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 24 times.
48 for (std::size_t i = range.begin(); i != range.end(); ++i) {
99
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
24 if (std::abs(points[i].coord_x - reference.coord_x) > kTolerance ||
100 std::abs(points[i].coord_y - reference.coord_y) > kTolerance) {
101 24 all_identical.store(false);
102 }
103 }
104 24 });
105
106 6 return all_identical.load();
107 }
108
109 6 std::size_t PetersonGrahamScannerALL::FindLowestPointParallel(const PointSet &points) {
110 struct LowestPointResult {
111 std::size_t index = 0;
112 double min_y = 0.0;
113 double min_x = 0.0;
114
115 LowestPointResult() = default;
116 6 LowestPointResult(std::size_t idx, double y, double x) : index(idx), min_y(y), min_x(x) {}
117 };
118
119 6 LowestPointResult result = tbb::parallel_reduce(
120 6 tbb::blocked_range<std::size_t>(0, points.size()), LowestPointResult(0, points[0].coord_y, points[0].coord_x),
121 6 [&points](const tbb::blocked_range<std::size_t> &range, LowestPointResult current_result) {
122
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 30 times.
60 for (std::size_t i = range.begin(); i != range.end(); ++i) {
123
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 20 times.
30 if (points[i].coord_y < current_result.min_y ||
124 (std::abs(points[i].coord_y - current_result.min_y) < kTolerance &&
125 points[i].coord_x < current_result.min_x)) {
126 10 current_result = LowestPointResult(i, points[i].coord_y, points[i].coord_x);
127 }
128 }
129 return current_result;
130 6 }, [](LowestPointResult lhs, LowestPointResult rhs) {
131 if (rhs.min_y < lhs.min_y || (std::abs(rhs.min_y - lhs.min_y) < kTolerance && rhs.min_x < lhs.min_x)) {
132 return rhs;
133 }
134 return lhs;
135 });
136
137 6 return result.index;
138 }
139
140
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 void PetersonGrahamScannerALL::SortPointsByAngleParallel(PointSet &points) {
141
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (points.size() < 2) {
142 return;
143 }
144
145 6 const Point2D origin = points[0];
146 PointComparator comparator(&origin);
147 6 tbb::parallel_sort(points.begin() + 1, points.end(), comparator);
148 }
149
150
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 bool PetersonGrahamScannerALL::RunImpl() {
151 hull_points_.clear();
152 6 const int total_points = static_cast<int>(input_points_.size());
153
154
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (total_points == 0) {
155 return true;
156 }
157
158
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
6 if (AreAllPointsIdentical(input_points_)) {
159 hull_points_.push_back(input_points_.front());
160 return true;
161 }
162
163
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (total_points < 3) {
164 hull_points_ = input_points_;
165 return true;
166 }
167
168 6 const std::size_t lowest_idx = FindLowestPointParallel(input_points_);
169 std::swap(input_points_[0], input_points_[lowest_idx]);
170
171 6 SortPointsByAngleParallel(input_points_);
172
173 6 std::vector<Point2D> stack;
174
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 stack.reserve(total_points);
175 stack.push_back(input_points_[0]);
176 stack.push_back(input_points_[1]);
177
178
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 6 times.
24 for (int i = 2; i < total_points; ++i) {
179
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 while (static_cast<int>(stack.size()) >= 2) {
180 const Point2D &second_last = stack[stack.size() - 2];
181 const Point2D &last = stack.back();
182
183
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (CalculateOrientation(second_last, last, input_points_[i]) <= kTolerance) {
184 stack.pop_back();
185 } else {
186 break;
187 }
188 }
189
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 stack.push_back(input_points_[i]);
190 }
191
192 6 hull_points_ = std::move(stack);
193 return true;
194 }
195
196 6 bool PetersonGrahamScannerALL::PostProcessingImpl() {
197 6 GetOutput() = static_cast<int>(hull_points_.size());
198 6 return true;
199 }
200
201 double PetersonGrahamScannerALL::ComputeOrientation(const Point2D &origin, const Point2D &a, const Point2D &b) {
202 return CalculateOrientation(origin, a, b);
203 }
204
205 double PetersonGrahamScannerALL::ComputeDistanceSq(const Point2D &p1, const Point2D &p2) {
206 return CalculateSquaredDistance(p1, p2);
207 }
208
209 } // namespace peterson_r_graham_scan_all
210