From: Akiko Date: Fri, 25 Oct 2013 10:39:27 +0000 (+0200) Subject: - fixed some small bugs X-Git-Url: http://community.linux-addicted.net/gitweb/?a=commitdiff_plain;h=70e774b3eee77f491b1789ee173006013cad3a7c;p=qtinns.git - fixed some small bugs - replaced default values by floats one (implicit converting from float to int is the better way) - added some missing operators and methods --- diff --git a/engine/Matrix.hxx b/engine/Matrix.hxx index e4c235c..186b481 100644 --- a/engine/Matrix.hxx +++ b/engine/Matrix.hxx @@ -8,9 +8,6 @@ * ~ Akiko ~ */ -#include -#include -#include #include "Vector.hxx" // --- generic forwarder --- @@ -23,7 +20,7 @@ class Matrix; template class Matrix { public: - // --- public data structures --- + // --- Generic Matrix: public data structures --- enum : size_t { columns = C, @@ -36,7 +33,7 @@ public: MT m[C][R]; }; - // --- constructors and deconstructors --- + // --- Generic Matrix: constructors and deconstructors --- Matrix() { @@ -59,7 +56,7 @@ public: { } - // --- default operators --- + // --- Generic Matrix: default operators --- Matrix& operator=(const Matrix& rhs) { @@ -104,9 +101,210 @@ public: return ml[cell]; } - // --- other operators --- + // --- Generic Matrix: other operators --- - // --- public methodes --- + Matrix& operator+=(const Matrix& rhs) + { + for (size_t cell = 0; cell < cells; ++cell) + ml[cell] += rhs.ml[cell]; + + return *this; + } + + template + Matrix& operator+=(const T& val) + { + static_assert (std::is_integral::value || std::is_floating_point::value, + "ERROR: template parameter is not an integral or floating point type"); + + for (size_t cell = 0; cell < cells; ++cell) + ml[cell] += val; + + return *this; + } + + Matrix operator+(const Matrix& rhs) const + { + Matrix mat(*this); + + for (size_t cell = 0; cell < cells; ++cell) + mat.ml[cell] += rhs.ml[cell]; + + return mat; + } + + template + Matrix operator+(const T& val) const + { + static_assert (std::is_integral::value || std::is_floating_point::value, + "ERROR: template parameter is not an integral or floating point type"); + + Matrix mat(*this); + + for (size_t cell = 0; cell < cells; ++cell) + mat.ml[cell] += val; + + return mat; + } + + // --- + + Matrix& operator-=(const Matrix& rhs) + { + for (size_t cell = 0; cell < cells; ++cell) + ml[cell] -= rhs.ml[cell]; + + return *this; + } + + template + Matrix& operator-=(const T& val) + { + static_assert (std::is_integral::value || std::is_floating_point::value, + "ERROR: template parameter is not an integral or floating point type"); + + for (size_t cell = 0; cell < cells; ++cell) + ml[cell] -= val; + + return *this; + } + + Matrix operator-(const Matrix& rhs) const + { + Matrix mat(*this); + + for (size_t cell = 0; cell < cells; ++cell) + mat.ml[cell] -= rhs.ml[cell]; + + return mat; + } + + template + Matrix operator-(const T& val) const + { + static_assert (std::is_integral::value || std::is_floating_point::value, + "ERROR: template parameter is not an integral or floating point type"); + + Matrix mat(*this); + + for (size_t cell = 0; cell < cells; ++cell) + mat.ml[cell] -= val; + + return *this; + } + + // --- + + // this one is very tricky, do not use it, it will fail in many ways + Matrix& operator*=(const Matrix& rhs) + { + const MT other_dim = columns; + Matrix mat(*this); + + for (size_t row = 0; row < rows; ++row) + { + for (size_t col = 0; col < columns; ++col) + { + MT sum = 0.0; + + for (size_t i = 0; i < other_dim; ++i) + sum += mat.m[i][row] * rhs.m[col][i]; + + mat.m[col][row] = sum; + } + } + *this = mat; + + return *this; + } + + template + Matrix& operator*=(const T& val) + { + static_assert (std::is_integral::value || std::is_floating_point::value, + "ERROR: template parameter is not an integral or floating point type"); + + for (size_t cell = 0; cell < cells; ++cell) + ml[cell] *= val; + + return *this; + } + + // this one is very tricky, do not use it, it will fail in many ways + Matrix operator*(const Matrix& rhs) const + { + const MT other_dim = columns; + Matrix mat(*this); + + for (size_t row = 0; row < rows; ++row) + { + for (size_t col = 0; col < columns; ++col) + { + MT sum = 0.0; + + for (size_t i = 0; i < other_dim; ++i) + sum += mat.m[i][row] * rhs.m[col][i]; + + mat.m[col][row] = sum; + } + } + + return mat; + } + + template + Matrix operator*(const T& val) const + { + static_assert (std::is_integral::value || std::is_floating_point::value, + "ERROR: template parameter is not an integral or floating point type"); + + Matrix mat(*this); + + for (size_t cell = 0; cell < cells; ++cell) + mat.ml[cell] *= val; + + return mat; + } + + // --- + + template + Matrix& operator/=(const T& val) + { + static_assert (std::is_integral::value || std::is_floating_point::value, + "ERROR: template parameter is not an integral or floating point type"); + + for (size_t cell = 0; cell < cells; ++cell) + ml[cell] /= val; + + return *this; + } + + template + Matrix operator/(const T& val) const + { + static_assert (std::is_integral::value || std::is_floating_point::value, + "ERROR: template parameter is not an integral or floating point type"); + + Matrix mat(*this); + + for (size_t cell = 0; cell < cells; ++cell) + mat.ml[cell] /= val; + + return mat; + } + + // --- Generic Matrix: public methodes --- + + template + void fill(const T& val) + { + static_assert (std::is_integral::value || std::is_floating_point::value, + "ERROR: template parameter is not an integral or floating point type"); + + for (size_t cell = 0; cell < cells; ++cell) + ml[cell] = val; + } bool isIdentity() const { @@ -143,14 +341,270 @@ public: } } } + + std::string string() const + { + std::stringstream result; + + result << "("; + for (size_t row = 0; row < rows; ++row) + { + result << "("; + for (size_t col = 0; col < columns; ++col) + { + result << m[col][row]; + if (col < (columns - 1)) + result << ", "; + } + result << ")"; + if (row < (rows - 1)) + result << ", "; + } + result << ")"; + + return result.str(); + } }; -// --- 4x4 matrix --- +// --- Generic Matrix: global operators --- + +template +bool operator==(const Matrix& mat1, const Matrix& mat2) +{ + static_assert (std::is_integral::value || std::is_floating_point::value, + "ERROR: template parameter is not an integral or floating point type"); + + bool result = true; + + for (size_t cell = 0; cell < (C * R); ++cell) + result = result && mat1.ml[cell] == mat2.ml[cell]; + + return result; +} + +template +bool operator!=(const Matrix& mat1, const Matrix& mat2) +{ + static_assert (std::is_integral::value || std::is_floating_point::value, + "ERROR: template parameter is not an integral or floating point type"); + + return !(mat1 == mat2); +} + +template +std::ostream& operator<<(std::ostream& lhs, const Matrix& rhs) +{ + static_assert (std::is_integral::value || std::is_floating_point::value, + "ERROR: template parameter is not an integral or floating point type"); + + for (size_t cell = 0; cell < (C * R); ++cell) + lhs << rhs.ml[cell]; + + return lhs; +} + +template +std::istream& operator<<(std::istream& lhs, Matrix& rhs) +{ + static_assert (std::is_integral::value || std::is_floating_point::value, + "ERROR: template parameter is not an integral or floating point type"); + + for (size_t cell = 0; cell < (C * R); ++cell) + lhs >> rhs.ml[cell]; + + return lhs; +} + +// --- + +template +Matrix operator+(const Matrix& mat1, const Matrix& mat2) +{ + static_assert (std::is_integral::value || std::is_floating_point::value, + "ERROR: template parameter is not an integral or floating point type"); + + Matrix mat(mat1); + + for (size_t cell = 0; cell < mat.cells; ++cell) + mat.ml[cell] += mat2.ml[cell]; + + return mat; +} + +template +Matrix operator+(const Matrix& mat, const Val& val) +{ + static_assert (std::is_integral::value || std::is_floating_point::value || + std::is_integral::value || std::is_floating_point::value, + "ERROR: template parameter is not an integral or floating point type"); + + Matrix m(mat); + + for (size_t cell = 0; cell < m.cells; ++cell) + m.ml[cell] += val; + + return m; +} + +template +Matrix operator+(const Val& val, const Matrix& mat) +{ + static_assert (std::is_integral::value || std::is_floating_point::value || + std::is_integral::value || std::is_floating_point::value, + "ERROR: template parameter is not an integral or floating point type"); + + Matrix m; + + for (size_t cell = 0; cell < m.cells; ++cell) + m.ml[cell] = val + mat.ml[cell]; + + return m; +} + +// --- + +template +Matrix operator-(const Matrix& mat1, const Matrix& mat2) +{ + static_assert (std::is_integral::value || std::is_floating_point::value, + "ERROR: template parameter is not an integral or floating point type"); + + Matrix mat(mat1); + + for (size_t cell = 0; cell < mat.cells; ++cell) + mat.ml[cell] -= mat2.ml[cell]; + + return mat; +} + +template +Matrix operator-(const Matrix& mat, const Val& val) +{ + static_assert (std::is_integral::value || std::is_floating_point::value || + std::is_integral::value || std::is_floating_point::value, + "ERROR: template parameter is not an integral or floating point type"); + + Matrix m(mat); + + for (size_t cell = 0; cell < m.cells; ++cell) + m.ml[cell] -= val; + + return m; +} + +template +Matrix operator-(const Val& val, const Matrix& mat) +{ + static_assert (std::is_integral::value || std::is_floating_point::value || + std::is_integral::value || std::is_floating_point::value, + "ERROR: template parameter is not an integral or floating point type"); + + Matrix m; + + for (size_t cell = 0; cell < m.cells; ++cell) + m.ml[cell] = val - mat.ml[cell]; + + return m; +} + +// --- + +// this one is very tricky, do not use it, it will fail in many ways +template +Matrix operator*(const Matrix& mat1, const Matrix& mat2) +{ + static_assert (std::is_integral::value || std::is_floating_point::value, + "ERROR: template parameter is not an integral or floating point type"); + + const T other_dim = C * R; + Matrix mat; + + for (size_t row = 0; row < mat.rows; ++row) + { + for (size_t col = 0; col < mat.columns; ++col) + { + T sum = 0.0; + + for (size_t i = 0; i < other_dim; ++i) + sum += mat1.m[i][row] * mat2.m[col][i]; + + mat.m[col][row] = sum; + } + } + + return mat; +} + +template +Matrix operator*(const Matrix& mat, const Val& val) +{ + static_assert (std::is_integral::value || std::is_floating_point::value || + std::is_integral::value || std::is_floating_point::value, + "ERROR: template parameter is not an integral or floating point type"); + + Matrix m(mat); + + for (size_t cell = 0; cell < mat.cells; ++cell) + m.ml[cell] *= val; + + return m; +} + +template +Matrix operator*(const Val& val, const Matrix& mat) +{ + static_assert (std::is_integral::value || std::is_floating_point::value || + std::is_integral::value || std::is_floating_point::value, + "ERROR: template parameter is not an integral or floating point type"); + + Matrix m; + + for (size_t cell = 0; cell < m.cells; ++cell) + m.ml[cell] = val * mat.ml[cell]; + + return m; +} + +// --- + +template +Matrix operator/(const Matrix& mat, const Val& val) +{ + static_assert (std::is_integral::value || std::is_floating_point::value || + std::is_integral::value || std::is_floating_point::value, + "ERROR: template parameter is not an integral or floating point type"); + + Matrix m(mat); + + for (size_t cell = 0; cell < m.cells; ++cell) + m.ml[cell] /= val; + + return m; +} + +template +Matrix operator/(const Val& val, const Matrix& mat) +{ + static_assert (std::is_integral::value || std::is_floating_point::value || + std::is_integral::value || std::is_floating_point::value, + "ERROR: template parameter is not an integral or floating point type"); + + Matrix m; + + for (size_t cell = 0; cell < m.cells; ++cell) + m.ml[cell] = val / mat.ml[cell]; + + return m; +} + + + +// --- Matrix 4x4 --- template class Matrix { public: - // --- public constants --- + // --- Matrix 4x4: public constants --- enum : size_t { columns = 4, @@ -158,7 +612,7 @@ public: cells = 4 * 4 }; - // --- public data structures --- + // --- Matrix 4x4: public data structures --- alignas (16) union { struct { @@ -171,14 +625,14 @@ public: MT ml[cells]; }; - // --- constructors and deconstructors --- + // --- Matrix 4x4: constructors and deconstructors --- // default is an identity matrix Matrix() - : ml{1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1} + : ml{1.0, 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0, 0.0, + 0.0, 0.0, 1.0, 0.0, + 0.0, 0.0, 0.0, 1.0} { } @@ -237,7 +691,7 @@ public: { } - // --- default operators --- + // --- Matrix 4x4: default operators --- Matrix& operator=(const Matrix& rhs) { @@ -296,7 +750,7 @@ public: -m14, -m24, -m34, -m44}; } - // --- other operators --- + // --- Matrix 4x4: other operators --- Matrix& operator+=(const Matrix& rhs) { @@ -371,6 +825,9 @@ public: template Matrix operator-(const T& val) const { + static_assert (std::is_integral::value || std::is_floating_point::value, + "ERROR: template parameter is not an integral or floating point type"); + return {m11 - val, m21 - val, m31 - val, m41 - val, m12 - val, m22 - val, m32 - val, m42 - val, m13 - val, m23 - val, m33 - val, m43 - val, @@ -493,7 +950,7 @@ public: m14 / val, m24 / val, m34 / val, m44 / val}; } - // --- public methods --- + // --- Matrix 4x4: public methods --- Vector4 column(const size_t& index) const { @@ -508,16 +965,19 @@ public: template void fill(const T& val) { + static_assert (std::is_integral::value || std::is_floating_point::value, + "ERROR: template parameter is not an integral or floating point type"); + for (size_t cell = 0; cell < cells; ++cell) ml[cell] = val; } void inverte(bool& invertible) { - Matrix im(0); + Matrix im(0.0); MT det = determinant(m); - if (det == static_cast(0)) + if (det == 0.0) { invertible = false; *this == Matrix(); // identity @@ -525,7 +985,7 @@ public: return; } - det = static_cast(1) / det; + det = 1.0 / det; invertible = true; im.m11 = determinant33(m, 1, 2, 3, 1, 2, 3) * det; @@ -589,18 +1049,18 @@ public: } protected: - // --- protected methods --- + // --- Matrix 4x4: protected methods --- constexpr MT determinant22(const MT mm[4][4], - const size_t& col1, const size_t& col2, - const size_t& row1, const size_t& row2) const + const size_t& col1, const size_t& col2, + const size_t& row1, const size_t& row2) const { return mm[col1][row1] * mm[col2][row2] - mm[col1][row2] * mm[col2][row1]; } constexpr MT determinant33(const MT mm[4][4], - const size_t& col1, const size_t& col2, const size_t& col3, - const size_t& row1, const size_t& row2, const size_t& row3) const + const size_t& col1, const size_t& col2, const size_t& col3, + const size_t& row1, const size_t& row2, const size_t& row3) const { return mm[col1][row1] * determinant22(mm, col2, col3, row2, row3) - mm[col2][row1] * determinant22(mm, col1, col3, row2, row3) + @@ -615,3 +1075,217 @@ protected: mm[3][0] * determinant33(mm, 0, 1, 2, 1, 2, 3); } }; + +// --- Matrix 4x4: global operators --- + +template +bool operator==(const Matrix& lhs, const Matrix& rhs) +{ + static_assert (std::is_integral::value || std::is_floating_point::value, + "ERROR: template parameter is not an integral or floating point type"); + + return lhs.m11 == rhs.m11 && lhs.m21 == rhs.m21 && lhs.m31 == rhs.m31 && lhs.m41 == rhs.m41 && + lhs.m12 == rhs.m12 && lhs.m22 == rhs.m22 && lhs.m32 == rhs.m32 && lhs.m42 == rhs.m42 && + lhs.m13 == rhs.m13 && lhs.m23 == rhs.m23 && lhs.m33 == rhs.m33 && lhs.m43 == rhs.m43 && + lhs.m14 == rhs.m14 && lhs.m24 == rhs.m24 && lhs.m34 == rhs.m34 && lhs.m44 == rhs.m44; +} + +template +bool operator!=(const Matrix& lhs, const Matrix& rhs) +{ + static_assert (std::is_integral::value || std::is_floating_point::value, + "ERROR: template parameter is not an integral or floating point type"); + + return !(lhs == rhs); +} + +template +std::ostream& operator<<(std::ostream& lhs, const Matrix& rhs) +{ + static_assert (std::is_integral::value || std::is_floating_point::value, + "ERROR: template parameter is not an integral or floating point type"); + + lhs << rhs.m11 << rhs.m21 << rhs.m31 << rhs.m41 + << rhs.m12 << rhs.m22 << rhs.m32 << rhs.m42 + << rhs.m13 << rhs.m23 << rhs.m33 << rhs.m43 + << rhs.m14 << rhs.m24 << rhs.m34 << rhs.m44; + + return lhs; +} + +template +std::istream& operator>>(std::istream& lhs, Matrix& rhs) +{ + static_assert (std::is_integral::value || std::is_floating_point::value, + "ERROR: template parameter is not an integral or floating point type"); + + lhs >> rhs.m11 >> rhs.m21 >> rhs.m31 >> rhs.m41 + >> rhs.m12 >> rhs.m22 >> rhs.m32 >> rhs.m42 + >> rhs.m13 >> rhs.m23 >> rhs.m33 >> rhs.m43 + >> rhs.m14 >> rhs.m24 >> rhs.m34 >> rhs.m44; + + return lhs; +} + +// --- + +template +Matrix operator+(const Matrix& mat1, const Matrix& mat2) +{ + static_assert (std::is_integral::value || std::is_floating_point::value, + "ERROR: template parameter is not an integral or floating point type"); + + return {mat1.m11 + mat2.m11, mat1.m21 + mat2.m21, mat1.m31 + mat2.m31, mat1.m41 + mat2.m41, + mat1.m12 + mat2.m12, mat1.m22 + mat2.m22, mat1.m32 + mat2.m32, mat1.m42 + mat2.m42, + mat1.m13 + mat2.m13, mat1.m23 + mat2.m23, mat1.m33 + mat2.m33, mat1.m43 + mat2.m43, + mat1.m14 + mat2.m14, mat1.m24 + mat2.m24, mat1.m34 + mat2.m34, mat1.m44 + mat2.m44}; +} + +template +Matrix operator+(const Matrix& mat, const Val& val) +{ + static_assert (std::is_integral::value || std::is_floating_point::value || + std::is_integral::value || std::is_floating_point::value, + "ERROR: template parameter is not an integral or floating point type"); + + return {mat.m11 + val, mat.m21 + val, mat.m31 + val, mat.m41 + val, + mat.m12 + val, mat.m22 + val, mat.m32 + val, mat.m42 + val, + mat.m13 + val, mat.m23 + val, mat.m33 + val, mat.m43 + val, + mat.m14 + val, mat.m24 + val, mat.m34 + val, mat.m44 + val}; +} + +template +Matrix operator+(const Val& val, const Matrix& mat) +{ + static_assert (std::is_integral::value || std::is_floating_point::value || + std::is_integral::value || std::is_floating_point::value, + "ERROR: template parameter is not an integral or floating point type"); + + return {val + mat.m11, val + mat.m21, val + mat.m31, val + mat.m41, + val + mat.m12, val + mat.m22, val + mat.m32, val + mat.m42, + val + mat.m13, val + mat.m23, val + mat.m33, val + mat.m43, + val + mat.m14, val + mat.m24, val + mat.m34, val + mat.m44}; +} + +// --- + +template +Matrix operator-(const Matrix& mat1, const Matrix& mat2) +{ + static_assert (std::is_integral::value || std::is_floating_point::value, + "ERROR: template parameter is not an integral or floating point type"); + + return {mat1.m11 - mat2.m11, mat1.m21 - mat2.m21, mat1.m31 - mat2.m31, mat1.m41 - mat2.m41, + mat1.m12 - mat2.m12, mat1.m22 - mat2.m22, mat1.m32 - mat2.m32, mat1.m42 - mat2.m42, + mat1.m13 - mat2.m13, mat1.m23 - mat2.m23, mat1.m33 - mat2.m33, mat1.m43 - mat2.m43, + mat1.m14 - mat2.m14, mat1.m24 - mat2.m24, mat1.m34 - mat2.m34, mat1.m44 - mat2.m44}; +} + +template +Matrix operator-(const Matrix& mat, const Val& val) +{ + static_assert (std::is_integral::value || std::is_floating_point::value || + std::is_integral::value || std::is_floating_point::value, + "ERROR: template parameter is not an integral or floating point type"); + + return {mat.m11 - val, mat.m21 - val, mat.m31 - val, mat.m41 - val, + mat.m12 - val, mat.m22 - val, mat.m32 - val, mat.m42 - val, + mat.m13 - val, mat.m23 - val, mat.m33 - val, mat.m43 - val, + mat.m14 - val, mat.m24 - val, mat.m34 - val, mat.m44 - val}; +} + +template +Matrix operator-(const Val& val, const Matrix& mat) +{ + static_assert (std::is_integral::value || std::is_floating_point::value || + std::is_integral::value || std::is_floating_point::value, + "ERROR: template parameter is not an integral or floating point type"); + + return {val - mat.m11, val - mat.m21, val - mat.m31, val - mat.m41, + val - mat.m12, val - mat.m22, val - mat.m32, val - mat.m42, + val - mat.m13, val - mat.m23, val - mat.m33, val - mat.m43, + val - mat.m14, val - mat.m24, val - mat.m34, val - mat.m44}; +} + +// --- + +template +Matrix operator*(const Matrix& mat1, const Matrix& mat2) +{ + static_assert (std::is_integral::value || std::is_floating_point::value, + "ERROR: template parameter is not an integral or floating point type"); + + return {mat1.m11 * mat2.m11 + mat1.m21 * mat2.m12 + mat1.m31 * mat2.m13 + mat1.m41 * mat2.m14, + mat1.m11 * mat2.m21 + mat1.m21 * mat2.m22 + mat1.m31 * mat2.m23 + mat1.m41 * mat2.m24, + mat1.m11 * mat2.m31 + mat1.m21 * mat2.m32 + mat1.m31 * mat2.m33 + mat1.m41 * mat2.m34, + mat1.m11 * mat2.m41 + mat1.m21 * mat2.m42 + mat1.m31 * mat2.m43 + mat1.m41 * mat2.m44, + + mat1.m12 * mat2.m11 + mat1.m22 * mat2.m12 + mat1.m32 * mat2.m13 + mat1.m42 * mat2.m14, + mat1.m12 * mat2.m21 + mat1.m22 * mat2.m22 + mat1.m32 * mat2.m23 + mat1.m42 * mat2.m24, + mat1.m12 * mat2.m31 + mat1.m22 * mat2.m32 + mat1.m32 * mat2.m33 + mat1.m42 * mat2.m34, + mat1.m12 * mat2.m41 + mat1.m22 * mat2.m42 + mat1.m32 * mat2.m43 + mat1.m42 * mat2.m44, + + mat1.m13 * mat2.m11 + mat1.m23 * mat2.m12 + mat1.m33 * mat2.m13 + mat1.m43 * mat2.m14, + mat1.m13 * mat2.m21 + mat1.m23 * mat2.m22 + mat1.m33 * mat2.m23 + mat1.m43 * mat2.m24, + mat1.m13 * mat2.m31 + mat1.m23 * mat2.m32 + mat1.m33 * mat2.m33 + mat1.m43 * mat2.m34, + mat1.m13 * mat2.m41 + mat1.m23 * mat2.m42 + mat1.m33 * mat2.m43 + mat1.m43 * mat2.m44, + + mat1.m14 * mat2.m11 + mat1.m24 * mat2.m12 + mat1.m34 * mat2.m13 + mat1.m44 * mat2.m14, + mat1.m14 * mat2.m21 + mat1.m24 * mat2.m22 + mat1.m34 * mat2.m23 + mat1.m44 * mat2.m24, + mat1.m14 * mat2.m31 + mat1.m24 * mat2.m32 + mat1.m34 * mat2.m33 + mat1.m44 * mat2.m34, + mat1.m14 * mat2.m41 + mat1.m24 * mat2.m42 + mat1.m34 * mat2.m43 + mat1.m44 * mat2.m44}; +} + +template +Matrix operator*(const Matrix& mat, const Val& val) +{ + static_assert (std::is_integral::value || std::is_floating_point::value || + std::is_integral::value || std::is_floating_point::value, + "ERROR: template parameter is not an integral or floating point type"); + + return {mat.m11 * val, mat.m21 * val, mat.m31 * val, mat.m41 * val, + mat.m12 * val, mat.m22 * val, mat.m32 * val, mat.m42 * val, + mat.m13 * val, mat.m23 * val, mat.m33 * val, mat.m43 * val, + mat.m14 * val, mat.m24 * val, mat.m34 * val, mat.m44 * val}; +} + +template +Matrix operator*(const Val& val, const Matrix& mat) +{ + static_assert (std::is_integral::value || std::is_floating_point::value || + std::is_integral::value || std::is_floating_point::value, + "ERROR: template parameter is not an integral or floating point type"); + + return {val * mat.m11, val * mat.m21, val * mat.m31, val * mat.m41, + val * mat.m12, val * mat.m22, val * mat.m32, val * mat.m42, + val * mat.m13, val * mat.m23, val * mat.m33, val * mat.m43, + val * mat.m14, val * mat.m24, val * mat.m34, val * mat.m44}; +} + +// --- + +template +Matrix operator/(const Matrix& mat, const Val& val) +{ + static_assert (std::is_integral::value || std::is_floating_point::value || + std::is_integral::value || std::is_floating_point::value, + "ERROR: template parameter is not an integral or floating point type"); + + return {mat.m11 / val, mat.m21 / val, mat.m31 / val, mat.m41 / val, + mat.m12 / val, mat.m22 / val, mat.m32 / val, mat.m42 / val, + mat.m13 / val, mat.m23 / val, mat.m33 / val, mat.m43 / val, + mat.m14 / val, mat.m24 / val, mat.m34 / val, mat.m44 / val}; +} + +template +Matrix operator/(const Val& val, const Matrix& mat) +{ + static_assert (std::is_integral::value || std::is_floating_point::value || + std::is_integral::value || std::is_floating_point::value, + "ERROR: template parameter is not an integral or floating point type"); + + return {val / mat.m11, val / mat.m21, val / mat.m31, val / mat.m41, + val / mat.m12, val / mat.m22, val / mat.m32, val / mat.m42, + val / mat.m13, val / mat.m23, val / mat.m33, val / mat.m43, + val / mat.m14, val / mat.m24, val / mat.m34, val / mat.m44}; +}