Created
April 9, 2025 13:22
-
-
Save TheBlackPlague/9f44f1993238730e5466bb8a7d7c8b3d to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // | |
| // 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