Ridiculous Generic Vector class header - WIP.
This commit is contained in:
@@ -6,11 +6,158 @@
|
||||
|
||||
namespace J3ML::LinearAlgebra
|
||||
{
|
||||
template <size_t DIMS, typename T>
|
||||
|
||||
template <size_t D, typename T>
|
||||
class Vector {
|
||||
static_assert(D > 1, "A vector cannot be of 1-dimension, it would be just a scalar!");
|
||||
public:
|
||||
enum { Dimensions = DIMS};
|
||||
T elems[DIMS];
|
||||
static constexpr bool IsAtLeast1D = D >= 1; // Should always be true for a proper vector.
|
||||
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 <jlog/Logger.hpp>
|
||||
#include <J3ML/LinearAlgebra/Matrix.hpp>
|
||||
#include <J3ML/LinearAlgebra/Vector.hpp>
|
||||
|
||||
|
||||
int main(int argc, char** argv)
|
||||
@@ -70,10 +71,25 @@ int main(int argc, char** argv)
|
||||
|
||||
auto C = A*B;
|
||||
|
||||
using Matrix2x3f = Matrix<2, 3, float>;
|
||||
|
||||
|
||||
std::cout << C << 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;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user