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
94 [[nodiscard]] constexpr static vector infinity() noexcept
95 requires(D == 2)
96 {
98 }
99
100 [[nodiscard]] constexpr static vector infinity() noexcept
101 requires(D == 3)
102 {
103 return vector{
107 }
108
112 [[nodiscard]] constexpr value_type& x() noexcept
113 {
114 return _v.x();
115 }
116
120 [[nodiscard]] constexpr value_type& y() noexcept
121 {
122 return _v.y();
123 }
124
128 [[nodiscard]] constexpr value_type& z() noexcept
129 requires(D == 3)
130 {
131 return _v.z();
132 }
133
137 [[nodiscard]] constexpr value_type x() const noexcept
138 {
139 return _v.x();
140 }
141
145 [[nodiscard]] constexpr value_type y() const noexcept
146 {
147 return _v.y();
148 }
149
153 [[nodiscard]] constexpr value_type z() const noexcept
154 requires(D == 3)
155 {
156 return _v.z();
157 }
158
162 [[nodiscard]] constexpr vector operator-() const noexcept
163 {
164 hi_axiom(holds_invariant());
165 return vector{-_v};
166 }
167
168 template<int E>
169 requires(E <= D)
170 constexpr vector& operator+=(vector<value_type, E> const& rhs) noexcept
171 {
172 hi_axiom(holds_invariant() && rhs.holds_invariant());
173 _v = _v + static_cast<array_type>(rhs);
174 return *this;
175 }
176
182 [[nodiscard]] constexpr friend vector operator+(vector const& lhs, vector const& rhs) noexcept
183 {
184 hi_axiom(lhs.holds_invariant() && rhs.holds_invariant());
185 return vector{lhs._v + rhs._v};
186 }
187
193 [[nodiscard]] constexpr friend vector operator-(vector const& lhs, vector const& rhs) noexcept
194 {
195 hi_axiom(lhs.holds_invariant() && rhs.holds_invariant());
196 return vector{lhs._v - rhs._v};
197 }
198
204 [[nodiscard]] constexpr friend vector operator*(vector const& lhs, value_type const& rhs) noexcept
205 {
206 hi_axiom(lhs.holds_invariant());
207 return vector{lhs._v * rhs};
208 }
209
215 [[nodiscard]] constexpr friend vector operator*(value_type const& lhs, vector const& rhs) noexcept
216 {
217 hi_axiom(rhs.holds_invariant());
218 return vector{array_type::broadcast(lhs) * rhs._v};
219 }
220
226 [[nodiscard]] constexpr friend bool operator==(vector const& lhs, vector const& rhs) noexcept
227 {
228 hi_axiom(lhs.holds_invariant() && rhs.holds_invariant());
229 return equal(lhs._v, rhs._v);
230 }
231
236 [[nodiscard]] constexpr friend value_type squared_hypot(vector const& rhs) noexcept
237 {
238 hi_axiom(rhs.holds_invariant());
239 return squared_hypot<element_mask>(rhs._v);
240 }
241
246 [[nodiscard]] constexpr friend value_type hypot(vector const& rhs) noexcept
247 requires std::is_floating_point_v<value_type>
248 {
249 hi_axiom(rhs.holds_invariant());
250 return hypot<element_mask>(rhs._v);
251 }
252
257 [[nodiscard]] constexpr friend value_type rcp_hypot(vector const& rhs) noexcept
258 {
259 hi_axiom(rhs.holds_invariant());
260 return rcp_hypot<element_mask>(rhs._v);
261 }
262
267 [[nodiscard]] constexpr friend vector normalize(vector const& rhs) noexcept
268 {
269 hi_axiom(rhs.holds_invariant());
270 return vector{normalize<element_mask>(rhs._v)};
271 }
272
278 [[nodiscard]] constexpr friend value_type dot(vector const& lhs, vector const& rhs) noexcept
279 {
280 hi_axiom(lhs.holds_invariant() && rhs.holds_invariant());
281 return dot<element_mask>(lhs._v, rhs._v);
282 }
283
289 [[nodiscard]] constexpr friend value_type det(vector const& lhs, vector const& rhs) noexcept
290 requires(D == 2)
291 {
292 hi_axiom(lhs.holds_invariant() && rhs.holds_invariant());
293 return lhs.x() * rhs.y() - lhs.y() * rhs.x();
294 }
295
301 [[nodiscard]] friend constexpr vector min(vector const& lhs, vector const& rhs) noexcept
302 {
303 return vector{min(static_cast<array_type>(lhs), static_cast<array_type>(rhs))};
304 }
305
311 [[nodiscard]] friend constexpr vector max(vector const& lhs, vector const& rhs) noexcept
312 {
313 return vector{max(static_cast<array_type>(lhs), static_cast<array_type>(rhs))};
314 }
315
318 [[nodiscard]] friend constexpr vector round(vector const& rhs) noexcept
319 {
320 return vector{round(static_cast<array_type>(rhs))};
321 }
322
325 [[nodiscard]] friend constexpr vector ceil(vector const& rhs) noexcept
326 {
327 return vector{ceil(static_cast<array_type>(rhs))};
328 }
329
332 [[nodiscard]] friend constexpr vector floor(vector const& rhs) noexcept
333 {
334 return vector{floor(static_cast<array_type>(rhs))};
335 }
336
340 [[nodiscard]] constexpr bool holds_invariant() const noexcept
341 {
342 return _v.w() == value_type{0} && (D == 3 || _v.z() == value_type{0});
343 }
344
345 [[nodiscard]] friend std::string to_string(vector const& rhs) noexcept
346 {
347 if constexpr (D == 2) {
348 return std::format("({}, {})", rhs._v.x(), rhs._v.y());
349 } else if constexpr (D == 3) {
350 return std::format("({}, {}, {})", rhs._v.x(), rhs._v.y(), rhs._v.z());
351 } else {
353 }
354 }
355
356 friend std::ostream& operator<<(std::ostream& lhs, vector const& rhs) noexcept
357 {
358 return lhs << to_string(rhs);
359 }
360
361private:
362 array_type _v;
363
364 static constexpr std::size_t element_mask = (1_uz << D) - 1;
365};
366
371[[nodiscard]] constexpr vector<float, 2> cross(vector<float, 2> const& rhs) noexcept
372{
373 hi_axiom(rhs.holds_invariant());
374 return vector<float, 2>{cross_2D(static_cast<f32x4>(rhs))};
375}
376
381[[nodiscard]] constexpr vector<float, 2> normal(vector<float, 2> const& rhs) noexcept
382{
383 hi_axiom(rhs.holds_invariant());
384 return normalize(cross(rhs));
385}
386
392[[nodiscard]] constexpr vector<float, 3> normal(vector<float, 3> const& rhs, float angle) noexcept
393{
394 if (angle != float{0}) {
396 }
397 return normal(vector<float, 2>{f32x4{rhs}.xy00()});
398}
399
408[[nodiscard]] constexpr float cross(vector<float, 2> const& lhs, vector<float, 2> const& rhs) noexcept
409{
410 hi_axiom(lhs.holds_invariant() && rhs.holds_invariant());
411 return cross_2D(static_cast<f32x4>(lhs), static_cast<f32x4>(rhs));
412}
413
419[[nodiscard]] constexpr vector<float, 3> cross(vector<float, 3> const& lhs, vector<float, 3> const& rhs) noexcept
420{
421 hi_axiom(lhs.holds_invariant() && rhs.holds_invariant());
422 return vector<float, 3>{cross_3D(static_cast<f32x4>(lhs), static_cast<f32x4>(rhs))};
423}
424
425} // namespace geo
426
427using vector2 = geo::vector<float, 2>;
428using vector3 = geo::vector<float, 3>;
429using vector2i = geo::vector<int, 2>;
430using vector3i = geo::vector<int, 3>;
431
432} // namespace hi::inline v1
433
434template<typename CharT>
435struct std::formatter<hi::geo::vector<float, 2>, CharT> {
436 auto parse(auto& pc)
437 {
438 return pc.end();
439 }
440
441 auto format(hi::geo::vector<float, 2> const& t, auto& fc)
442 {
443 return std::vformat_to(fc.out(), "({}, {})", std::make_format_args(t.x(), t.y()));
444 }
445};
446
447template<typename CharT>
448struct std::formatter<hi::geo::vector<float, 3>, CharT> {
449 auto parse(auto& pc)
450 {
451 return pc.end();
452 }
453
454 auto format(hi::geo::vector<float, 3> const& t, auto& fc)
455 {
456 return std::vformat_to(fc.out(), "({}, {}, {})", std::make_format_args(t.x(), t.y(), t.z()));
457 }
458};
459
460template<typename CharT>
461struct std::formatter<hi::geo::vector<int, 2>, CharT> {
462 auto parse(auto& pc)
463 {
464 return pc.end();
465 }
466
467 auto format(hi::geo::vector<int, 2> const& t, auto& fc)
468 {
469 return std::vformat_to(fc.out(), "({}, {})", std::make_format_args(t.x(), t.y()));
470 }
471};
472
473template<typename CharT>
474struct std::formatter<hi::geo::vector<int, 3>, CharT> {
475 auto parse(auto& pc)
476 {
477 return pc.end();
478 }
479
480 auto format(hi::geo::vector<int, 3> const& t, auto& fc)
481 {
482 return std::vformat_to(fc.out(), "({}, {}, {})", std::make_format_args(t.x(), t.y(), t.z()));
483 }
484};
#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:289
friend constexpr vector min(vector const &lhs, vector const &rhs) noexcept
Mix the two vectors and get the lowest value of each element.
Definition vector.hpp:301
constexpr friend value_type squared_hypot(vector const &rhs) noexcept
Get the squared length of the vector.
Definition vector.hpp:236
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:257
constexpr friend bool operator==(vector const &lhs, vector const &rhs) noexcept
Compare if two vectors are equal.
Definition vector.hpp:226
friend constexpr vector round(vector const &rhs) noexcept
Round the elements of the vector toward nearest integer.
Definition vector.hpp:318
constexpr bool holds_invariant() const noexcept
Check if the vector is valid.
Definition vector.hpp:340
constexpr friend vector normalize(vector const &rhs) noexcept
Normalize a vector to a unit vector.
Definition vector.hpp:267
constexpr value_type & y() noexcept
Access the y element from the vector.
Definition vector.hpp:120
constexpr value_type y() const noexcept
Access the y element from the vector.
Definition vector.hpp:145
constexpr friend value_type dot(vector const &lhs, vector const &rhs) noexcept
Get the dot product between two vectors.
Definition vector.hpp:278
constexpr friend vector operator*(vector const &lhs, value_type const &rhs) noexcept
Scale the vector by a scaler.
Definition vector.hpp:204
constexpr friend vector operator-(vector const &lhs, vector const &rhs) noexcept
Subtract two vectors from each other.
Definition vector.hpp:193
constexpr value_type & x() noexcept
Access the x element from the vector.
Definition vector.hpp:112
constexpr vector operator-() const noexcept
Mirror this vector.
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:332
constexpr friend value_type hypot(vector const &rhs) noexcept
Get the length of the vector.
Definition vector.hpp:246
constexpr value_type z() const noexcept
Access the z element from the vector.
Definition vector.hpp:153
constexpr value_type & z() noexcept
Access the z element from the vector.
Definition vector.hpp:128
constexpr friend vector operator*(value_type const &lhs, vector const &rhs) noexcept
Scale the vector by a scaler.
Definition vector.hpp:215
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:325
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 vector max(vector const &lhs, vector const &rhs) noexcept
Mix the two vectors and get the highest value of each element.
Definition vector.hpp:311
constexpr friend vector operator+(vector const &lhs, vector const &rhs) noexcept
Add two vectors from each other.
Definition vector.hpp:182
constexpr value_type x() const noexcept
Access the x element from the vector.
Definition vector.hpp:137
T infinity(T... args)
T to_string(T... args)