HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
vector.hpp
1// Copyright Take Vos 2021-2022.
2// Distributed under the Boost Software License, Version 1.0.
3// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
4
5#pragma once
6
7#include "../rapid/numeric_array.hpp"
8
9namespace hi::inline v1 {
10
11namespace geo {
12
20template<int D>
21class vector {
22public:
23 static_assert(D == 2 || D == 3, "Only 2D or 3D vectors are supported");
24
25 constexpr vector(vector const&) noexcept = default;
26 constexpr vector(vector&&) noexcept = default;
27 constexpr vector& operator=(vector const&) noexcept = default;
28 constexpr vector& operator=(vector&&) noexcept = default;
29
32 template<int E>
33 requires(E < D) [[nodiscard]] constexpr vector(vector<E> const& other) noexcept : _v(static_cast<f32x4>(other))
34 {
35 hi_axiom(holds_invariant());
36 }
37
41 template<int E>
42 requires(E > D) [[nodiscard]] constexpr explicit vector(vector<E> const& other) noexcept : _v(static_cast<f32x4>(other))
43 {
44 for (std::size_t i = D; i != E; ++i) {
45 _v[i] = 0.0f;
46 }
47 hi_axiom(holds_invariant());
48 }
49
52 [[nodiscard]] constexpr explicit operator f32x4() const noexcept
53 {
54 return _v;
55 }
56
59 [[nodiscard]] constexpr explicit vector(f32x4 const& other) noexcept : _v(other)
60 {
61 hi_axiom(holds_invariant());
62 }
63
66 [[nodiscard]] constexpr vector() noexcept : _v(0.0f, 0.0f, 0.0f, 0.0f) {}
67
72 [[nodiscard]] constexpr vector(float x, float y) noexcept requires(D == 2) : _v(x, y, 0.0f, 0.0f) {}
73
79 [[nodiscard]] constexpr vector(float x, float y, float z = 0.0f) noexcept requires(D == 3) : _v(x, y, z, 0.0f) {}
80
84 [[nodiscard]] constexpr float& x() noexcept
85 {
86 return _v.x();
87 }
88
92 [[nodiscard]] constexpr float& y() noexcept
93 {
94 return _v.y();
95 }
96
100 [[nodiscard]] constexpr float& z() noexcept requires(D == 3)
101 {
102 return _v.z();
103 }
104
108 [[nodiscard]] constexpr float const& x() const noexcept
109 {
110 return _v.x();
111 }
112
116 [[nodiscard]] constexpr float const& y() const noexcept
117 {
118 return _v.y();
119 }
120
124 [[nodiscard]] constexpr float const& z() const noexcept requires(D == 3)
125 {
126 return _v.z();
127 }
128
132 [[nodiscard]] constexpr vector operator-() const noexcept
133 {
134 hi_axiom(holds_invariant());
135 return vector{-_v};
136 }
137
138 template<int E>
139 requires(E <= D) constexpr vector& operator+=(vector<E> const& rhs) noexcept
140 {
141 hi_axiom(holds_invariant() && rhs.holds_invariant());
142 _v = _v + static_cast<f32x4>(rhs);
143 return *this;
144 }
145
151 [[nodiscard]] constexpr friend vector operator+(vector const& lhs, vector const& rhs) noexcept
152 {
153 hi_axiom(lhs.holds_invariant() && rhs.holds_invariant());
154 return vector{lhs._v + rhs._v};
155 }
156
162 [[nodiscard]] constexpr friend vector operator-(vector const& lhs, vector const& rhs) noexcept
163 {
164 hi_axiom(lhs.holds_invariant() && rhs.holds_invariant());
165 return vector{lhs._v - rhs._v};
166 }
167
173 [[nodiscard]] constexpr friend vector operator*(vector const& lhs, float const& rhs) noexcept
174 {
175 hi_axiom(lhs.holds_invariant());
176 return vector{lhs._v * rhs};
177 }
178
184 [[nodiscard]] constexpr friend vector operator*(float const& lhs, vector const& rhs) noexcept
185 {
186 hi_axiom(rhs.holds_invariant());
187 return vector{f32x4::broadcast(lhs) * rhs._v};
188 }
189
195 [[nodiscard]] constexpr friend bool operator==(vector const& lhs, vector const& rhs) noexcept
196 {
197 hi_axiom(lhs.holds_invariant() && rhs.holds_invariant());
198 return lhs._v == rhs._v;
199 }
200
205 [[nodiscard]] constexpr friend float squared_hypot(vector const& rhs) noexcept
206 {
207 hi_axiom(rhs.holds_invariant());
208 return squared_hypot<element_mask>(rhs._v);
209 }
210
215 [[nodiscard]] constexpr friend float hypot(vector const& rhs) noexcept
216 {
217 hi_axiom(rhs.holds_invariant());
218 return hypot<element_mask>(rhs._v);
219 }
220
225 [[nodiscard]] constexpr friend float rcp_hypot(vector const& rhs) noexcept
226 {
227 hi_axiom(rhs.holds_invariant());
228 return rcp_hypot<element_mask>(rhs._v);
229 }
230
235 [[nodiscard]] constexpr friend vector normalize(vector const& rhs) noexcept
236 {
237 hi_axiom(rhs.holds_invariant());
238 return vector{normalize<element_mask>(rhs._v)};
239 }
240
246 [[nodiscard]] constexpr friend float dot(vector const& lhs, vector const& rhs) noexcept
247 {
248 hi_axiom(lhs.holds_invariant() && rhs.holds_invariant());
249 return dot<element_mask>(lhs._v, rhs._v);
250 }
251
257 [[nodiscard]] constexpr friend float det(vector const& lhs, vector const& rhs) noexcept requires (D == 2)
258 {
259 hi_axiom(lhs.holds_invariant() && rhs.holds_invariant());
260 return lhs.x() * rhs.y() - lhs.y() * rhs.x();
261 }
262
268 template<int E>
269 [[nodiscard]] friend constexpr auto min(vector const& lhs, vector<E> const& rhs) noexcept
270 {
271 return vector<std::max(D, E)>{min(static_cast<f32x4>(lhs), static_cast<f32x4>(rhs))};
272 }
273
279 template<int E>
280 [[nodiscard]] friend constexpr auto max(vector const& lhs, vector<E> const& rhs) noexcept
281 {
282 return vector<std::max(D, E)>{max(static_cast<f32x4>(lhs), static_cast<f32x4>(rhs))};
283 }
284
287 [[nodiscard]] friend constexpr vector round(vector const& rhs) noexcept
288 {
289 return vector{round(static_cast<f32x4>(rhs))};
290 }
291
294 [[nodiscard]] friend constexpr vector ceil(vector const& rhs) noexcept
295 {
296 return vector{ceil(static_cast<f32x4>(rhs))};
297 }
298
301 [[nodiscard]] friend constexpr vector floor(vector const& rhs) noexcept
302 {
303 return vector{floor(static_cast<f32x4>(rhs))};
304 }
305
309 [[nodiscard]] constexpr bool holds_invariant() const noexcept
310 {
311 return _v.w() == 0.0f && (D == 3 || _v.z() == 0.0f);
312 }
313
314 [[nodiscard]] friend std::string to_string(vector const& rhs) noexcept
315 {
316 if constexpr (D == 2) {
317 return std::format("({}, {})", rhs._v.x(), rhs._v.y());
318 } else if constexpr (D == 3) {
319 return std::format("({}, {}, {})", rhs._v.x(), rhs._v.y(), rhs._v.z());
320 } else {
321 hi_static_no_default();
322 }
323 }
324
325 friend std::ostream& operator<<(std::ostream& lhs, vector const& rhs) noexcept
326 {
327 return lhs << to_string(rhs);
328 }
329
330private:
331 f32x4 _v;
332
333 static constexpr std::size_t element_mask = (1_uz << D) - 1;
334};
335
340[[nodiscard]] constexpr vector<2> cross(vector<2> const& rhs) noexcept
341{
342 hi_axiom(rhs.holds_invariant());
343 return vector<2>{cross_2D(static_cast<f32x4>(rhs))};
344}
345
350[[nodiscard]] constexpr vector<2> normal(vector<2> const& rhs) noexcept
351{
352 hi_axiom(rhs.holds_invariant());
353 return normalize(cross(rhs));
354}
355
361[[nodiscard]] constexpr vector<3> normal(vector<3> const& rhs, float angle) noexcept
362{
363 if (angle != 0.0f) {
364 hi_not_implemented();
365 }
366 return normal(vector<2>{f32x4{rhs}.xy00()});
367}
368
377[[nodiscard]] constexpr float cross(vector<2> const& lhs, vector<2> const& rhs) noexcept
378{
379 hi_axiom(lhs.holds_invariant() && rhs.holds_invariant());
380 return cross_2D(static_cast<f32x4>(lhs), static_cast<f32x4>(rhs));
381}
382
388[[nodiscard]] constexpr vector<3> cross(vector<3> const& lhs, vector<3> const& rhs) noexcept
389{
390 hi_axiom(lhs.holds_invariant() && rhs.holds_invariant());
391 return vector<3>{cross_3D(static_cast<f32x4>(lhs), static_cast<f32x4>(rhs))};
392}
393
394} // namespace geo
395
396using vector2 = geo::vector<2>;
397using vector3 = geo::vector<3>;
398
399} // namespace hi::inline v1
400
401template<typename CharT>
402struct std::formatter<hi::geo::vector<2>, CharT> {
403 auto parse(auto& pc)
404 {
405 return pc.end();
406 }
407
408 auto format(hi::geo::vector<2> const& t, auto& fc)
409 {
410 return std::vformat_to(fc.out(), "({}, {})", std::make_format_args(t.x(), t.y()));
411 }
412};
413
414template<typename CharT>
415struct std::formatter<hi::geo::vector<3>, CharT> : std::formatter<float, CharT> {
416 auto parse(auto& pc)
417 {
418 return pc.end();
419 }
420
421 auto format(hi::geo::vector<3> const& t, auto& fc)
422 {
423 return std::vformat_to(fc.out(), "({}, {}, {})", std::make_format_args(t.x(), t.y(), t.z()));
424 }
425};
DOXYGEN BUG.
Definition algorithm.hpp:15
The HikoGUI namespace.
Definition ascii.hpp:19
A high-level geometric vector Part of the high-level vector, point, mat and color types.
Definition vector.hpp:21
constexpr vector(float x, float y) noexcept
Construct a 2D vector from x and y elements.
Definition vector.hpp:72
constexpr vector(float x, float y, float z=0.0f) noexcept
Construct a 3D vector from x, y and z elements.
Definition vector.hpp:79
constexpr friend float hypot(vector const &rhs) noexcept
Get the length of the vector.
Definition vector.hpp:215
constexpr vector(vector< E > const &other) noexcept
Construct a vector from a higher dimension vector.
Definition vector.hpp:42
friend constexpr auto min(vector const &lhs, vector< E > const &rhs) noexcept
Mix the two vectors and get the lowest value of each element.
Definition vector.hpp:269
constexpr friend bool operator==(vector const &lhs, vector const &rhs) noexcept
Compare if two vectors are equal.
Definition vector.hpp:195
constexpr bool holds_invariant() const noexcept
Check if the vector is valid.
Definition vector.hpp:309
friend constexpr vector round(vector const &rhs) noexcept
Round the elements of the vector toward nearest integer.
Definition vector.hpp:287
constexpr vector() noexcept
Construct a empty vector / zero length.
Definition vector.hpp:66
constexpr vector(f32x4 const &other) noexcept
Construct a vector from a f32x4-numeric_array.
Definition vector.hpp:59
constexpr friend vector normalize(vector const &rhs) noexcept
Normalize a vector to a unit vector.
Definition vector.hpp:235
constexpr friend vector operator*(float const &lhs, vector const &rhs) noexcept
Scale the vector by a scaler.
Definition vector.hpp:184
constexpr float & z() noexcept
Access the z element from the vector.
Definition vector.hpp:100
constexpr friend vector operator-(vector const &lhs, vector const &rhs) noexcept
Subtract two vectors from each other.
Definition vector.hpp:162
friend constexpr vector floor(vector const &rhs) noexcept
Round the elements of the vector toward downward and to the left.
Definition vector.hpp:301
constexpr vector operator-() const noexcept
Mirror this vector.
Definition vector.hpp:132
constexpr friend vector operator*(vector const &lhs, float const &rhs) noexcept
Scale the vector by a scaler.
Definition vector.hpp:173
constexpr float const & y() const noexcept
Access the y element from the vector.
Definition vector.hpp:116
constexpr friend float squared_hypot(vector const &rhs) noexcept
Get the squared length of the vector.
Definition vector.hpp:205
constexpr friend float det(vector const &lhs, vector const &rhs) noexcept
Get the determinate between two vectors.
Definition vector.hpp:257
friend constexpr vector ceil(vector const &rhs) noexcept
Round the elements of the vector toward upward and to the right.
Definition vector.hpp:294
constexpr friend float dot(vector const &lhs, vector const &rhs) noexcept
Get the dot product between two vectors.
Definition vector.hpp:246
constexpr float & y() noexcept
Access the y element from the vector.
Definition vector.hpp:92
constexpr vector(vector< E > const &other) noexcept
Construct a vector from a lower dimension vector.
Definition vector.hpp:33
constexpr friend float rcp_hypot(vector const &rhs) noexcept
Get the length of the vector.
Definition vector.hpp:225
constexpr float & x() noexcept
Access the x element from the vector.
Definition vector.hpp:84
constexpr friend vector operator+(vector const &lhs, vector const &rhs) noexcept
Add two vectors from each other.
Definition vector.hpp:151
constexpr float const & x() const noexcept
Access the x element from the vector.
Definition vector.hpp:108
constexpr float const & z() const noexcept
Access the z element from the vector.
Definition vector.hpp:124
friend constexpr auto max(vector const &lhs, vector< E > const &rhs) noexcept
Mix the two vectors and get the highest value of each element.
Definition vector.hpp:280
T max(T... args)
T to_string(T... args)