Pasha Bibko Util Library
Loading...
Searching...
No Matches
Vec.h
1#pragma once
2
3#include <type_traits>
4#include <utility>
5#include <cstddef>
6
14namespace PashaBibko::Util
15{
16 /* Excludes the internal namespace from the documentation */
17 #ifndef DOXYGEN_HIDE
18
19 namespace Internal
20 {
21 /* General layout of a Vec<T> with just an array of x length */
22 template<std::size_t len, typename Ty, typename Enable = void>
23 struct VecMembers
24 {
25 Ty data[len];
26
27 template<typename... Args> VecMembers(Args&&... args) : data{ std::forward<Args>(args)... } {}
28 };
29
30 /* Provides aliases of [X, Y] to indecies of [0, 1] to the array when of length 2 */
31 template<std::size_t len, typename Ty>
32 struct VecMembers<len, Ty, std::enable_if_t<(len == 2)>>
33 {
34 union
35 {
36 struct { Ty x, y; };
37 Ty data[2];
38 };
39
40 template<typename... Args> VecMembers(Args&&... args) : data{ std::forward<Args>(args)... } {}
41 };
42
43 /* Provides aliases of [X, Y, Z] and [R, G, B] to indecies of [0, 1, 2] to the array when of length 3 */
44 template<std::size_t len, typename Ty>
45 struct VecMembers<len, Ty, std::enable_if_t<(len == 3)>>
46 {
47 union
48 {
49 struct { Ty x, y, z; };
50 struct { Ty r, g, b; };
51 Ty data[3];
52 };
53
54 template<typename... Args> VecMembers(Args&&... args) : data{ std::forward<Args>(args)... } {}
55 };
56
57 /* Provides aliases of [X, Y, Z, Z] and [R, G, B, A] to indecies of [0, 1, 2, 3] to the array when of length 4 */
58 template<std::size_t len, typename Ty>
59 struct VecMembers<len, Ty, std::enable_if_t<(len == 4)>>
60 {
61 union
62 {
63 struct { Ty x, y, z, w; };
64 struct { Ty r, g, b, a; };
65 Ty data[4];
66 };
67
68 template<typename... Args> VecMembers(Args&&... args) : data{ std::forward<Args>(args)... } {}
69 };
70
71 /* Checks all types within a variadic template are the same */
72 template<typename Ty, typename... Args> concept AllSameType = (std::is_same_v<Ty, Args> && ...);
73
74 /* Checks types can be added together */
75 template<typename LhsTy, typename RhsTy>
76 concept CanAdd = requires(LhsTy lhs, RhsTy rhs)
77 {
78 { lhs + rhs } -> std::same_as<decltype(lhs + rhs)>;
79 };
80
81 /* The result type when two types are added to each other */
82 template<typename LhsTy, typename RhsTy>
83 using AddResultT = decltype(std::declval<LhsTy>() + std::declval<RhsTy>());
84
85 /* Checks two types can be subtracted from each other */
86 template<typename LhsTy, typename RhsTy>
87 concept CanSub = requires(LhsTy lhs, RhsTy rhs)
88 {
89 { lhs - rhs } -> std::same_as<decltype(lhs - rhs)>;
90 };
91
92 /* The result type when two types are subtracted from each other */
93 template<typename LhsTy, typename RhsTy>
94 using SubResultT = decltype(std::declval<LhsTy>() + std::declval<RhsTy>());
95
96 /* Checks two types can be multipled together */
97 template<typename LhsTy, typename RhsTy>
98 concept CanMul = requires(LhsTy lhs, RhsTy rhs)
99 {
100 { lhs * rhs } -> std::same_as<decltype(lhs * rhs)>;
101 };
102
103 /* The result type when two types are multiplied to each other */
104 template<typename LhsTy, typename RhsTy>
105 using MulResultT = decltype(std::declval<LhsTy>() * std::declval<RhsTy>());
106
107 /* Checks two types can be divided from each other */
108 template<typename LhsTy, typename RhsTy>
109 concept CanDiv = requires(LhsTy lhs, RhsTy rhs)
110 {
111 { lhs / rhs } -> std::same_as<decltype(lhs + rhs)>;
112 };
113
114 /* The result type when two types are divided from each other */
115 template<typename LhsTy, typename RhsTy>
116 using DivResultT = decltype(std::declval<LhsTy>() / std::declval<RhsTy>());
117
118 /* Checks the types can be compared equally */
119 template<typename LhsTy, typename RhsTy>
120 concept CanEqualityCheck = requires(LhsTy lhs, RhsTy rhs)
121 {
122 { lhs == rhs } -> std::convertible_to<bool>;
123 { lhs != rhs } -> std::convertible_to<bool>;
124 };
125 }
126
127 #endif // DOXYGEN_HIDE
128
213 template<std::size_t len, typename Ty>
214 requires (len != 0 && len != 1) && std::is_copy_constructible_v<Ty>
215 struct Vec : public Internal::VecMembers<len, Ty>
216 {
223 template<typename = std::enable_if_t<std::is_default_constructible_v<Ty>>>
225 {
226 for (std::size_t index = 0; index < len; index++)
227 this->data[index] = Ty{};
228 }
229
235 explicit Vec(const Ty& value)
236 {
237 for (std::size_t index = 0; index < len; index++)
238 this->data[index] = value;
239 }
240
249 template<typename... Args> requires Internal::AllSameType<Ty, Args...> && (sizeof...(Args) == len)
250 explicit Vec(Args&&... args) : Internal::VecMembers<len, Ty>(std::forward<Args>(args)...) {}
251
261 Ty& operator[](std::size_t index) { return this->data[index]; }
262
269 Ty* begin() noexcept { return this->data; }
270
277 Ty* end() { return this->data + len; }
278
279 /* Hides const versions of functions as they do not need to be documented twice */
280 #ifndef DOXYGEN_HIDE
281
282 const Ty& operator[](std::size_t index) const { return this->data[index]; }
283
284 const Ty* begin() const noexcept { return this->data; }
285 const Ty* cbegin() const noexcept { return this->data; }
286
287 const Ty* end() const noexcept { return this->data + len; }
288 const Ty* cend() const noexcept { return this->data + len; }
289
290 #endif // DOXYGEN_HIDE
291
299 template<typename OtherTy>
300 requires Internal::CanAdd<Ty, OtherTy> && std::is_same_v<Ty, Internal::AddResultT<Ty, OtherTy>>
301 Vec& operator+= (const Vec<len, OtherTy>& other)
302 {
303 for (std::size_t index = 0; index < len; index++)
304 this->data[index] += other[index];
305
306 return *this;
307 }
308
316 template<typename OtherTy>
317 requires Internal::CanSub<Ty, OtherTy> && std::is_same_v<Ty, Internal::SubResultT<Ty, OtherTy>>
318 Vec& operator-= (const Vec<len, OtherTy>& other)
319 {
320 for (std::size_t index = 0; index < len; index++)
321 this->data[index] += other[index];
322
323 return *this;
324 }
325
333 template<typename OtherTy>
334 requires Internal::CanMul<Ty, OtherTy> && std::is_same_v<Ty, Internal::MulResultT<Ty, OtherTy>>
335 Vec& operator*= (const Vec<len, OtherTy>& other)
336 {
337 for (std::size_t index = 0; index < len; index++)
338 this->data[index] += other[index];
339
340 return *this;
341 }
342
350 template<typename OtherTy>
351 requires Internal::CanDiv<Ty, OtherTy> && std::is_same_v<Ty, Internal::DivResultT<Ty, OtherTy>>
352 Vec& operator/= (const Vec<len, OtherTy>& other)
353 {
354 for (std::size_t index = 0; index < len; index++)
355 this->data[index] += other[index];
356
357 return *this;
358 }
359 };
360
369 template<std::size_t len, typename LhsTy, typename RhsTy, typename ResTy = Internal::AddResultT<LhsTy, RhsTy>>
370 requires Internal::CanAdd<LhsTy, RhsTy>
372 {
373 return [&]<std::size_t... index>(std::index_sequence<index...>) { return Vec<len, ResTy>{ (lhs[index] + rhs[index])... }; } (std::make_index_sequence<len>{});
374 }
375
383 template<std::size_t len, typename LhsTy, typename RhsTy, typename ResTy = Internal::SubResultT<LhsTy, RhsTy>>
384 requires Internal::CanSub<LhsTy, RhsTy>
386 {
387 return [&]<std::size_t... index>(std::index_sequence<index...>) { return Vec<len, ResTy>{ (lhs[index] - rhs[index])... }; } (std::make_index_sequence<len>{});
388 }
389
398 template<std::size_t len, typename LhsTy, typename RhsTy, typename ResTy = Internal::MulResultT<LhsTy, RhsTy>>
399 requires Internal::CanMul<LhsTy, RhsTy>
401 {
402 return [&]<std::size_t... index>(std::index_sequence<index...>) { return Vec<len, ResTy>{ (lhs[index] * rhs[index])... }; } (std::make_index_sequence<len>{});
403 }
404
413 template<std::size_t len, typename LhsTy, typename RhsTy, typename ResTy = Internal::SubResultT<LhsTy, RhsTy>>
414 requires Internal::CanDiv<LhsTy, RhsTy>
416 {
417 return [&]<std::size_t... index>(std::index_sequence<index...>) { return Vec<len, ResTy>{ (lhs[index] / rhs[index])... }; } (std::make_index_sequence<len>{});
418 }
419
426 template<std::size_t len, typename LhsTy, typename RhsTy>
427 requires Internal::CanEqualityCheck<LhsTy, RhsTy>
428 bool operator== (const Vec<len, LhsTy>& lhs, const Vec<len, RhsTy>& rhs)
429 {
430 for (std::size_t index = 0; index < len; index++)
431 {
432 if (lhs[index] != rhs[index])
433 return false;
434 }
435
436 return true;
437 }
438
445 template<std::size_t len, typename LhsTy, typename RhsTy>
446 requires Internal::CanEqualityCheck<LhsTy, RhsTy>
447 bool operator!= (const Vec<len, LhsTy>& lhs, const Vec<len, RhsTy>& rhs)
448 {
449 for (size_t index = 0; index < len; index++)
450 {
451 if (lhs[index] == rhs[index])
452 return false;
453 }
454
455 return true;
456 }
457
458 /* Hides using aliases to avoid uneccesary bloat in doxygen documentation */
459 /* The types are mentoined in the description of Vec<len, T> */
460 #ifndef DOXYGEN_HIDE
461
462 template<typename Ty = float>
463 using Vec2 = Vec<2, Ty>;
464
465 template<typename Ty = float>
466 using Vec3 = Vec<3, Ty>;
467
468 template<typename Ty = float>
469 using Vec4 = Vec<4, Ty>;
470
471 using Vec2s = Vec3<short>;
472 using Vec2i = Vec3<int>;
473 using Vec2u = Vec3<unsigned int>;
474 using Vec2l = Vec3<long>;
475 using Vec2d = Vec3<double>;
476
477 using Vec3s = Vec3<short>;
478 using Vec3i = Vec3<int>;
479 using Vec3u = Vec3<unsigned int>;
480 using Vec3l = Vec3<long>;
481 using Vec3d = Vec3<double>;
482
483 using Vec3s = Vec3<short>;
484 using Vec3i = Vec3<int>;
485 using Vec3u = Vec3<unsigned int>;
486 using Vec3l = Vec3<long>;
487 using Vec3d = Vec3<double>;
488
489 #endif // DOXYGEN_HIDE
490}
Definition Colour.h:10
bool operator==(const Vec< len, LhsTy > &lhs, const Vec< len, RhsTy > &rhs)
Checks if two vectors are equal.
Definition Vec.h:428
bool operator!=(const Vec< len, LhsTy > &lhs, const Vec< len, RhsTy > &rhs)
Checks if two vectors are not equal.
Definition Vec.h:447
Vec< len, ResTy > operator-(const Vec< len, LhsTy > &lhs, const Vec< len, RhsTy > &rhs)
Subtracts the right vector by the left vector.
Definition Vec.h:385
Vec< len, ResTy > operator+(const Vec< len, LhsTy > &lhs, const Vec< len, RhsTy > &rhs)
Adds two vectors together.
Definition Vec.h:371
Vec< len, ResTy > operator/(const Vec< len, LhsTy > &lhs, const Vec< len, RhsTy > &rhs)
Divides the left vector by the right vector.
Definition Vec.h:415
Vec< len, ResTy > operator*(const Vec< len, LhsTy > &lhs, const Vec< len, RhsTy > &rhs)
Multiplies two vectors together.
Definition Vec.h:400
Mathmatical vector class.
Definition Vec.h:216
Ty & operator[](std::size_t index)
Returns a reference to the item at that index.
Definition Vec.h:261
Vec(Args &&... args)
Creates a vector with a given value for each item.
Definition Vec.h:250
Ty * end()
Returns a pointer to the end of the vector.
Definition Vec.h:277
Vec()
Default constructor which default constructs all items.
Definition Vec.h:224
Vec(const Ty &value)
Constructor to create each item in the vector with a given value.
Definition Vec.h:235
Ty * begin() noexcept
Returns a pointer to the beginning of the array.
Definition Vec.h:269