Skip to content

Instantly share code, notes, and snippets.

@TheBlackPlague
Created April 9, 2025 13:22
Show Gist options
  • Select an option

  • Save TheBlackPlague/9f44f1993238730e5466bb8a7d7c8b3d to your computer and use it in GitHub Desktop.

Select an option

Save TheBlackPlague/9f44f1993238730e5466bb8a7d7c8b3d to your computer and use it in GitHub Desktop.
//
// Copyright (c) 2025 Keplerium authors. See the list of authors for more details.
// Licensed under MIT.
//
#ifndef VECTOR_H
#define VECTOR_H
#include <array>
#include "../FixedType.h"
#include "Random.h"
template<typename E, FloatingPoint T, size_t N>
struct EVector
{
const E& Self() const
{
return static_cast<const E&>(*this);
}
T operator[](size_t idx) const
{
return Self()[idx];
}
T Norm2() const
{
return Dot(Self(), Self());
}
T Norm() const
{
return std::sqrt(Norm2());
}
};
template<typename E, FloatingPoint T, size_t N>
std::ostream& operator <<(std::ostream& os, const EVector<E, T, N>& e)
{
os << '<';
for (size_t i = 0; i < N; i++) {
os << e.Self()[i];
if (i < N - 1) os << ", ";
}
os << '>';
return os;
}
template<FloatingPoint T, size_t N, bool Enable = N >= 1>
struct XComponent {};
template<FloatingPoint T, size_t N>
struct XComponent<T, N, true>
{
T& X;
explicit XComponent(T& x) : X(x) {}
};
template<FloatingPoint T, size_t N, bool Enable = N >= 2>
struct YComponent {};
template<FloatingPoint T, size_t N>
struct YComponent<T, N, true>
{
T& Y;
explicit YComponent(T& y) : Y(y) {}
};
template<FloatingPoint T, size_t N, bool Enable = N >= 3>
struct ZComponent {};
template<FloatingPoint T, size_t N>
struct ZComponent<T, N, true>
{
T& Z;
explicit ZComponent(T& z) : Z(z) {}
};
template<FloatingPoint T, size_t N>
struct VectorComponent
{
protected:
std::array<T, N> Component;
public:
VectorComponent() : Component {} {}
};
template<FloatingPoint T, size_t N>
struct Vector : VectorComponent<T, N>, XComponent<T, N>, YComponent<T, N>, ZComponent<T, N>, EVector<Vector<T, N>, T, N>
{
Vector() :
XComponent<T, N>(this->Component[0]),
YComponent<T, N>(this->Component[1]),
ZComponent<T, N>(this->Component[2])
{}
template<typename E>
Vector(const EVector<E, T, N>& e) :
XComponent<T, N>(this->Component[0]),
YComponent<T, N>(this->Component[1]),
ZComponent<T, N>(this->Component[2])
{
for (size_t i = 0; i < N; i++) this->Component[i] = e[i];
}
template<FloatingPoint ... Ts, typename = std::enable_if_t<sizeof ... (Ts) == N>>
Vector(const Ts ... args) :
XComponent<T, N>(this->Component[0]),
YComponent<T, N>(this->Component[1]),
ZComponent<T, N>(this->Component[2])
{
this->Component = { static_cast<T>(args) ... };
}
template<typename E>
Vector& operator =(const EVector<E, T, N>& e)
{
for (size_t i = 0; i < N; i++) this->Component[i] = e[i];
return *this;
}
Vector& operator =(const Vector& v)
{
for (size_t i = 0; i < N; i++) this->Component[i] = v[i];
return *this;
}
T& operator [](size_t idx)
{
return this->Component[idx];
}
T operator [](size_t idx) const
{
return this->Component[idx];
}
static Vector Random()
{
Vector result;
result.Component = ::random<T, N>();
return result;
}
};
template<typename E1, typename E2, FloatingPoint T, size_t N>
struct EVectorAddE : EVector<EVectorAddE<E1, E2, T, N>, T, N>
{
private:
const E1 u;
const E2 v;
public:
EVectorAddE(const E1&& u, const E2&& v) : u(std::move(u)), v(std::move(v)) {}
T operator [](size_t idx) const
{
return u[idx] + v[idx];
}
};
template<typename E1, typename E2, FloatingPoint T, size_t N>
EVectorAddE<E1, E2, T, N> operator +(const EVector<E1, T, N>& u, const EVector<E2, T, N>& v)
{
return EVectorAddE<E1, E2, T, N>(std::move(u.Self()), std::move(v.Self()));
}
template<typename E, FloatingPoint T, size_t N>
struct EVectorAddS : EVector<EVectorAddS<E, T, N>, T, N>
{
private:
const E u;
const T v;
public:
EVectorAddS(const E&& u, const T s) : u(std::move(u)), v(s) {}
T operator [](size_t idx) const
{
return u[idx] + v;
}
};
template<typename E, FloatingPoint T1, Arithmetic T2, size_t N>
EVectorAddS<E, T1, N> operator +(const EVector<E, T1, N>& u, T2 s)
{
return EVectorAddS<E, T1, N>(std::move(u.Self()), static_cast<T1>(s));
}
template<typename E, FloatingPoint T, size_t N>
struct EVectorNegE : EVector<EVectorNegE<E, T, N>, T, N>
{
private:
const E u;
public:
EVectorNegE(const E&& u) : u(std::move(u)) {}
T operator [](size_t idx) const
{
return -u[idx];
}
};
template<typename E, FloatingPoint T, size_t N>
EVectorNegE<E, T, N> operator -(const EVector<E, T, N>& u)
{
return EVectorNegE<E, T, N>(std::move(u.Self()));
}
template<typename E1, typename E2, FloatingPoint T, size_t N>
EVectorAddE<E1, EVectorNegE<E2, T, N>, T, N> operator -(const EVector<E1, T, N>& u, const EVector<E2, T, N>& v)
{
return u + -v;
}
template<typename E, FloatingPoint T1, Arithmetic T2, size_t N>
EVectorAddS<E, T1, N> operator -(const EVector<E, T1, N>& u, const T2 s)
{
return EVectorAddS<E, T1, N>(std::move(u.Self()), static_cast<T1>(-s));
}
template<typename E1, typename E2, FloatingPoint T, size_t N>
struct EVectorProductE : EVector<EVectorProductE<E1, E2, T, N>, T, N>
{
private:
const E1 u;
const E2 v;
public:
EVectorProductE(const E1&& u, const E2&& v) : u(std::move(u)), v(std::move(v)) {}
T operator [](size_t idx) const
{
return u[idx] * v[idx];
}
};
template<typename E1, typename E2, FloatingPoint T, size_t N>
EVectorProductE<E1, E2, T, N> operator *(const EVector<E1, T, N>& u, const EVector<E2, T, N>& v)
{
return EVectorProductE<E1, E2, T, N>(std::move(u.Self()), std::move(v.Self()));
}
template<typename E, FloatingPoint T, size_t N>
struct EVectorProductS : EVector<EVectorProductS<E, T, N>, T, N>
{
private:
const E u;
const T v;
public:
EVectorProductS(const E&& u, const T s) : u(std::move(u)), v(s) {}
T operator [](size_t idx) const
{
return u[idx] * v;
}
};
template<typename E, FloatingPoint T1, Arithmetic T2, size_t N>
EVectorProductS<E, T1, N> operator *(const EVector<E, T1, N>& u, const T2 s)
{
return EVectorProductS<E, T1, N>(std::move(u.Self()), static_cast<T1>(s));
}
template<typename E1, typename E2, FloatingPoint T, size_t N>
struct EVectorQuotientE : EVector<EVectorQuotientE<E1, E2, T, N>, T, N>
{
private:
const E1 u;
const E2 v;
public:
EVectorQuotientE(const E1&& u, const E2&& v) : u(std::move(u)), v(std::move(v)) {}
T operator [](size_t idx) const
{
return u[idx] / v[idx];
}
};
template<typename E1, typename E2, FloatingPoint T, size_t N>
EVectorQuotientE<E1, E2, T, N> operator /(const EVector<E1, T, N>& u, const EVector<E2, T, N>& v)
{
return EVectorQuotientE<E1, E2, T, N>(std::move(u.Self()), std::move(v.Self()));
}
template<typename E, FloatingPoint T, size_t N>
struct EVectorQuotientS : EVector<EVectorQuotientS<E, T, N>, T, N>
{
private:
const E u;
const T v;
public:
EVectorQuotientS(const E&& u, const T s) : u(std::move(u)), v(s) {}
T operator [](size_t idx) const
{
return u[idx] / v;
}
};
template<typename E, FloatingPoint T1, Arithmetic T2, size_t N>
EVectorQuotientS<E, T1, N> operator /(const EVector<E, T1, N>& u, const T2 s)
{
return EVectorQuotientS<E, T1, N>(std::move(u.Self()), static_cast<T1>(s));
}
template<typename E1, typename E2, FloatingPoint T, size_t N>
T Dot(const EVector<E1, T, N>& u, const EVector<E2, T, N>& v)
{
const EVectorProductE<E1, E2, T, N> product = u * v;
T result = 0;
for (size_t i = 0; i < N; i++) result += product[i];
return result;
}
#endif //VECTOR_H
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment