Ridiculous Generic Vector class header - WIP.
This commit is contained in:
@@ -6,11 +6,158 @@
|
|||||||
|
|
||||||
namespace J3ML::LinearAlgebra
|
namespace J3ML::LinearAlgebra
|
||||||
{
|
{
|
||||||
template <size_t DIMS, typename T>
|
|
||||||
|
template <size_t D, typename T>
|
||||||
class Vector {
|
class Vector {
|
||||||
|
static_assert(D > 1, "A vector cannot be of 1-dimension, it would be just a scalar!");
|
||||||
public:
|
public:
|
||||||
enum { Dimensions = DIMS};
|
static constexpr bool IsAtLeast1D = D >= 1; // Should always be true for a proper vector.
|
||||||
T elems[DIMS];
|
static constexpr bool IsAtLeast2D = D >= 2; // Should always be true for a proper vector.
|
||||||
|
static constexpr bool IsAtLeast3D = D >= 3;
|
||||||
|
static constexpr bool IsAtLeast4D = D >= 4;
|
||||||
|
|
||||||
|
static constexpr bool Is1D = IsAtLeast1D; // Should always be true for a proper vector.
|
||||||
|
static constexpr bool Is2D = IsAtLeast2D; // Should always be true for a proper vector.
|
||||||
|
static constexpr bool Is3D = IsAtLeast3D;
|
||||||
|
static constexpr bool Is4D = IsAtLeast4D;
|
||||||
|
|
||||||
|
static constexpr bool IsExact1D = D == 1; // Should never be true for a proper vector.
|
||||||
|
static constexpr bool IsExact2D = D == 2;
|
||||||
|
static constexpr bool IsExact3D = D == 3;
|
||||||
|
static constexpr bool IsExact4D = D == 4;
|
||||||
|
|
||||||
|
static constexpr bool IsAtMost1D = D <= 1; // Should also never be true.
|
||||||
|
static constexpr bool IsAtMost2D = D <= 2;
|
||||||
|
static constexpr bool IsAtMost3D = D <= 3;
|
||||||
|
static constexpr bool IsAtMost4D = D <= 4;
|
||||||
|
|
||||||
|
static constexpr bool IsFloatingPoint = std::is_floating_point_v<T>;
|
||||||
|
static constexpr bool IsIntegral = std::is_integral_v<T>;
|
||||||
|
|
||||||
|
using value_type = T;
|
||||||
|
using self_type = Vector<D, T>;
|
||||||
|
static const Vector<D, T> Zero;
|
||||||
|
static const self_type One = self_type(1);
|
||||||
|
static const self_type UnitX;
|
||||||
|
static const self_type UnitY;
|
||||||
|
static const self_type NaN = self_type(std::numeric_limits<T>::signaling_NaN());
|
||||||
|
static const self_type Infinity = self_type(std::numeric_limits<T>::infinity());
|
||||||
|
static const self_type NegativeInfinity = self_type(-std::numeric_limits<T>::infinity());
|
||||||
|
static self_type GetUnitX() requires Is1D {}
|
||||||
|
static self_type GetUnitY() requires Is2D {}
|
||||||
|
static self_type GetUnitZ() requires Is3D {}
|
||||||
|
static self_type GetUnitW() requires Is4D {}
|
||||||
|
enum { Dimensions = D};
|
||||||
|
std::array<T, Dimensions> data;
|
||||||
|
/// Default constructor initializes all elements to zero.
|
||||||
|
Vector() : data{} {}
|
||||||
|
/// Initialize all elements to a single value.
|
||||||
|
explicit Vector(T value) { data.fill(value); }
|
||||||
|
Vector(T x, T y) requires Is2D: data{x, y} {}
|
||||||
|
Vector(T x, T y, T z) requires Is3D: data{x, y, z} {}
|
||||||
|
Vector(T x, T y, T z, T w) requires Is4D: data{x, y, z, w} {}
|
||||||
|
Vector(std::initializer_list<T> values);
|
||||||
|
T& operator[](size_t index) { return data[index]; }
|
||||||
|
const T& operator[](size_t index) const { return data[index]; }
|
||||||
|
T X() const requires Is1D { return At(0);}
|
||||||
|
T Y() const requires Is2D { return At(1);}
|
||||||
|
T Z() const requires Is3D { return At(2);}
|
||||||
|
T W() const requires Is4D { return At(3);}
|
||||||
|
T& X() requires Is1D { return At(0);}
|
||||||
|
T& Y() requires Is2D { return At(1);}
|
||||||
|
T& Z() requires Is3D { return At(2);}
|
||||||
|
T& W() requires Is4D { return At(3);}
|
||||||
|
Vector<2, T> XX() const requires Is1D { return {X()};}
|
||||||
|
Vector<2, T> YY() const requires Is2D { return {Y()};}
|
||||||
|
Vector<2, T> ZZ() const requires Is3D { return {Z()};}
|
||||||
|
Vector<2, T> WW() const requires Is4D { return {W()};}
|
||||||
|
Vector<3, T> XXX() const requires Is1D { return {X()};}
|
||||||
|
Vector<3, T> YYY() const requires Is2D { return {Y()};}
|
||||||
|
Vector<3, T> ZZZ() const requires Is3D { return {Z()};}
|
||||||
|
Vector<3, T> WWW() const requires Is4D { return {W()};}
|
||||||
|
Vector<4, T> XXXX() const requires Is1D { return {X()};}
|
||||||
|
Vector<4, T> YYYY() const requires Is2D { return {Y()};}
|
||||||
|
Vector<4, T> ZZZZ() const requires Is3D { return {Z()};}
|
||||||
|
Vector<4, T> WWWW() const requires Is4D { return {W()};}
|
||||||
|
Vector<2, T> XY() const requires Is2D { return {X(), Y()};}
|
||||||
|
Vector<2, T> XYZ() const requires Is3D { return {X(), Y(), Z()};}
|
||||||
|
Vector<2, T> XYZW() const requires Is4D { return {X(), Y(), Z(), W()};}
|
||||||
|
self_type& operator+=(const self_type& other);
|
||||||
|
T* ptr();
|
||||||
|
[[nodiscard]] const T* ptr() const;
|
||||||
|
[[nodiscard]]T At(size_t index) const;
|
||||||
|
T& At(size_t index);
|
||||||
|
[[nodiscard]] T Dot(const self_type& other) const;
|
||||||
|
[[nodiscard]] T LengthSquared() const;
|
||||||
|
[[nodiscard]] T LengthSq() const;
|
||||||
|
[[nodiscard]] T Length() const;
|
||||||
|
[[nodiscard]] self_type& Normalized() const;
|
||||||
|
void Normalize();
|
||||||
|
template <size_t N> void Normalize();
|
||||||
|
bool IsNormalized() const;
|
||||||
|
template <size_t N> bool IsNormalized() const;
|
||||||
|
bool IsFinite() const;
|
||||||
|
bool IsZero();
|
||||||
|
bool IsPerpendicular() const;
|
||||||
|
bool IsPerp();
|
||||||
|
self_type Min(const self_type& ceil) const;
|
||||||
|
self_type Max(const self_type& floor) const;
|
||||||
|
self_type Min(T ceil) const;
|
||||||
|
self_type Max(T floor) const;
|
||||||
|
self_type Clamp(const self_type& floor, const self_type& ceil) const;
|
||||||
|
self_type Clamp(T floor, T ceil) const;
|
||||||
|
T Distance(const self_type& other) const requires IsFloatingPoint;
|
||||||
|
int ManhattanDistance(const self_type& other) const requires IsIntegral;
|
||||||
|
|
||||||
|
self_type Cross(const self_type& other) const requires Is3D && IsFloatingPoint {
|
||||||
|
return {
|
||||||
|
At(1) * other.At(2) - At(2) * other.At(1),
|
||||||
|
At(2) * other.At(0) - At(0) * other.At(2),
|
||||||
|
At(0) * other.At(1) - At(1) * other.At(0),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool AreOrthonormal(const self_type& A, const self_type& B, float epsilon = 1e-3f);
|
||||||
|
|
||||||
|
self_type Abs() const;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<size_t DIMS, typename T>
|
||||||
|
Vector<DIMS, T>::Vector(std::initializer_list<T> values) {
|
||||||
|
size_t i = 0;
|
||||||
|
for (const T& value : values) {
|
||||||
|
if (i < DIMS) {
|
||||||
|
data[i++] = value;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<size_t DIMS, typename T>
|
||||||
|
Vector<DIMS, T> & Vector<DIMS, T>::operator+=(const Vector &other) {
|
||||||
|
return {0};
|
||||||
|
}
|
||||||
|
|
||||||
|
using v2f = Vector<2, float>;
|
||||||
|
using v3f = Vector<3, float>;
|
||||||
|
using v4f = Vector<4, float>;
|
||||||
|
using v2d = Vector<2, double>;
|
||||||
|
using v3d = Vector<3, double>;
|
||||||
|
using v4d = Vector<4, double>;
|
||||||
|
using v2i = Vector<2, int>;
|
||||||
|
using v3i = Vector<3, int>;
|
||||||
|
using v4i = Vector<4, int>;
|
||||||
|
|
||||||
|
const v2f Vector<2, float>::Zero = v2f(0);
|
||||||
|
const v3f Vector<3, float>::Zero = v3f(0);
|
||||||
|
const v4f Vector<4, float>::Zero = v4f(0);
|
||||||
|
|
||||||
|
const v2f Vector<2, float>::One = v2f(1);
|
||||||
|
const v3f Vector<3, float>::One = v3f(1);
|
||||||
|
const v4f Vector<4, float>::One = v4f(1);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
16
main.cpp
16
main.cpp
@@ -16,6 +16,7 @@
|
|||||||
#include <J3ML/J3ML.hpp>
|
#include <J3ML/J3ML.hpp>
|
||||||
#include <jlog/Logger.hpp>
|
#include <jlog/Logger.hpp>
|
||||||
#include <J3ML/LinearAlgebra/Matrix.hpp>
|
#include <J3ML/LinearAlgebra/Matrix.hpp>
|
||||||
|
#include <J3ML/LinearAlgebra/Vector.hpp>
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
@@ -70,10 +71,25 @@ int main(int argc, char** argv)
|
|||||||
|
|
||||||
auto C = A*B;
|
auto C = A*B;
|
||||||
|
|
||||||
|
using Matrix2x3f = Matrix<2, 3, float>;
|
||||||
|
|
||||||
|
|
||||||
std::cout << C << std::endl;
|
std::cout << C << std::endl;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
std::cout << "j3ml demo coming soon" << std::endl;
|
std::cout << "j3ml demo coming soon" << std::endl;
|
||||||
|
|
||||||
|
v2f _v2f{1.f};
|
||||||
|
v3f _v3f{1.f};
|
||||||
|
v4f _v4f(1);
|
||||||
|
|
||||||
|
v2i ipair (420, 420);
|
||||||
|
|
||||||
|
v3i ipair3(0,0,0);
|
||||||
|
|
||||||
|
v4i ipair4(1,2,3,4);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user