#pragma once #include "Core/public/Math/Boilerplate.h" #include "Core/public/Math/MathFwd.h" #include "Core/public/Math/Vector2.hpp" #ifndef MATRIX2_H #define MATRIX2_H namespace Phanes::Core::Math { // 2x2 Matrix defined in column-major order. // Accessed by M[Row][Col]. template struct TMatrix2 { public: union { struct { /// /// Column one. /// TVector2 c0; /// /// Column two /// TVector2 c1; }; T data[2][2]; }; public: TMatrix2() = default; /** * Copy constructor. */ TMatrix2(const TMatrix2& m1) { this->c0 = m1.c0; this->c1 = m1.c1; } /** * Construct Matrix from 2d array. * * @param(fields) 2D Array with column major order. */ TMatrix2(T fields[2][2]) { this->data[0][0] = fields[0][0]; this->data[1][0] = fields[1][0]; this->data[0][1] = fields[0][1]; this->data[1][1] = fields[1][1]; } /** * Construct Matrix from parameters. * * @param(n00) M[0][0] * @param(n10) M[1][0] * @param(n01) M[0][1] * @param(n11) M[1][1] * * @note nXY = n[Row][Col] */ TMatrix2(T n00, T n01, T n10, T n11) { this->data[0][0] = n00; this->data[1][0] = n01; this->data[0][1] = n10; this->data[1][1] = n11; } /** * Construct Matrix from two 2d vector columns. * * @param(v1) Column zero * @param(v2) Column one */ TMatrix2(const TVector2& v1, const TVector2& v2) { this->c0 = v1; this->c1 = v2; } public: T& operator() (int n, int m) { return this->data[m][n]; } T operator() (int n, int m) const { return this->data[m][n]; } TVector2& operator[] (int m) { switch (m) { case 0: return this->c0; case 1: return this->c1; } throw std::invalid_argument("m is outside valid range."); } TVector2 operator[] (int m) const { switch (m) { case 0: return this->c0; case 1: return this->c1; } throw std::invalid_argument("m is outside valid range."); } }; // ====================== // // TMatrix2 operator // // ====================== // template TMatrix2& operator+= (TMatrix2& m1, T s) { m1(0, 0) += s; m1(0, 1) += s; m1(1, 0) += s; m1(1, 1) += s; return m1; } template TMatrix2& operator+= (TMatrix2& m1, const TMatrix2& m2) { m1(0, 0) += m2(0, 0); m1(0, 1) += m2(0, 1); m1(1, 0) += m2(1, 0); m1(1, 1) += m2(1, 1); return m1; } template TMatrix2& operator-= (TMatrix2& m1, T s) { m1(0, 0) -= s; m1(0, 1) -= s; m1(1, 0) -= s; m1(1, 1) -= s; return m1; } template TMatrix2& operator-= (TMatrix2& m1, const TMatrix2& m2) { m1(0, 0) -= m2(0, 0); m1(0, 1) -= m2(0, 1); m1(1, 0) -= m2(1, 0); m1(1, 1) -= m2(1, 1); return m1; } template TMatrix2& operator*= (TMatrix2& m1, T s) { m1.data[0][0] *= s; m1.data[0][1] *= s; m1.data[1][0] *= s; m1.data[1][1] *= s; return m1; } template TMatrix2& operator*= (TMatrix2& m1, const TMatrix2& m2) { TMatrix2 c = m1; m1(0, 0) = c(0, 0) * m2(0, 0) + c(0, 1) * m2(1, 0); m1(0, 1) = c(0, 0) * m2(0, 1) + c(0, 1) * m2(1, 1); m1(1, 0) = c(1, 0) * m2(0, 0) + c(1, 1) * m2(1, 0); m1(1, 1) = c(1, 0) * m2(0, 1) + c(1, 1) * m2(1, 1); return m1; } template TMatrix2& operator/= (TMatrix2& m1, T s) { s = (T)1.0 / s; m1.data[0][0] *= s; m1.data[0][1] *= s; m1.data[1][0] *= s; m1.data[1][1] *= s; return m1; } template TMatrix2 operator+ (const TMatrix2& m1, T s) { return TMatrix2(m1(0, 0) + s, m1(0, 1) + s, m1(1, 0) + s, m1(1, 1) + s); } template TMatrix2 operator+ (const TMatrix2& m1, const TMatrix2& m2) { return TMatrix2(m1(0, 0) + m2(0, 0), m1(0, 1) + m2(0, 1), m1(1, 0) + m2(1, 0), m1(1, 1) + m2(1, 1)); } template TMatrix2 operator- (const TMatrix2& m1, T s) { return TMatrix2(m1(0, 0) - s, m1(0, 1) - s, m1(1, 0) - s, m1(1, 1) - s); } template TMatrix2 operator- (const TMatrix2& m1, const TMatrix2& m2) { return TMatrix2(m1(0, 0) - m2(0, 0), m1(0, 1) - m2(0, 1), m1(1, 0) - m2(1, 0), m1(1, 1) - m2(1, 1)); } template TMatrix2 operator* (const TMatrix2& m1, T s) { return TMatrix2(m1(0, 0) * s, m1(0, 1) * s, m1(1, 0) * s, m1(1, 1) * s); } template TMatrix2 operator/ (const TMatrix2& m1, T s) { s = (T)1.0 / s; return TMatrix2(m1(0, 0) * s, m1(0, 1) * s, m1(1, 0) * s, m1(1, 1) * s); } template TMatrix2 operator* (const TMatrix2& m1, const TMatrix2& m2) { return TMatrix2(m1(0, 0) * m2(0, 0) + m1(0, 1) * m2(1, 0), m1(0, 0) * m2(0, 1) + m1(0, 1) * m2(1, 1), m1(1, 0) * m2(0, 0) + m1(1, 1) * m2(1, 0), m1(1, 0) * m2(0, 1) + m1(1, 1) * m2(1, 1)); } template TVector2 operator* (const TMatrix2& m1, const TVector2& v) { return TVector2(m1(0, 0) * v.x + m1(0, 1) * v.y, m1(1, 0) * v.x + m1(1, 1) * v.y); } template bool operator== (const TMatrix2& m1, const TMatrix2& m2) { return m1[0] == m2[0] && m1[1] == m2[1]; } template bool operator!= (const TMatrix2& m1, const TMatrix2& m2) { return m1[0] != m2[0] || m1[1] != m2[1]; } // ============================== // // Matrix function definition // // ============================== // template T Determinant(const TMatrix2& m1) { return m1(0, 0) * m1(1, 1) - m1(0, 1) * m1(1, 0); } template TMatrix2& InverseV(TMatrix2& m1) { float _1_det = 1.0f / Determinant(m1); float m00 = m1(0, 0); m1(0, 0) = m1(1, 1); m1(0, 1) = -m1(0, 1); m1(1, 0) = -m1(1, 0); m1(1, 1) = m00; m1 *= _1_det; return m1; } template TMatrix2& TransposeV(TMatrix2& m1) { Swap(m1(0, 1), m1(1, 0)); return m1; } // =============== // // WITH RETURN // // =============== // template TMatrix2 Inverse(TMatrix2& m1) { float _1_det = 1.0f / Determinant(m1); return TMatrix2( m1(1, 1) * _1_det, -m1(0, 1) * _1_det, -m1(1, 0) * _1_det, m1(0, 0) * _1_det); } template TMatrix2 Transpose(const TMatrix2& m1) { return TMatrix2(m1(0, 0), m1(1, 0), m1(0, 1), m1(1, 1)); } template bool IsIdentityMatrix(const TMatrix2& m1, T threshold = P_FLT_INAC) { return (abs(m1(0, 0) - (T)1.0) < P_FLT_INAC && abs(m1(0, 1)) < P_FLT_INAC && abs(m1(1, 0)) < P_FLT_INAC && abs(m1(1, 1) - (T)1.0) < P_FLT_INAC); } } // Phanes::Core::Math #endif // !MATRIX2_H #include "Core/public/Math/SIMD/SIMDIntrinsics.h"