1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225 | #pragma once
#include <complex><--- Include file: not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <cmath><--- Include file: not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <iostream><--- Include file: not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <utility>
#include <type_traits><--- Include file: not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include "snippet/iterations.hpp"
#include "global/constants.hpp"
#include "internal/types.hpp"
#include "internal/exception.hpp"
#include "internal/dev_env.hpp"
#include "utility/functional.hpp"
#include "numeric/float.hpp"
#include "view/cyclic.hpp"
namespace uni {
template <class T>
struct point {
using value_type = T;
private:
value_type _x, _y;
public:
constexpr point() : point(0, 0) {}
constexpr point(const T& x, const T& y) noexcept(NO_EXCEPT) : _x(x), _y(y) {}
template<class U> constexpr point(const point<U>& p) noexcept(NO_EXCEPT) : _x(p.x()), _y(p.y()) {};<--- Struct 'point < double >' has a constructor with 1 argument that is not explicit. [+]Struct 'point < double >' has a constructor with 1 argument that is not explicit. Such, so called "Converting constructors", should in general be explicit for type safety reasons as that prevents unintended implicit conversions. <--- Struct 'point < long double >' has a constructor with 1 argument that is not explicit. [+]Struct 'point < long double >' has a constructor with 1 argument that is not explicit. Such, so called "Converting constructors", should in general be explicit for type safety reasons as that prevents unintended implicit conversions. <--- Struct 'point < std :: int32_t >' has a constructor with 1 argument that is not explicit. [+]Struct 'point < std :: int32_t >' has a constructor with 1 argument that is not explicit. Such, so called "Converting constructors", should in general be explicit for type safety reasons as that prevents unintended implicit conversions.
template<class U>
constexpr point& operator=(const point<U>& p) & noexcept(NO_EXCEPT) {
if(&p != this) this->_x = p._x, this->_y = p._y;
return *this;
};
inline constexpr auto& x() noexcept(NO_EXCEPT) { return this->_x; }<--- Shadowed declaration
inline constexpr auto& y() noexcept(NO_EXCEPT) { return this->_y; }<--- Shadowed declaration
inline constexpr const auto& x() const noexcept(NO_EXCEPT) { return this->_x; }
inline constexpr const auto& y() const noexcept(NO_EXCEPT) { return this->_y; }
constexpr auto& rotate_quarter() noexcept(NO_EXCEPT) {
const auto x = this->_x - this->_y;<--- Shadow variable
const auto y = this->_x + this->_y;<--- Shadow variable
this->_x = std::move(x), this->_y = std::move(y);
return *this;
}
constexpr auto& operator+=(const point& v) noexcept(NO_EXCEPT) { this->_x += v._x, this->_y += v._y; return *this; }
constexpr auto& operator-=(const point& v) noexcept(NO_EXCEPT) { this->_x -= v._x, this->_y -= v._y; return *this; }
constexpr auto& operator+=(const value_type& v) noexcept(NO_EXCEPT) { this->_x += v, this->_y += v; return *this; }
constexpr auto& operator-=(const value_type& v) noexcept(NO_EXCEPT) { this->_x -= v, this->_y -= v; return *this; }
constexpr auto& operator*=(const value_type& v) noexcept(NO_EXCEPT) { this->_x *= v, this->_y *= v; return *this; }
constexpr auto& operator/=(const value_type& v) noexcept(NO_EXCEPT) { this->_x /= v, this->_y /= v; return *this; }
friend inline constexpr auto operator+(const point& p) noexcept(NO_EXCEPT) { return { +p._x, +p._y }; }
friend inline constexpr auto operator-(const point& p) noexcept(NO_EXCEPT) { return { -p._x, -p._y }; }
friend inline constexpr auto operator+(point a, const point& b) noexcept(NO_EXCEPT) { return a += b; }
friend inline constexpr auto operator-(point a, const point& b) noexcept(NO_EXCEPT) { return a -= b; }
friend constexpr auto operator*(const point& a, const point& b) noexcept(NO_EXCEPT) { return a._x * b._x + a._y * b._y; }
friend inline constexpr auto operator+(point a, const value_type& b) noexcept(NO_EXCEPT) { return a += b; }
friend inline constexpr auto operator-(point a, const value_type& b) noexcept(NO_EXCEPT) { return a -= b; }
friend inline constexpr auto operator*(point a, const value_type& b) noexcept(NO_EXCEPT) { return a *= b; }
friend inline constexpr auto operator/(point a, const value_type& b) noexcept(NO_EXCEPT) { return a /= b; }
friend inline constexpr auto operator+(const value_type& a, point b) noexcept(NO_EXCEPT) { return b += a; }
friend inline constexpr auto operator-(const value_type& a, point b) noexcept(NO_EXCEPT) { return b += a; }
friend inline constexpr auto operator*(const value_type& a, point b) noexcept(NO_EXCEPT) { return b *= a; }
friend inline constexpr auto operator/(const value_type& a, point b) noexcept(NO_EXCEPT) { return b /= a; }
friend inline constexpr bool operator==(const point& a, const point& b) noexcept(NO_EXCEPT) { return compare(a._x, b._x) == 0 and compare(a._y, b._y) == 0; }
friend inline constexpr bool operator!=(const point& a, const point& b) noexcept(NO_EXCEPT) { return !(a == b); }
friend inline constexpr bool operator<(const point& a, const point& b) noexcept(NO_EXCEPT) { return compare(a._x, b._x) != 0 ? compare(a._x, b._x) < 0 : compare(a._y, b._y) < 0; }
friend inline constexpr bool operator>(const point& a, const point& b) noexcept(NO_EXCEPT) { return compare(a._x, b._x) != 0 ? compare(a._x, b._x) > 0 : compare(a._y, b._y) > 0; }
friend inline constexpr bool operator<=(const point& a, const point& b) noexcept(NO_EXCEPT) { return !(a > b); }
friend inline constexpr bool operator>=(const point& a, const point& b) noexcept(NO_EXCEPT) { return !(a < b); }
auto _debug() const { return std::make_pair(this->_x, this->_y); }
};
template<size_t I, class T>
inline const auto& get(const point<T>& p) noexcept(NO_EXCEPT) {
if constexpr(I == 0) { return p.x(); }
else if constexpr(I == 1) { return p.y(); }
else static_assert(uni::internal::EXCEPTION_ON_VALUE<I>);
}
template<size_t I, class T>
inline auto& get(point<T>& p) noexcept(NO_EXCEPT) {
if constexpr(I == 0) return p.x();
else if constexpr(I == 1) return p.y();
else static_assert(internal::EXCEPTION_ON_VALUE<I>);
}
} // namespace uni
namespace std {
template<class T>
struct tuple_size<uni::point<T>> : integral_constant<size_t,2> {};
template<size_t I, class T>
struct tuple_element<I,uni::point<T>> {
using type = typename uni::point<T>::value_type;
};
template<class T>
constexpr auto norm(const uni::point<T>& v) noexcept(NO_EXCEPT) { return v.x() * v.x() + v.y() * v.y(); }
template<class T>
constexpr auto abs(const uni::point<T>& v) noexcept(NO_EXCEPT) {
if constexpr(is_floating_point_v<T>) {
return static_cast<T>(std::abs(std::complex<T>(v.x(), v.y())));
}
else {
return static_cast<T>(sqrt(norm(v)));
}
}
template<class T>
constexpr auto arg(const uni::point<T>& v) noexcept(NO_EXCEPT) {
return static_cast<T>(std::arg(std::complex<T>(v.x(), v.y())));
}
template<class T, class C, class S>
auto& operator>>(basic_istream<C, S>& in, uni::point<T>& v) noexcept(NO_EXCEPT) {
T x, y; in >> x >> y;
v = { x, y };
return in;
}
template<class T, class C, class S>
auto& operator<<(basic_ostream<C, S>& out, const uni::point<T>& v) noexcept(NO_EXCEPT) {
out << v.x() << " " << v.y();
return out;
}
} // namespace std
namespace uni {
template<class T>
constexpr auto distance(const point<T>& a, const point<T>& b) noexcept(NO_EXCEPT) {
return std::abs(a - b);
}
template<class T>
constexpr auto squared_distance(const point<T>& a, const point<T>& b) noexcept(NO_EXCEPT) {
return std::norm(a - b);
}
template<class T>
constexpr auto manhattan_distance(const point<T>& a, const point<T>& b) noexcept(NO_EXCEPT) {
return std::abs(a.x() - b.x()) + std::abs(a.y() - b.y());
}
template<class T>
constexpr auto chebyshev_distance(const point<T>& a, const point<T>& b) noexcept(NO_EXCEPT) {
return std::max(std::abs(a.x() - b.x()), std::abs(a.y() - b.y()));
}
template<class T>
constexpr auto dot(point<T> a, point<T> b, const point<T>& o = point<T>()) noexcept(NO_EXCEPT) {
a -= o, b -= o;
return a * b;
}
template<class T>
constexpr auto cross(point<T> a, point<T> b, const point<T>& o = point<T>()) noexcept(NO_EXCEPT) {
a -= o, b -= o;
return a.x() * b.y() - a.y() * b.x();
}
template<class T, class Angle = T>
constexpr point<T> rotate(const point<T>& p, const Angle angle) noexcept(NO_EXCEPT) {
return {
std::cos(angle) * p.x() - std::sin(angle) * p.y(),
std::sin(angle) * p.x() + std::cos(angle) * p.y()
};
}
template<class T, class Angle = T>
constexpr auto rotate(const point<T>& p, const point<T>& q, const Angle angle) noexcept(NO_EXCEPT) {
return rotate(p - q, angle) + q;
}
template<class T>
inline constexpr auto relation(const point<T>& p, const point<T>& q) noexcept(NO_EXCEPT) { return relation<T>({ 0, 0 }, p, q); }
template<class T>
auto to_degree(const T& radian) { return radian * 180 / PI<T>; }
template<class T>
auto to_radian(const T& degree) { return degree * PI<T> / 180; }
} // namespace uni
|