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 "../SIMD/module.hpp"
8
9namespace hi::inline v1 {
10
11namespace geo {
12
20template<typename T, int D>
21class vector {
22public:
23 using value_type = T;
24 using array_type = simd<value_type, 4>;
25
26 static_assert(D == 2 || D == 3, "Only 2D or 3D vectors are supported");
27
28 constexpr vector(vector const&) noexcept = default;
29 constexpr vector(vector&&) noexcept = default;
30 constexpr vector& operator=(vector const&) noexcept = default;
31 constexpr vector& operator=(vector&&) noexcept = default;
32
35 template<int E>
36 requires(E < D)
37 [[nodiscard]] constexpr vector(vector<value_type, E> const& other) noexcept : _v(static_cast<array_type>(other))
38 {
39 hi_axiom(holds_invariant());
40 }
41
45 template<int E>
46 requires(E > D)
47 [[nodiscard]] constexpr explicit vector(vector<value_type, E> const& other) noexcept : _v(static_cast<array_type>(other))
48 {
49 for (std::size_t i = D; i != E; ++i) {
50 _v[i] = value_type{0};
51 }
52 hi_axiom(holds_invariant());
53 }
54
57 [[nodiscard]] constexpr explicit operator array_type() const noexcept
58 {
59 return _v;
60 }
61
64 [[nodiscard]] constexpr explicit vector(array_type const& other) noexcept : _v(other)
65 {
66 hi_axiom(holds_invariant());
67 }
68
71 [[nodiscard]] constexpr vector() noexcept : _v(value_type{0}, value_type{0}, value_type{0}, value_type{0}) {}
72
77 [[nodiscard]] constexpr vector(value_type x, value_type y) noexcept
78 requires(D == 2)
79 : _v(x, y, value_type{0}, value_type{0})
80 {
81 }
82
88 [[nodiscard]] constexpr vector(value_type x, value_type y, value_type z = value_type{0}) noexcept
89 requires(D == 3)
90 : _v(x, y, z, value_type{0})
91 {
92 }
93
97 [[nodiscard]] constexpr value_type& x() noexcept
98 {
99 return _v.x();
100 }
101
105 [[nodiscard]] constexpr value_type& y() noexcept
106 {
107 return _v.y();
108 }
109
113 [[nodiscard]] constexpr value_type& z() noexcept
114 requires(D == 3)
115 {
116 return _v.z();
117 }
118
122 [[nodiscard]] constexpr value_type x() const noexcept
123 {
124 return _v.x();
125 }
126
130 [[nodiscard]] constexpr value_type y() const noexcept
131 {
132 return _v.y();
133 }
134
138 [[nodiscard]] constexpr value_type z() const noexcept
139 requires(D == 3)
140 {
141 return _v.z();
142 }
143
147 [[nodiscard]] constexpr vector operator-() const noexcept
148 {
149 hi_axiom(holds_invariant());
150 return vector{-_v};
151 }
152
153 template<int E>
154 requires(E <= D)
155 constexpr vector& operator+=(vector<value_type, E> const& rhs) noexcept
156 {
157 hi_axiom(holds_invariant() && rhs.holds_invariant());
158 _v = _v + static_cast<array_type>(rhs);
159 return *this;
160 }
161
167 [[nodiscard]] constexpr friend vector operator+(vector const& lhs, vector const& rhs) noexcept
168 {
169 hi_axiom(lhs.holds_invariant() && rhs.holds_invariant());
170 return vector{lhs._v + rhs._v};
171 }
172
178 [[nodiscard]] constexpr friend vector operator-(vector const& lhs, vector const& rhs) noexcept
179 {
180 hi_axiom(lhs.holds_invariant() && rhs.holds_invariant());
181 return vector{lhs._v - rhs._v};
182 }
183
189 [[nodiscard]] constexpr friend vector operator*(vector const& lhs, value_type const& rhs) noexcept
190 {
191 hi_axiom(lhs.holds_invariant());
192 return vector{lhs._v * rhs};
193 }
194
200 [[nodiscard]] constexpr friend vector operator*(value_type const& lhs, vector const& rhs) noexcept
201 {
202 hi_axiom(rhs.holds_invariant());
203 return vector{array_type::broadcast(lhs) * rhs._v};
204 }
205
211 [[nodiscard]] constexpr friend bool operator==(vector const& lhs, vector const& rhs) noexcept
212 {
213 hi_axiom(lhs.holds_invariant() && rhs.holds_invariant());
214 return equal(lhs._v, rhs._v);
215 }
216
221 [[nodiscard]] constexpr friend value_type squared_hypot(vector const& rhs) noexcept
222 {
223 hi_axiom(rhs.holds_invariant());
224 return squared_hypot<element_mask>(rhs._v);
225 }
226
231 [[nodiscard]] constexpr friend value_type hypot(vector const& rhs) noexcept
232 requires std::is_floating_point_v<value_type>
233 {
234 hi_axiom(rhs.holds_invariant());
235 return hypot<element_mask>(rhs._v);
236 }
237
242 [[nodiscard]] constexpr friend value_type rcp_hypot(vector const& rhs) noexcept
243 {
244 hi_axiom(rhs.holds_invariant());
245 return rcp_hypot<element_mask>(rhs._v);
246 }
247
252 [[nodiscard]] constexpr friend vector normalize(vector const& rhs) noexcept
253 {
254 hi_axiom(rhs.holds_invariant());
255 return vector{normalize<element_mask>(rhs._v)};
256 }
257
263 [[nodiscard]] constexpr friend value_type dot(vector const& lhs, vector const& rhs) noexcept
264 {
265 hi_axiom(lhs.holds_invariant() && rhs.holds_invariant());
266 return dot<element_mask>(lhs._v, rhs._v);
267 }
268
274 [[nodiscard]] constexpr friend value_type det(vector const& lhs, vector const& rhs) noexcept
275 requires(D == 2)
276 {
277 hi_axiom(lhs.holds_invariant() && rhs.holds_invariant());
278 return lhs.x() * rhs.y() - lhs.y() * rhs.x();
279 }
280
286 template<int E>
287 [[nodiscard]] friend constexpr auto min(vector const& lhs, vector<value_type, E> const& rhs) noexcept
288 {
289 return vector<value_type, std::max(D, E)>{min(static_cast<array_type>(lhs), static_cast<array_type>(rhs))};
290 }
291
297 template<int E>
298 [[nodiscard]] friend constexpr auto max(vector const& lhs, vector<value_type, E> const& rhs) noexcept
299 {
300 return vector<value_type, std::max(D, E)>{max(static_cast<array_type>(lhs), static_cast<array_type>(rhs))};
301 }
302
305 [[nodiscard]] friend constexpr vector round(vector const& rhs) noexcept
306 {
307 return vector{round(static_cast<array_type>(rhs))};
308 }
309
312 [[nodiscard]] friend constexpr vector ceil(vector const& rhs) noexcept
313 {
314 return vector{ceil(static_cast<array_type>(rhs))};
315 }
316
319 [[nodiscard]] friend constexpr vector floor(vector const& rhs) noexcept
320 {
321 return vector{floor(static_cast<array_type>(rhs))};
322 }
323
327 [[nodiscard]] constexpr bool holds_invariant() const noexcept
328 {
329 return _v.w() == value_type{0} && (D == 3 || _v.z() == value_type{0});
330 }
331
332 [[nodiscard]] friend std::string to_string(vector const& rhs) noexcept
333 {
334 if constexpr (D == 2) {
335 return std::format("({}, {})", rhs._v.x(), rhs._v.y());
336 } else if constexpr (D == 3) {
337 return std::format("({}, {}, {})", rhs._v.x(), rhs._v.y(), rhs._v.z());
338 } else {
340 }
341 }
342
343 friend std::ostream& operator<<(std::ostream& lhs, vector const& rhs) noexcept
344 {
345 return lhs << to_string(rhs);
346 }
347
348private:
349 array_type _v;
350
351 static constexpr std::size_t element_mask = (1_uz << D) - 1;
352};
353
358[[nodiscard]] constexpr vector<float, 2> cross(vector<float, 2> const& rhs) noexcept
359{
360 hi_axiom(rhs.holds_invariant());
361 return vector<float, 2>{cross_2D(static_cast<f32x4>(rhs))};
362}
363
368[[nodiscard]] constexpr vector<float, 2> normal(vector<float, 2> const& rhs) noexcept
369{
370 hi_axiom(rhs.holds_invariant());
371 return normalize(cross(rhs));
372}
373
379[[nodiscard]] constexpr vector<float, 3> normal(vector<float, 3> const& rhs, float angle) noexcept
380{
381 if (angle != float{0}) {
383 }
384 return normal(vector<float, 2>{f32x4{rhs}.xy00()});
385}
386
395[[nodiscard]] constexpr float cross(vector<float, 2> const& lhs, vector<float, 2> const& rhs) noexcept
396{
397 hi_axiom(lhs.holds_invariant() && rhs.holds_invariant());
398 return cross_2D(static_cast<f32x4>(lhs), static_cast<f32x4>(rhs));
399}
400
406[[nodiscard]] constexpr vector<float, 3> cross(vector<float, 3> const& lhs, vector<float, 3> const& rhs) noexcept
407{
408 hi_axiom(lhs.holds_invariant() && rhs.holds_invariant());
409 return vector<float, 3>{cross_3D(static_cast<f32x4>(lhs), static_cast<f32x4>(rhs))};
410}
411
412} // namespace geo
413
414using vector2 = geo::vector<float, 2>;
415using vector3 = geo::vector<float, 3>;
416using vector2i = geo::vector<int, 2>;
417using vector3i = geo::vector<int, 3>;
418
419} // namespace hi::inline v1
420
421template<typename CharT>
422struct std::formatter<hi::geo::vector<float, 2>, CharT> {
423 auto parse(auto& pc)
424 {
425 return pc.end();
426 }
427
428 auto format(hi::geo::vector<float, 2> const& t, auto& fc)
429 {
430 return std::vformat_to(fc.out(), "({}, {})", std::make_format_args(t.x(), t.y()));
431 }
432};
433
434template<typename CharT>
435struct std::formatter<hi::geo::vector<float, 3>, CharT> {
436 auto parse(auto& pc)
437 {
438 return pc.end();
439 }
440
441 auto format(hi::geo::vector<float, 3> const& t, auto& fc)
442 {
443 return std::vformat_to(fc.out(), "({}, {}, {})", std::make_format_args(t.x(), t.y(), t.z()));
444 }
445};
446
447template<typename CharT>
448struct std::formatter<hi::geo::vector<int, 2>, CharT> {
449 auto parse(auto& pc)
450 {
451 return pc.end();
452 }
453
454 auto format(hi::geo::vector<int, 2> const& t, auto& fc)
455 {
456 return std::vformat_to(fc.out(), "({}, {})", std::make_format_args(t.x(), t.y()));
457 }
458};
459
460template<typename CharT>
461struct std::formatter<hi::geo::vector<int, 3>, CharT> {
462 auto parse(auto& pc)
463 {
464 return pc.end();
465 }
466
467 auto format(hi::geo::vector<int, 3> const& t, auto& fc)
468 {
469 return std::vformat_to(fc.out(), "({}, {}, {})", std::make_format_args(t.x(), t.y(), t.z()));
470 }
471};
#define hi_static_no_default(...)
This part of the code should not be reachable, unless a programming bug.
Definition assert.hpp:323
#define hi_not_implemented(...)
This part of the code has not been implemented yet.
Definition assert.hpp:335
#define hi_axiom(expression,...)
Specify an axiom; an expression that is true.
Definition assert.hpp:253
DOXYGEN BUG.
Definition algorithm.hpp:13
geometry/margins.hpp
Definition cache.hpp:11
A high-level geometric vector Part of the high-level vector, point, mat and color types.
Definition vector.hpp:21
constexpr friend value_type det(vector const &lhs, vector const &rhs) noexcept
Get the determinate between two vectors.
Definition vector.hpp:274
constexpr friend value_type squared_hypot(vector const &rhs) noexcept
Get the squared length of the vector.
Definition vector.hpp:221
constexpr vector() noexcept
Construct a empty vector / zero length.
Definition vector.hpp:71
constexpr vector(vector< value_type, E > const &other) noexcept
Construct a vector from a higher dimension vector.
Definition vector.hpp:47
constexpr friend value_type rcp_hypot(vector const &rhs) noexcept
Get the length of the vector.
Definition vector.hpp:242
constexpr friend bool operator==(vector const &lhs, vector const &rhs) noexcept
Compare if two vectors are equal.
Definition vector.hpp:211
friend constexpr vector round(vector const &rhs) noexcept
Round the elements of the vector toward nearest integer.
Definition vector.hpp:305
constexpr bool holds_invariant() const noexcept
Check if the vector is valid.
Definition vector.hpp:327
constexpr friend vector normalize(vector const &rhs) noexcept
Normalize a vector to a unit vector.
Definition vector.hpp:252
constexpr value_type & y() noexcept
Access the y element from the vector.
Definition vector.hpp:105
constexpr value_type y() const noexcept
Access the y element from the vector.
Definition vector.hpp:130
friend constexpr auto max(vector const &lhs, vector< value_type, E > const &rhs) noexcept
Mix the two vectors and get the highest value of each element.
Definition vector.hpp:298
constexpr friend value_type dot(vector const &lhs, vector const &rhs) noexcept
Get the dot product between two vectors.
Definition vector.hpp:263
constexpr friend vector operator*(vector const &lhs, value_type const &rhs) noexcept
Scale the vector by a scaler.
Definition vector.hpp:189
constexpr friend vector operator-(vector const &lhs, vector const &rhs) noexcept
Subtract two vectors from each other.
Definition vector.hpp:178
constexpr value_type & x() noexcept
Access the x element from the vector.
Definition vector.hpp:97
constexpr vector operator-() const noexcept
Mirror this vector.
Definition vector.hpp:147
friend constexpr vector floor(vector const &rhs) noexcept
Round the elements of the vector toward downward and to the left.
Definition vector.hpp:319
constexpr friend value_type hypot(vector const &rhs) noexcept
Get the length of the vector.
Definition vector.hpp:231
constexpr value_type z() const noexcept
Access the z element from the vector.
Definition vector.hpp:138
constexpr value_type & z() noexcept
Access the z element from the vector.
Definition vector.hpp:113
constexpr friend vector operator*(value_type const &lhs, vector const &rhs) noexcept
Scale the vector by a scaler.
Definition vector.hpp:200
constexpr vector(value_type x, value_type y) noexcept
Construct a 2D vector from x and y elements.
Definition vector.hpp:77
friend constexpr vector ceil(vector const &rhs) noexcept
Round the elements of the vector toward upward and to the right.
Definition vector.hpp:312
constexpr vector(value_type x, value_type y, value_type z=value_type{0}) noexcept
Construct a 3D vector from x, y and z elements.
Definition vector.hpp:88
constexpr vector(array_type const &other) noexcept
Construct a vector from a array_type-simd.
Definition vector.hpp:64
constexpr vector(vector< value_type, E > const &other) noexcept
Construct a vector from a lower dimension vector.
Definition vector.hpp:37
friend constexpr auto min(vector const &lhs, vector< value_type, E > const &rhs) noexcept
Mix the two vectors and get the lowest value of each element.
Definition vector.hpp:287
constexpr friend vector operator+(vector const &lhs, vector const &rhs) noexcept
Add two vectors from each other.
Definition vector.hpp:167
constexpr value_type x() const noexcept
Access the x element from the vector.
Definition vector.hpp:122
T max(T... args)
T to_string(T... args)