HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
vector.hpp
1// Copyright Take Vos 2021.
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 tt {
10namespace geo {
11
19template<int D>
20class vector {
21public:
22 static_assert(D == 2 || D == 3, "Only 2D or 3D vectors are supported");
23
24 constexpr vector(vector const &) noexcept = default;
25 constexpr vector(vector &&) noexcept = default;
26 constexpr vector &operator=(vector const &) noexcept = default;
27 constexpr vector &operator=(vector &&) noexcept = default;
28
31 template<int E>
32 requires(E < D) [[nodiscard]] constexpr vector(vector<E> const &other) noexcept : _v(static_cast<f32x4>(other))
33 {
34 tt_axiom(is_valid());
35 }
36
40 template<int E>
41 requires(E > D) [[nodiscard]] constexpr explicit vector(vector<E> const &other) noexcept : _v(static_cast<f32x4>(other))
42 {
43 for (size_t i = D; i != E; ++i) {
44 _v[i] = 0.0f;
45 }
46 tt_axiom(is_valid());
47 }
48
51 [[nodiscard]] constexpr explicit operator f32x4() const noexcept
52 {
53 return _v;
54 }
55
58 [[nodiscard]] constexpr explicit vector(f32x4 const &other) noexcept : _v(other)
59 {
60 tt_axiom(is_valid());
61 }
62
65 [[nodiscard]] constexpr vector() noexcept : _v(0.0f, 0.0f, 0.0f, 0.0f) {}
66
71 [[nodiscard]] constexpr vector(float x, float y) noexcept requires(D == 2) : _v(x, y, 0.0f, 0.0f) {}
72
78 [[nodiscard]] constexpr vector(float x, float y, float z = 0.0f) noexcept requires(D == 3) : _v(x, y, z, 0.0f) {}
79
83 [[nodiscard]] constexpr float &x() noexcept
84 {
85 return _v.x();
86 }
87
91 [[nodiscard]] constexpr float &y() noexcept
92 {
93 return _v.y();
94 }
95
99 [[nodiscard]] constexpr float &z() noexcept requires(D == 3)
100 {
101 return _v.z();
102 }
103
107 [[nodiscard]] constexpr float const &x() const noexcept
108 {
109 return _v.x();
110 }
111
115 [[nodiscard]] constexpr float const &y() const noexcept
116 {
117 return _v.y();
118 }
119
123 [[nodiscard]] constexpr float const &z() const noexcept requires(D == 3)
124 {
125 return _v.z();
126 }
127
131 [[nodiscard]] constexpr vector operator-() const noexcept
132 {
133 tt_axiom(is_valid());
134 return vector{-_v};
135 }
136
137 template<int E> requires (E <= D)
138 constexpr vector &operator+=(vector<E> const &rhs) noexcept
139 {
140 tt_axiom(is_valid() && rhs.is_valid());
141 _v = _v + static_cast<f32x4>(rhs);
142 return *this;
143 }
144
150 [[nodiscard]] constexpr friend vector operator+(vector const &lhs, vector const &rhs) noexcept
151 {
152 tt_axiom(lhs.is_valid() && rhs.is_valid());
153 return vector{lhs._v + rhs._v};
154 }
155
161 [[nodiscard]] constexpr friend vector operator-(vector const &lhs, vector const &rhs) noexcept
162 {
163 tt_axiom(lhs.is_valid() && rhs.is_valid());
164 return vector{lhs._v - rhs._v};
165 }
166
172 [[nodiscard]] constexpr friend vector operator*(vector const &lhs, float const &rhs) noexcept
173 {
174 tt_axiom(lhs.is_valid());
175 return vector{lhs._v * rhs};
176 }
177
183 [[nodiscard]] constexpr friend vector operator*(float const &lhs, vector const &rhs) noexcept
184 {
185 tt_axiom(rhs.is_valid());
186 return vector{f32x4::broadcast(lhs) * rhs._v};
187 }
188
194 [[nodiscard]] constexpr friend bool operator==(vector const &lhs, vector const &rhs) noexcept
195 {
196 tt_axiom(lhs.is_valid() && rhs.is_valid());
197 return lhs._v == rhs._v;
198 }
199
204 [[nodiscard]] constexpr friend float squared_hypot(vector const &rhs) noexcept
205 {
206 tt_axiom(rhs.is_valid());
207 return squared_hypot<element_mask>(rhs._v);
208 }
209
214 [[nodiscard]] constexpr friend float hypot(vector const &rhs) noexcept
215 {
216 tt_axiom(rhs.is_valid());
217 return hypot<element_mask>(rhs._v);
218 }
219
224 [[nodiscard]] constexpr friend float rcp_hypot(vector const &rhs) noexcept
225 {
226 tt_axiom(rhs.is_valid());
227 return rcp_hypot<element_mask>(rhs._v);
228 }
229
234 [[nodiscard]] constexpr friend vector normalize(vector const &rhs) noexcept
235 {
236 tt_axiom(rhs.is_valid());
237 return vector{normalize<element_mask>(rhs._v)};
238 }
239
245 [[nodiscard]] constexpr friend float dot(vector const &lhs, vector const &rhs) noexcept
246 {
247 tt_axiom(lhs.is_valid() && rhs.is_valid());
248 return dot<element_mask>(lhs._v, rhs._v);
249 }
250
256 template<int E>
257 [[nodiscard]] friend constexpr auto min(vector const &lhs, vector<E> const &rhs) noexcept
258 {
259 return vector<std::max(D, E)>{min(static_cast<f32x4>(lhs), static_cast<f32x4>(rhs))};
260 }
261
267 template<int E>
268 [[nodiscard]] friend constexpr auto max(vector const &lhs, vector<E> const &rhs) noexcept
269 {
270 return vector<std::max(D, E)>{max(static_cast<f32x4>(lhs), static_cast<f32x4>(rhs))};
271 }
272
275 [[nodiscard]] friend constexpr vector round(vector const &rhs) noexcept
276 {
277 return vector{round(static_cast<f32x4>(rhs))};
278 }
279
282 [[nodiscard]] friend constexpr vector ceil(vector const &rhs) noexcept
283 {
284 return vector{ceil(static_cast<f32x4>(rhs))};
285 }
286
289 [[nodiscard]] friend constexpr vector floor(vector const &rhs) noexcept
290 {
291 return vector{floor(static_cast<f32x4>(rhs))};
292 }
293
297 [[nodiscard]] constexpr bool is_valid() const noexcept
298 {
299 return _v.w() == 0.0f && (D == 3 || _v.z() == 0.0f);
300 }
301
302 [[nodiscard]] friend std::string to_string(vector const &rhs) noexcept
303 {
304 if constexpr (D == 2) {
305 return std::format("({}, {})", rhs._v.x(), rhs._v.y());
306 } else if constexpr (D == 3) {
307 return std::format("({}, {}, {})", rhs._v.x(), rhs._v.y(), rhs._v.z());
308 } else {
309 tt_static_no_default();
310 }
311 }
312
313 friend std::ostream &operator<<(std::ostream &lhs, vector const &rhs) noexcept
314 {
315 return lhs << to_string(rhs);
316 }
317
318private:
319 f32x4 _v;
320
321 static constexpr size_t element_mask = (1_uz << D) - 1;
322};
323
328[[nodiscard]] constexpr vector<2> cross(vector<2> const &rhs) noexcept
329{
330 tt_axiom(rhs.is_valid());
331 return vector<2>{cross_2D(static_cast<f32x4>(rhs))};
332}
333
338[[nodiscard]] constexpr vector<2> normal(vector<2> const &rhs) noexcept
339{
340 tt_axiom(rhs.is_valid());
341 return normalize(cross(rhs));
342}
343
352[[nodiscard]] constexpr float cross(vector<2> const &lhs, vector<2> const &rhs) noexcept
353{
354 tt_axiom(lhs.is_valid() && rhs.is_valid());
355 return cross_2D(static_cast<f32x4>(lhs), static_cast<f32x4>(rhs));
356}
357
363[[nodiscard]] constexpr vector<3> cross(vector<3> const &lhs, vector<3> const &rhs) noexcept
364{
365 tt_axiom(lhs.is_valid() && rhs.is_valid());
366 return vector<3>{cross_3D(static_cast<f32x4>(lhs), static_cast<f32x4>(rhs))};
367}
368
369}
370
371using vector2 = geo::vector<2>;
372using vector3 = geo::vector<3>;
373
374} // namespace tt
375
376namespace std {
377
378template<typename CharT>
379struct formatter<tt::geo::vector<2>, CharT> {
380 auto parse(auto &pc)
381 {
382 return pc.end();
383 }
384
385 auto format(tt::geo::vector<2> const &t, auto &fc)
386 {
387 return std::vformat_to(fc.out(), "({}, {})", std::make_format_args(t.x(), t.y()));
388 }
389};
390
391template<typename CharT>
392struct formatter<tt::geo::vector<3>, CharT> : formatter<float, CharT> {
393 auto parse(auto &pc)
394 {
395 return pc.end();
396 }
397
398 auto format(tt::geo::vector<3> const &t, auto &fc)
399 {
400 return std::vformat_to(fc.out(), "({}, {}, {})", std::make_format_args(t.x(), t.y(), t.z()));
401 }
402};
403
404} // namespace std
STL namespace.
A high-level geometric vector Part of the high-level vector, point, mat and color types.
Definition vector.hpp:20
constexpr float const & x() const noexcept
Access the x element from the vector.
Definition vector.hpp:107
constexpr vector(f32x4 const &other) noexcept
Construct a vector from a f32x4-numeric_array.
Definition vector.hpp:58
constexpr float & x() noexcept
Access the x element from the vector.
Definition vector.hpp:83
constexpr vector(float x, float y) noexcept
Construct a 2D vector from x and y elements.
Definition vector.hpp:71
constexpr friend float hypot(vector const &rhs) noexcept
Get the length of the vector.
Definition vector.hpp:214
constexpr vector(float x, float y, float z=0.0f) noexcept
Construct a 3D vector from x, y and z elements.
Definition vector.hpp:78
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:257
constexpr friend bool operator==(vector const &lhs, vector const &rhs) noexcept
Compare if two vectors are equal.
Definition vector.hpp:194
constexpr float const & y() const noexcept
Access the y element from the vector.
Definition vector.hpp:115
friend constexpr vector round(vector const &rhs) noexcept
Round the elements of the vector toward nearest integer.
Definition vector.hpp:275
constexpr vector(vector< E > const &other) noexcept
Construct a vector from a higher dimension vector.
Definition vector.hpp:41
constexpr friend vector normalize(vector const &rhs) noexcept
Normalize a vector to a unit vector.
Definition vector.hpp:234
constexpr friend vector operator*(float const &lhs, vector const &rhs) noexcept
Scale the vector by a scaler.
Definition vector.hpp:183
constexpr vector() noexcept
Construct a empty vector / zero length.
Definition vector.hpp:65
constexpr friend vector operator-(vector const &lhs, vector const &rhs) noexcept
Subtract two vectors from each other.
Definition vector.hpp:161
constexpr float & z() noexcept
Access the z element from the vector.
Definition vector.hpp:99
friend constexpr vector floor(vector const &rhs) noexcept
Round the elements of the vector toward downward and to the left.
Definition vector.hpp:289
constexpr vector operator-() const noexcept
Mirror this vector.
Definition vector.hpp:131
constexpr vector(vector< E > const &other) noexcept
Construct a vector from a lower dimension vector.
Definition vector.hpp:32
constexpr friend vector operator*(vector const &lhs, float const &rhs) noexcept
Scale the vector by a scaler.
Definition vector.hpp:172
constexpr float const & z() const noexcept
Access the z element from the vector.
Definition vector.hpp:123
constexpr friend float squared_hypot(vector const &rhs) noexcept
Get the squared length of the vector.
Definition vector.hpp:204
constexpr bool is_valid() const noexcept
Check if the vector is valid.
Definition vector.hpp:297
friend constexpr vector ceil(vector const &rhs) noexcept
Round the elements of the vector toward upward and to the right.
Definition vector.hpp:282
constexpr friend float dot(vector const &lhs, vector const &rhs) noexcept
Get the dot product between two vectors.
Definition vector.hpp:245
constexpr friend float rcp_hypot(vector const &rhs) noexcept
Get the length of the vector.
Definition vector.hpp:224
constexpr friend vector operator+(vector const &lhs, vector const &rhs) noexcept
Add two vectors from each other.
Definition vector.hpp:150
constexpr float & y() noexcept
Access the y element from the vector.
Definition vector.hpp:91
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:268
T max(T... args)