diff --git a/CMakeLists.txt b/CMakeLists.txt index 13f3b2b..94471d9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -102,6 +102,10 @@ add_library(fennec STATIC include/fennec/math/detail/__vector_traits.h source/debug/assert_impl.cpp + include/fennec/math/detail/__math.h + include/fennec/lang/detail/__int.h + include/fennec/lang/detail/__stdlib.h + include/fennec/math/detail/__matrix.h ) # add metaprogramming templates as a dependency and also force documentation to be generated when fennec is compiled diff --git a/include/fennec/lang/detail/__int.h b/include/fennec/lang/detail/__int.h new file mode 100644 index 0000000..35c8170 --- /dev/null +++ b/include/fennec/lang/detail/__int.h @@ -0,0 +1,27 @@ +// ===================================================================================================================== +// fennec, a free and open source game engine +// Copyright © 2025 Medusa Slockbower +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// ===================================================================================================================== + +#ifndef FENNEC_LANG_DETAIL_INT_H +#define FENNEC_LANG_DETAIL_INT_H + +#pragma push_macro("__cplusplus") +#undef __cplusplus +#include +#pragma pop_macro("__cplusplus") + +#endif // FENNEC_LANG_DETAIL_INT_H diff --git a/include/fennec/lang/detail/__stdlib.h b/include/fennec/lang/detail/__stdlib.h new file mode 100644 index 0000000..1545475 --- /dev/null +++ b/include/fennec/lang/detail/__stdlib.h @@ -0,0 +1,29 @@ +// ===================================================================================================================== +// fennec, a free and open source game engine +// Copyright © 2025 Medusa Slockbower +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// ===================================================================================================================== + +#ifndef FENNEC_LANG_DETAIL_STDLIB_H +#define FENNEC_LANG_DETAIL_STDLIB_H + +#pragma push_macro("__cplusplus") +#undef __cplusplus +extern "C" { +#include +} +#pragma pop_macro("__cplusplus") + +#endif // FENNEC_LANG_DETAIL_STDLIB_H diff --git a/include/fennec/lang/limits.h b/include/fennec/lang/limits.h index deca9ed..89c7b13 100644 --- a/include/fennec/lang/limits.h +++ b/include/fennec/lang/limits.h @@ -201,8 +201,6 @@ /// /// -#include - #include #include diff --git a/include/fennec/lang/sequences.h b/include/fennec/lang/sequences.h index 3a68b95..60930fd 100644 --- a/include/fennec/lang/sequences.h +++ b/include/fennec/lang/sequences.h @@ -203,23 +203,23 @@ template using concat_sequence_t // Internal ============================================================================================================ -// Implementation for Generating an \ref integer_sequence +// Implementation for Generating an integer_sequence template struct make_integer_sequence : concat_sequence_t, make_integer_sequence_t>{}; -// Base Case of \f$N=0\f$ +// Base Case of N=0 template struct make_integer_sequence : integer_sequence {}; -// Base Case of \f$N=1\f$ +// Base Case of N=1 template struct make_integer_sequence : integer_sequence{}; -// Implementation for Generating an \ref integer_sequence +// Implementation for Generating an index_sequence template struct make_index_sequence : concat_sequence_t, make_index_sequence_t>{}; -// Base Case of \f$N=0\f$ +// Base Case of N=0 template<> struct make_index_sequence<0> : index_sequence<> {}; -// Base Case of \f$N=1\f$ +// Base Case of N=1 template<> struct make_index_sequence<1> : index_sequence<0>{}; diff --git a/include/fennec/lang/types.h b/include/fennec/lang/types.h index 700bed6..78b0dd7 100644 --- a/include/fennec/lang/types.h +++ b/include/fennec/lang/types.h @@ -215,7 +215,7 @@ /// /// -#include +#include namespace fennec { diff --git a/include/fennec/lang/utility.h b/include/fennec/lang/utility.h index 24da281..2c3023f 100644 --- a/include/fennec/lang/utility.h +++ b/include/fennec/lang/utility.h @@ -72,10 +72,10 @@ namespace fennec /// \tparam T base type of the object /// \param x reference to the object /// \returns -template constexpr T&& forward(remove_reference_t& x) noexcept { return x; } +template constexpr T&& forward(remove_reference_t& x) noexcept { return static_cast(x); } // specialization for T&& -template constexpr T&& forward(remove_reference_t&& x) noexcept { return x; } +template constexpr T&& forward(remove_reference_t&& x) noexcept { return static_cast(x); } /// diff --git a/include/fennec/math/common.h b/include/fennec/math/common.h index 19daa1b..34e5ffa 100644 --- a/include/fennec/math/common.h +++ b/include/fennec/math/common.h @@ -274,8 +274,7 @@ /// /// - -#include +#include #include @@ -357,7 +356,7 @@ constexpr vector sign(const vector& x) /// \param x input value template constexpr genType floor(genType x) - { return std::floor(x); } + { return ::floor(x); } // Vector Specializations ---------------------------------------------------------------------------------------------- @@ -380,7 +379,7 @@ constexpr vector floor(const vector& x) /// \param x input value template constexpr genType ceil(genType x) - { return std::ceil(x); } + { return ::ceil(x); } // Vector Specializations ---------------------------------------------------------------------------------------------- @@ -403,7 +402,7 @@ constexpr vector ceil(const vector& x) /// /// \param x input value template constexpr genType round(genType x) - { return std::round(x); } + { return ::round(x); } // Vector Specializations ---------------------------------------------------------------------------------------------- @@ -451,7 +450,7 @@ constexpr vector roundEven(const vector& x) /// \param x input value template constexpr genType trunc(genType x) - { return std::trunc(x); } + { return ::trunc(x); } // Vector Specializations ---------------------------------------------------------------------------------------------- @@ -482,7 +481,7 @@ constexpr vector trunc(const vector& x) /// \param x input value template constexpr genType fract(genType x) - { return x - std::floor(x); } + { return x - ::floor(x); } // Vector Specializations ---------------------------------------------------------------------------------------------- @@ -534,7 +533,7 @@ constexpr vector mod(const vector& x, const vector /// \param i integral out template constexpr genType modf(genType x, genType& i) - { return std::modf(x, &i); } + { return ::modf(x, &i); } // Vector Specializations ---------------------------------------------------------------------------------------------- @@ -562,7 +561,7 @@ constexpr vector modf(const vector& x, vector requires(is_bool_v) constexpr genBType isnan(genType x) - { return std::isnan(x); } + { return ::isnan(x); } // Vector Specializations ---------------------------------------------------------------------------------------------- @@ -585,7 +584,7 @@ constexpr vector isnan(const vector& x) /// \param x input value template requires(is_bool_v) constexpr genBType isinf(genType x) - { return std::isinf(x); } + { return ::isinf(x); } // Vector Specializations ---------------------------------------------------------------------------------------------- @@ -684,7 +683,7 @@ constexpr vector uintBitsToFloat(const vector& x) /// \param c the addend template constexpr genType fma(genType a, genType b, genType c) - { return std::fma(a, b, c); } + { return ::fma(a, b, c); } // Vector Specializations ---------------------------------------------------------------------------------------------- @@ -713,7 +712,7 @@ constexpr vector fma(const vector& a, const vector /// \param exp The variable to store the exponent in template requires(is_integral_v) constexpr genType frexp(genType x, genIType& exp) - { return std::frexp(x, &exp); } + { return ::frexp(x, &exp); } // Vector Specializations ---------------------------------------------------------------------------------------------- @@ -744,7 +743,7 @@ constexpr vector frexp(const vector& x, vector requires(is_integral_v) constexpr genType ldexp(genType x, genIType exp) - { return std::ldexp(x, exp); } + { return ::ldexp(x, exp); } // Vector Specializations ---------------------------------------------------------------------------------------------- diff --git a/include/fennec/math/detail/__fwd.h b/include/fennec/math/detail/__fwd.h index 5b3e18f..694a300 100644 --- a/include/fennec/math/detail/__fwd.h +++ b/include/fennec/math/detail/__fwd.h @@ -31,7 +31,7 @@ template struct matrix; // template using vec = decltype(detail::__gen_vector(make_index_sequence{})); // Gets the type returned by this function -template using mat +template using mat = decltype(detail::__gen_matrix(make_index_sequence{})); // Gets the type returned by this function } diff --git a/include/fennec/math/detail/__math.h b/include/fennec/math/detail/__math.h new file mode 100644 index 0000000..88349e0 --- /dev/null +++ b/include/fennec/math/detail/__math.h @@ -0,0 +1,57 @@ +// ===================================================================================================================== +// fennec, a free and open source game engine +// Copyright © 2025 Medusa Slockbower +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// ===================================================================================================================== + +#ifndef FENNEC_MATH_DETAIL_MATH_H +#define FENNEC_MATH_DETAIL_MATH_H + +#pragma push_macro("__cplusplus") +#undef __cplusplus +#include +#pragma pop_macro("__cplusplus") + +#undef div +#undef acos +#undef asin +#undef atan +#undef atan2 +#undef ceil +#undef cos +#undef cosh +#undef exp +#undef fabs +#undef floor +#undef fmod +#undef frexp +#undef ldexp +#undef log +#undef log10 +#undef modf +#undef pow +#undef sin +#undef sinh +#undef sqrt +#undef tan +#undef tanh +#undef fpclassify +#undef signbit +#undef isfinite +#undef isnormal +#undef isnan +#undef isinf + +#endif // FENNEC_MATH_DETAIL_MATH_H diff --git a/include/fennec/math/detail/__matrix.h b/include/fennec/math/detail/__matrix.h new file mode 100644 index 0000000..c41c80b --- /dev/null +++ b/include/fennec/math/detail/__matrix.h @@ -0,0 +1,147 @@ +// ===================================================================================================================== +// fennec, a free and open source game engine +// Copyright © 2025 Medusa Slockbower +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// ===================================================================================================================== + +#ifndef FENNEC_MATH_DETAIL_MATRIX_H +#define FENNEC_MATH_DETAIL_MATRIX_H + +#include + +namespace fennec +{ + +// specialization for mat2 +template requires(rows == 2 && sizeof...(cols) == 2) +constexpr scalar determinant(const matrix& m) +{ + return m[0][0] * m[1][1] - m[1][0] * m[0][1]; +} + +// specialization for mat3 +template requires(rows == 3 && sizeof...(cols) == 3) +constexpr scalar determinant(const matrix& m) +{ + // Cofactor expansion over first column, better for cache locality than the first row + return m[0][0] * (m[1][1] * m[2][2] - m[1][2] * m[2][1]) + - m[0][1] * (m[1][0] * m[2][2] - m[1][2] * m[2][0]) + + m[0][2] * (m[1][0] * m[2][1] - m[1][1] * m[2][0]); +} + +// specialization for mat4 +template requires(rows == 4 && sizeof...(cols) == 4) +constexpr scalar determinant(const matrix& m) +{ + // Cofactor expansion over the first column, better for cache locality than the first row + scalar d00 = m[2][2] * m[3][3] - m[3][2] * m[2][3]; + scalar d01 = m[2][1] * m[3][3] - m[3][1] * m[2][3]; + scalar d02 = m[2][1] * m[3][2] - m[3][1] * m[2][2]; + scalar d03 = m[2][0] * m[3][3] - m[3][0] * m[2][3]; + scalar d04 = m[2][0] * m[3][2] - m[3][0] * m[2][2]; + scalar d05 = m[2][0] * m[3][1] - m[3][0] * m[2][1]; + + scalar f0 = +(m[1][1]*d00 - m[1][2]*d01 + m[1][3]*d02); + scalar f1 = -(m[1][0]*d00 - m[1][2]*d03 + m[1][3]*d04); + scalar f2 = +(m[1][0]*d01 - m[1][1]*d03 + m[1][3]*d05); + scalar f3 = -(m[1][0]*d02 - m[1][1]*d04 + m[1][2]*d05); + + return m[0][0]*f0 + m[0][1]*f1 + m[0][2]*f2 + m[0][3]*f3; +} + + +// specialization for mat2 +template requires(rows == 2 && sizeof...(cols) == 2) +constexpr matrix inverse(const matrix& m) +{ + scalar di = scalar(1) / fennec::determinant(m); + return matrix( + m[1][1] * di, -m[0][1] * di, -m[1][0] * di, m[0][0] * di + ); +} + +// specialization for mat3 +template requires(rows == 3 && sizeof...(cols) == 3) +constexpr matrix inverse(const matrix& m) +{ + scalar di = scalar(1) / fennec::determinant(m); + + matrix i( + (m[1][1] * m[2][2] - m[2][1] * m[1][2]) * di + , -(m[0][1] * m[2][2] - m[2][1] * m[0][2]) * di + , (m[0][1] * m[1][2] - m[1][1] * m[0][2]) * di + + , -(m[1][0] * m[2][2] - m[2][0] * m[1][2]) * di + , (m[0][0] * m[2][2] - m[2][0] * m[0][2]) * di + , -(m[0][0] * m[1][2] - m[1][0] * m[0][2]) * di + + , (m[1][0] * m[2][1] - m[2][0] * m[1][1]) * di + , -(m[0][0] * m[2][1] - m[2][0] * m[0][1]) * di + , (m[0][0] * m[1][1] - m[1][0] * m[0][1]) * di + ); + + return i; +} + +template requires(rows == 4 && sizeof...(cols) == 4) +constexpr matrix inverse(const matrix& m) +{ + scalar s0 = m[0][0] * m[1][1] - m[1][0] * m[0][1]; + scalar s1 = m[0][0] * m[1][2] - m[1][0] * m[0][2]; + scalar s2 = m[0][0] * m[1][3] - m[1][0] * m[0][3]; + scalar s3 = m[0][1] * m[1][2] - m[1][1] * m[0][2]; + scalar s4 = m[0][1] * m[1][3] - m[1][1] * m[0][3]; + scalar s5 = m[0][2] * m[1][3] - m[1][2] * m[0][3]; + + scalar c5 = m[2][2] * m[3][3] - m[3][2] * m[2][3]; + scalar c4 = m[2][1] * m[3][3] - m[3][1] * m[2][3]; + scalar c3 = m[2][1] * m[3][2] - m[3][1] * m[2][2]; + scalar c2 = m[2][0] * m[3][3] - m[3][0] * m[2][3]; + scalar c1 = m[2][0] * m[3][2] - m[3][0] * m[2][2]; + scalar c0 = m[2][0] * m[3][1] - m[3][0] * m[2][1]; + + // Should check for 0 determinant + scalar invdet = (s0 * c5 - s1 * c4 + s2 * c3 + s3 * c2 - s4 * c1 + s5 * c0); + invdet = invdet ? 1.0 / invdet : 0; + + matrix i( + ( m[1][1] * c5 - m[1][2] * c4 + m[1][3] * c3) * invdet + , (-m[0][1] * c5 + m[0][2] * c4 - m[0][3] * c3) * invdet + , ( m[3][1] * s5 - m[3][2] * s4 + m[3][3] * s3) * invdet + , (-m[2][1] * s5 + m[2][2] * s4 - m[2][3] * s3) * invdet + + , (-m[1][0] * c5 + m[1][2] * c2 - m[1][3] * c1) * invdet + , ( m[0][0] * c5 - m[0][2] * c2 + m[0][3] * c1) * invdet + , (-m[3][0] * s5 + m[3][2] * s2 - m[3][3] * s1) * invdet + , ( m[2][0] * s5 - m[2][2] * s2 + m[2][3] * s1) * invdet + + , ( m[1][0] * c4 - m[1][1] * c2 + m[1][3] * c0) * invdet + , (-m[0][0] * c4 + m[0][1] * c2 - m[0][3] * c0) * invdet + , ( m[3][0] * s4 - m[3][1] * s2 + m[3][3] * s0) * invdet + , (-m[2][0] * s4 + m[2][1] * s2 - m[2][3] * s0) * invdet + + , (-m[1][0] * c3 + m[1][1] * c1 - m[1][2] * c0) * invdet + , ( m[0][0] * c3 - m[0][1] * c1 + m[0][2] * c0) * invdet + , (-m[3][0] * s3 + m[3][1] * s1 - m[3][2] * s0) * invdet + , ( m[2][0] * s3 - m[2][1] * s1 + m[2][2] * s0) * invdet + ); + + return i; +} + +} + + +#endif // FENNEC_MATH_DETAIL_MATRIX_H diff --git a/include/fennec/math/exponential.h b/include/fennec/math/exponential.h index 43f31f8..dc70083 100644 --- a/include/fennec/math/exponential.h +++ b/include/fennec/math/exponential.h @@ -32,11 +32,6 @@ #ifndef FENNEC_MATH_EXPONENTIAL_H #define FENNEC_MATH_EXPONENTIAL_H -#pragma push_macro("__cplusplus") -#undef __cplusplus -#include -#pragma pop_macro("__cplusplus") - /// /// /// @@ -93,6 +88,8 @@ /// /// +#include + namespace fennec { @@ -206,7 +203,7 @@ template constexpr genType sqrt(const vector constexpr genType inversesqrt(genType x) - { return 1.0f / std::sqrt(x); } + { return 1.0f / ::sqrt(x); } template constexpr vector inversesqrt(const vector& x) diff --git a/include/fennec/math/geometric.h b/include/fennec/math/geometric.h index a9b250c..7eaf13d 100644 --- a/include/fennec/math/geometric.h +++ b/include/fennec/math/geometric.h @@ -32,9 +32,6 @@ #ifndef FENNEC_MATH_GEOMETRIC_H #define FENNEC_MATH_GEOMETRIC_H -#include -#include - /// /// @@ -111,6 +108,9 @@ /// /// +#include +#include + namespace fennec { diff --git a/include/fennec/math/matrix.h b/include/fennec/math/matrix.h index f2c9db1..f562db3 100644 --- a/include/fennec/math/matrix.h +++ b/include/fennec/math/matrix.h @@ -44,6 +44,7 @@ /// #include +#include #include @@ -56,9 +57,6 @@ namespace fennec /// /// \brief returns a **copy** of the column \f$i\f$ of matrix \f$m\f$ -/// \tparam scalar the base scalar type -/// \tparam rows number of rows in the matrix -/// \tparam cols indices of the columns in the matrix /// \param m the matrix /// \param i the index of the row /// \returns a **copy** of the column at index \f$i\f$ @@ -69,9 +67,6 @@ constexpr vec column(const matrix& m, size_ /// /// \brief returns a **copy** of the row \f$i\f$ of matrix \f$m\f$ -/// \tparam scalar the base scalar type -/// \tparam rows number of rows in the matrix -/// \tparam cols indices of the columns in the matrix /// \param m the matrix /// \param i the index of the row /// \returns a **copy** of the row at index \f$i\f$ @@ -80,7 +75,8 @@ constexpr vec row(const matrix& { return vec(m[cols][i]...); } -template using tmat2x2 = mat; ///< helper for creating 2x2 matrices of the specified type. +template +using tmat2x2 = mat; ///< helper for creating 2x2 matrices of the specified type. template using tmat2x3 = mat; ///< helper for creating 2x3 matrices of the specified type. template using tmat2x4 = mat; ///< helper for creating 2x4 matrices of the specified type. template using tmat3x2 = mat; ///< helper for creating 3x2 matrices of the specified type. @@ -92,7 +88,7 @@ template using tmat4x4 = mat; ///< helper for c using mat2 = tmat2x2; ///< Specification for glsl float matrices using mat3 = tmat3x3; ///< Specification for glsl float matrices -using mat4 = tmat3x3; ///< Specification for glsl float matrices +using mat4 = tmat4x4; ///< Specification for glsl float matrices using mat2x2 = tmat2x2; ///< Specification for sized glsl float matrices using mat2x3 = tmat2x3; ///< Specification for sized glsl float matrices @@ -120,6 +116,70 @@ using dmat4x4 = tmat4x4; ///< Specification for size glsl double matri /// +/// \brief Multiply matrix \$x\f$ by matrix \f$y\f$ component-wise. +/// \details Multiply matrix x by matrix y component-wise, i.e., result[i][j] is the scalar product of x[i][j] and y[i][j].

+/// Note: to get linear algebraic matrix multiplication, use +/// the multiply operator (*) +/// \param x the first matrix +/// \param y the second matrix +/// \returns the resulting product in a matrix of the same size and base type +template +constexpr matrix matrixCompMult(const matrix& x, const matrix& y) noexcept +{ return matrix(x[cols] * y[cols] ...); } + +/// +/// \brief Performs a linear algebraic multiply, multiplying \f$c\f$ by the components of \f$r\f$, producing a matrix. +/// +/// \details Treats the first parameter \f$c\f$ as a column vector (matrix +/// with one column) and the second parameter \f$r\f$ as a row +/// vector (matrix with one row) and does a linear algebraic +/// matrix multiply \f$c \cross r\f$, yielding a matrix whose number of +/// rows is the number of components in \f$c\f$ and whose +/// number of columns is the number of components in \f$r\f$. +/// \param c the column vector +/// \param r the row vector +/// \returns the resulting matrix produced by the linear algebraic product +template +constexpr matrix outerProduct(const vector& c, const vector& r) noexcept +{ + return matrix( + c * r[s1]... + ); +} + +/// +/// \brief get the transpose of \f$m\f$ +/// \param m the matrix to transpose +/// \returns a matrix that is the transpose of \f$m\f$ +/// \details The input matrix m is not modified. +template +constexpr mat transpose(const matrix& m) noexcept +{ + return [m](index_sequence) -> mat { + return mat(fennec::row(m, i) ...); + }(make_index_sequence{}); +} + +/// +/// \brief Returns the determinant of m. +/// \param m the matrix +/// \returns the determinant of m. +template +constexpr scalar determinant(const matrix&) noexcept +{ + // ReSharper disable once CppStaticAssertFailure + static_assert(false, "implementation undefined"); + return 0; +} + +template +constexpr matrix inverse(const matrix&) noexcept +{ + // ReSharper disable once CppStaticAssertFailure + static_assert(false, "implementation undefined"); + return 1; +} + /// /// \brief /// \tparam ScalarT @@ -196,7 +256,6 @@ struct matrix constexpr matrix(const matrix_t& mat) : data{ mat.data } {} - /// /// \brief move constructor /// @@ -232,7 +291,7 @@ struct matrix /// \param args template requires(total_component_count_v == num_components) constexpr matrix(ArgsT&&...args) - { matrix::__construct(std::forward(args)...); } + { matrix::__construct(fennec::forward(args)...); } /// @} @@ -279,12 +338,12 @@ struct matrix /// \param i the index /// \returns the column at index \f$i\f$ constexpr const column_t& operator[](size_t i) const - { assert(i < rows); return data[i]; } + { assert(i < columns); return data[i]; } /// /// \copydetails matrix::operator()(size_t, size_t) const constexpr scalar_t& operator()(size_t i, size_t j) - { assert(i < rows && j < columns); return data[i][j]; } + { assert(i < columns && j < rows); return data[i][j]; } /// /// \brief returns the cell in row \p j column \p i @@ -292,7 +351,7 @@ struct matrix /// \param j the row /// \returns the cell at the specified index. constexpr scalar_t operator()(size_t i, size_t j) const - { assert(i < rows && j < columns); return data[i][j]; } + { assert(i < columns && j < rows); return data[i][j]; } /// @} @@ -589,8 +648,11 @@ struct matrix /// \param lhs the rows to multiply with /// \param rhs the columns to multiply with constexpr friend matrix_t operator*(const matrix_t& lhs, const transpose_t& rhs) - { return [lhs, rhs](index_sequence) -> matrix_t - { return matrix_t(rhs * fennec::row(lhs, i)...); }(make_index_sequence{}); } + { + return [lhs, rhs](index_sequence) -> matrix_t { + return matrix_t(rhs * fennec::row(lhs, i)...); + }(make_index_sequence{}); + } /// @} @@ -606,26 +668,33 @@ private: template constexpr void __construct(HeadT&& head, ArgsT&&...args) { - matrix::__insert(head); + matrix::__insert(head); matrix::__construct>(std::forward(args)...); } template constexpr void __insert(scalar_t s) - { data[i0 / columns][i0 % columns] = s; } + { data[i0 / rows][i0 % rows] = s; } template requires(is_arithmetic_v) constexpr void __insert(OScalarT s) - { data[i0 / columns][i0 % columns] = scalar_t(s); } + { data[i0 / rows][i0 % rows] = scalar_t(s); } template constexpr void __insert(const vector& v) { (matrix::__insert(v[i]), ...); } + template + constexpr void __insert(const vector& v) + { (matrix::__insert(v[i]), ...); } + }; + +// Internal ============================================================================================================ + } diff --git a/include/fennec/math/relational.h b/include/fennec/math/relational.h index c5700bb..b735319 100644 --- a/include/fennec/math/relational.h +++ b/include/fennec/math/relational.h @@ -31,8 +31,6 @@ #ifndef FENNEC_MATH_RELATIONAL_H #define FENNEC_MATH_RELATIONAL_H -#include - /// /// \page fennec_math_relational Relational /// @@ -114,7 +112,7 @@ /// /// -// TODO: Document +#include namespace fennec { diff --git a/include/fennec/math/scalar.h b/include/fennec/math/scalar.h index 29f8395..b4e2136 100644 --- a/include/fennec/math/scalar.h +++ b/include/fennec/math/scalar.h @@ -31,8 +31,6 @@ #ifndef FENNEC_MATH_SCALAR_H #define FENNEC_MATH_SCALAR_H -#include - /// /// /// @@ -59,6 +57,8 @@ /// /// +#include + #include #include diff --git a/include/fennec/math/swizzle.h b/include/fennec/math/swizzle.h index 23c75c4..adf3745 100644 --- a/include/fennec/math/swizzle.h +++ b/include/fennec/math/swizzle.h @@ -42,6 +42,7 @@ /// #include + #include namespace fennec diff --git a/include/fennec/math/trigonometric.h b/include/fennec/math/trigonometric.h index 6e1206a..0d4a9db 100644 --- a/include/fennec/math/trigonometric.h +++ b/include/fennec/math/trigonometric.h @@ -147,7 +147,7 @@ /// /// -#include +#include namespace fennec { @@ -209,7 +209,7 @@ constexpr vector degrees(const vector& radians) /// \param x the angle \f$\theta\f$ in \f$radians\f$ template constexpr genType sin(genType x) - { return std::sin(x); } + { return ::sin(x); } template constexpr vector sin(const vector& x) @@ -226,7 +226,7 @@ constexpr vector sin(const vector& x) /// \param x the angle \f$\theta\f$ in \f$radians\f$ template constexpr genType cos(genType x) - { return std::cos(x); } + { return ::cos(x); } template constexpr vector cos(const vector& x) @@ -243,7 +243,7 @@ constexpr vector cos(const vector& x) /// \param x The Angle \f$\theta\f$ in \f$radians\f$ template constexpr genType tan(genType x) - { return std::tan(x); } + { return ::tan(x); } template constexpr vector tan(const vector& x) @@ -267,7 +267,7 @@ constexpr vector tan(const vector& x) /// \param x The Sine Value produced by \f$\theta\f$ template constexpr genType asin(genType x) - { return std::asin(x); } + { return ::asin(x); } template constexpr vector asin(const vector& x) @@ -285,7 +285,7 @@ constexpr vector asin(const vector& x) /// \param x The Cosine Value produced by \f$\theta\f$ template constexpr genType acos(genType x) - { return std::acos(x); } + { return ::acos(x); } template constexpr vector acos(const vector& x) @@ -303,7 +303,7 @@ constexpr vector acos(const vector& x) /// \param y_over_x The Cosine Value produced by \f$\theta\f$ template constexpr genType atan(genType y_over_x) - { return std::atan(y_over_x); } + { return ::atan(y_over_x); } template constexpr vector atan(const vector& y_over_x) @@ -322,7 +322,7 @@ constexpr vector atan(const vector& y_over_x) /// \param x The Cosine Value produced by \f$\theta\f$ template constexpr genType atan(genType y, genType x) - { return std::atan2(y, x); } + { return ::atan2(y, x); } template constexpr vector atan(const vector& y, const vector& x) @@ -345,7 +345,7 @@ constexpr vector atan(const vector& y, const vecto /// \param x The Hyperbolic Angle \f$\alpha\f$ template constexpr genType sinh(genType x) - { return std::sinh(x); } + { return ::sinh(x); } template constexpr vector sinh(const vector& x) @@ -360,7 +360,7 @@ constexpr vector sinh(const vector& x) /// \param x The Hyperbolic Angle \f$\alpha\f$ template constexpr genType cosh(genType x) - { return std::cosh(x); } + { return ::cosh(x); } template constexpr vector cosh(const vector& x) @@ -375,7 +375,7 @@ constexpr vector cosh(const vector& x) /// \param x The Hyperbolic Angle \f$\alpha\f$ template constexpr genType tanh(genType x) - { return std::tanh(x); } + { return ::tanh(x); } template constexpr vector tanh(const vector& x) @@ -396,7 +396,7 @@ constexpr vector tanh(const vector& x) /// \param x the hyperbolic angle \f$\alpha\f$ template constexpr genType asinh(genType x) - { return std::asinh(x); } + { return ::asinh(x); } template constexpr vector asinh(const vector& x) @@ -412,7 +412,7 @@ constexpr vector asinh(const vector& x) /// \param x the hyperbolic angle \f$\alpha\f$ template constexpr genType acosh(genType x) - { return std::acosh(x); } + { return ::acosh(x); } template constexpr vector acosh(const vector& x) @@ -428,7 +428,7 @@ constexpr vector acosh(const vector& x) /// \param x The Hyperbolic Angle \f$\alpha\f$ template constexpr genType atanh(genType x) - { return std::atanh(x); } + { return ::atanh(x); } template constexpr vector atanh(const vector& x) diff --git a/include/fennec/math/vector.h b/include/fennec/math/vector.h index e1d8c95..cdb3d9a 100644 --- a/include/fennec/math/vector.h +++ b/include/fennec/math/vector.h @@ -468,7 +468,7 @@ struct vector : detail::vector_base_type /// \param lhs left hand side /// \param rhs right hand side constexpr friend vector_t operator+(scalar_t lhs, const vector_t& rhs) - { return vector_t((lhs[IndicesV] + rhs[IndicesV]) ...); } + { return vector_t((lhs + rhs[IndicesV]) ...); } /// /// \brief \ref fennec_math_scalar "scalar" - \ref fennec_math_vector "vector" subtraction operator @@ -478,7 +478,7 @@ struct vector : detail::vector_base_type /// \param lhs left hand side /// \param rhs right hand side constexpr friend vector_t operator-(scalar_t lhs, const vector_t& rhs) - { return vector_t((lhs[IndicesV] - rhs[IndicesV]) ...); } + { return vector_t((lhs - rhs[IndicesV]) ...); } /// /// \brief \ref fennec_math_scalar "scalar" - \ref fennec_math_vector "vector" multiplication operator @@ -796,17 +796,7 @@ struct vector : detail::vector_base_type /// \param rhs Right Hand Side of the Expression /// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i\&rhs_i\f$ constexpr friend vector_t operator&(scalar_t rhs, const vector_t& lhs) requires(is_integral_v) - { return vector_t((lhs & rhs[IndicesV]) ...); } - - /// - /// \brief \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" bitwise and assignment operator - /// - /// \details - /// \param lhs Left Hand Side of the Expression - /// \param rhs Right Hand Side of the Expression - /// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i\&rhs_i\f$ - constexpr friend vector_t operator&=(vector_t& lhs, scalar_t rhs) requires(is_integral_v) - { return ((lhs[IndicesV] &= rhs), ..., lhs); } + { return vector_t((lhs[IndicesV] & rhs) ...); } /// /// \brief \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" bitwise and operator @@ -819,13 +809,13 @@ struct vector : detail::vector_base_type { return vector_t((lhs[IndicesV] & rhs) ...); } /// - /// \brief \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" bitwise and assignment operator + /// \brief \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" bitwise and assignment operator /// /// \details /// \param lhs Left Hand Side of the Expression /// \param rhs Right Hand Side of the Expression /// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i\&rhs_i\f$ - constexpr friend vector_t operator&=(vector_t& lhs, const vector_t& rhs) requires(is_integral_v) + constexpr friend vector_t operator&=(vector_t& lhs, scalar_t rhs) requires(is_integral_v) { return ((lhs[IndicesV] &= rhs), ..., lhs); } /// @@ -838,6 +828,16 @@ struct vector : detail::vector_base_type constexpr friend vector_t operator&(const vector_t& lhs, const vector_t& rhs) requires(is_integral_v) { return vector_t((lhs[IndicesV] & rhs[IndicesV]) ...); } + /// + /// \brief \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" bitwise and assignment operator + /// + /// \details + /// \param lhs Left Hand Side of the Expression + /// \param rhs Right Hand Side of the Expression + /// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i\&rhs_i\f$ + constexpr friend vector_t operator&=(vector_t& lhs, const vector_t& rhs) requires(is_integral_v) + { return ((lhs[IndicesV] &= rhs[IndicesV]), ..., lhs); } + /// @@ -850,16 +850,6 @@ struct vector : detail::vector_base_type constexpr friend vector_t operator|(scalar_t rhs, const vector_t& lhs) requires(is_integral_v) { return vector_t((lhs & rhs[IndicesV]) ...); } - /// - /// \brief \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" bitwise or assignment operator - /// - /// \details - /// \param lhs Left Hand Side of the Expression - /// \param rhs Right Hand Side of the Expression - /// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i|rhs_i\f$ - constexpr friend vector_t operator|=(vector_t& lhs, scalar_t rhs) requires(is_integral_v) - { return ((lhs[IndicesV] |= rhs), ..., lhs); } - /// /// \brief \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" bitwise or operator /// @@ -871,13 +861,13 @@ struct vector : detail::vector_base_type { return vector_t((lhs[IndicesV] | rhs) ...); } /// - /// \brief \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" bitwise or assignment operator + /// \brief \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" bitwise or assignment operator /// /// \details /// \param lhs Left Hand Side of the Expression /// \param rhs Right Hand Side of the Expression /// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i|rhs_i\f$ - constexpr friend vector_t operator|=(vector_t& lhs, const vector_t& rhs) requires(is_integral_v) + constexpr friend vector_t operator|=(vector_t& lhs, scalar_t rhs) requires(is_integral_v) { return ((lhs[IndicesV] |= rhs), ..., lhs); } /// @@ -888,7 +878,17 @@ struct vector : detail::vector_base_type /// \param rhs Right Hand Side of the Expression /// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i|rhs_i\f$ constexpr friend vector_t operator|(const vector_t& lhs, const vector_t& rhs) requires(is_integral_v) - { return vector_t((lhs[IndicesV] | rhs[IndicesV]) ...); } + { return vector_t((lhs[IndicesV] | rhs[IndicesV]) ...); } + + /// + /// \brief \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" bitwise or assignment operator + /// + /// \details + /// \param lhs Left Hand Side of the Expression + /// \param rhs Right Hand Side of the Expression + /// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i|rhs_i\f$ + constexpr friend vector_t operator|=(vector_t& lhs, const vector_t& rhs) requires(is_integral_v) + { return ((lhs[IndicesV] |= rhs), ..., lhs); } @@ -900,14 +900,6 @@ struct vector : detail::vector_base_type constexpr friend vector_t operator^(scalar_t rhs, const vector_t& lhs) requires(is_integral_v) { return vector_t((lhs ^ rhs[IndicesV]) ...); } - /// - /// \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" bitwise xor assignment operator - /// \param lhs Left Hand Side of the Expression - /// \param rhs Right Hand Side of the Expression - /// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i\^rhs_i\f$ - constexpr friend vector_t operator^=(vector_t& lhs, scalar_t rhs) requires(is_integral_v) - { return ((lhs[IndicesV] ^= rhs), ..., lhs); } - /// /// \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" bitwise xor operator /// \param lhs Left Hand Side of the Expression @@ -917,11 +909,11 @@ struct vector : detail::vector_base_type { return vector_t((lhs[IndicesV] ^ rhs) ...); } /// - /// \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" bitwise xor assignment operator + /// \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" bitwise xor assignment operator /// \param lhs Left Hand Side of the Expression /// \param rhs Right Hand Side of the Expression /// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i\^rhs_i\f$ - constexpr friend vector_t operator^=(vector_t& lhs, const vector_t& rhs) requires(is_integral_v) + constexpr friend vector_t operator^=(vector_t& lhs, scalar_t rhs) requires(is_integral_v) { return ((lhs[IndicesV] ^= rhs), ..., lhs); } /// @@ -932,15 +924,15 @@ struct vector : detail::vector_base_type constexpr friend vector_t operator^(const vector_t& lhs, const vector_t& rhs) requires(is_integral_v) { return vector_t((lhs[IndicesV] ^ rhs[IndicesV]) ...); } - - /// - /// \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" bitwise left-shift assignment operator + /// \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" bitwise xor assignment operator /// \param lhs Left Hand Side of the Expression /// \param rhs Right Hand Side of the Expression - /// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i<<=rhs_i\f$ - constexpr friend vector_t operator<<=(vector_t& lhs, scalar_t rhs) requires(is_integral_v) - { return ((lhs[IndicesV] <<= rhs), ..., lhs); } + /// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i\^rhs_i\f$ + constexpr friend vector_t operator^=(vector_t& lhs, const vector_t& rhs) requires(is_integral_v) + { return ((lhs[IndicesV] ^= rhs), ..., lhs); } + + /// /// \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" bitwise or operator @@ -951,11 +943,11 @@ struct vector : detail::vector_base_type { return vector_t((lhs[IndicesV] << rhs) ...); } /// - /// \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" bitwise or assignment operator + /// \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" bitwise left-shift assignment operator /// \param lhs Left Hand Side of the Expression /// \param rhs Right Hand Side of the Expression /// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i<<=rhs_i\f$ - constexpr friend vector_t operator<<=(vector_t& lhs, const vector_t& rhs) requires(is_integral_v) + constexpr friend vector_t operator<<=(vector_t& lhs, scalar_t rhs) requires(is_integral_v) { return ((lhs[IndicesV] <<= rhs), ..., lhs); } /// @@ -966,15 +958,15 @@ struct vector : detail::vector_base_type constexpr friend vector_t operator<<(const vector_t& lhs, const vector_t& rhs) requires(is_integral_v) { return vector_t((lhs[IndicesV] << rhs[IndicesV]) ...); } - - /// - /// \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" bitwise left-shift assignment operator + /// \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" bitwise or assignment operator /// \param lhs Left Hand Side of the Expression /// \param rhs Right Hand Side of the Expression - /// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i>>=rhs_i\f$ - constexpr friend vector_t operator>>=(vector_t& lhs, scalar_t rhs) requires(is_integral_v) - { return ((lhs[IndicesV] >>= rhs), ..., lhs); } + /// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i<<=rhs_i\f$ + constexpr friend vector_t operator<<=(vector_t& lhs, const vector_t& rhs) requires(is_integral_v) + { return ((lhs[IndicesV] <<= rhs), ..., lhs); } + + /// /// \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" bitwise or operator @@ -985,11 +977,11 @@ struct vector : detail::vector_base_type { return vector_t((lhs[IndicesV] >> rhs) ...); } /// - /// \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" bitwise or assignment operator + /// \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" bitwise left-shift assignment operator /// \param lhs Left Hand Side of the Expression /// \param rhs Right Hand Side of the Expression /// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i>>=rhs_i\f$ - constexpr friend vector_t operator>>=(vector_t& lhs, const vector_t& rhs) requires(is_integral_v) + constexpr friend vector_t operator>>=(vector_t& lhs, scalar_t rhs) requires(is_integral_v) { return ((lhs[IndicesV] >>= rhs), ..., lhs); } /// @@ -1000,6 +992,14 @@ struct vector : detail::vector_base_type constexpr friend vector_t operator>>(const vector_t& lhs, const vector_t& rhs) requires(is_integral_v) { return vector_t((lhs[IndicesV] >> rhs[IndicesV]) ...); } + /// + /// \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" bitwise or assignment operator + /// \param lhs Left Hand Side of the Expression + /// \param rhs Right Hand Side of the Expression + /// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i>>=rhs_i\f$ + constexpr friend vector_t operator>>=(vector_t& lhs, const vector_t& rhs) requires(is_integral_v) + { return ((lhs[IndicesV] >>= rhs), ..., lhs); } + /// @} diff --git a/include/fennec/memory/new.h b/include/fennec/memory/new.h index 13416ce..dd714c0 100644 --- a/include/fennec/memory/new.h +++ b/include/fennec/memory/new.h @@ -20,7 +20,6 @@ #ifndef FENNEC_MEMORY_NEW_H #define FENNEC_MEMORY_NEW_H -#include #include #include @@ -44,10 +43,10 @@ template void construct(TypeT* ptr, const TypeT& val) { ptr->TypeT(val); } template void construct(TypeT* ptr, TypeT&& val) - { ptr->TypeT(fennec::forward(val)); } + { ptr->TypeT(fennec::forward(val)); } template void construct(TypeT* ptr, ArgsT...args) - { ptr->TypeT(fennec::forward(args)...); } + { ptr->TypeT(fennec::forward(args)...); } template void destruct(TypeT* ptr) { ptr->~TypeT(); } diff --git a/source/lang/assert.cpp b/source/lang/assert.cpp index 4a1726b..01a576d 100644 --- a/source/lang/assert.cpp +++ b/source/lang/assert.cpp @@ -16,7 +16,7 @@ // along with this program. If not, see . // ===================================================================================================================== -#include +#include using assert_handler = void (*)(const char *, const char *, int , const char *); diff --git a/source/memory/new.cpp b/source/memory/new.cpp index f3ce24a..c5d75dc 100644 --- a/source/memory/new.cpp +++ b/source/memory/new.cpp @@ -16,8 +16,9 @@ // along with this program. If not, see . // ===================================================================================================================== +#include + #include -#include #ifdef FENNEC_MEMORY_DEBUGGER diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 21ee62a..701e41e 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -14,6 +14,7 @@ add_executable(fennec-test main.cpp tests/test_lang.h tests/lang/test_conditional_types.h tests/lang/test_bits.h + tests/lang/test_sequences.h ) target_link_libraries(fennec-test PRIVATE diff --git a/test/test.h b/test/test.h index af62f24..ee478f1 100644 --- a/test/test.h +++ b/test/test.h @@ -25,6 +25,7 @@ #include #include +#include #include namespace fennec @@ -56,7 +57,10 @@ inline std::ostream& operator<<(std::ostream& os, const matrix(std::ostream& os, index_sequence) { + // ((os << fennec::row(m, i) << " "), ...); + //}(os, make_index_sequence{}); + os << "]"; return os; } diff --git a/test/tests/lang/test_sequences.h b/test/tests/lang/test_sequences.h new file mode 100644 index 0000000..4055058 --- /dev/null +++ b/test/tests/lang/test_sequences.h @@ -0,0 +1,41 @@ +// ===================================================================================================================== +// fennec, a free and open source game engine +// Copyright © 2025 Medusa Slockbower +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// ===================================================================================================================== + +#ifndef FENNEC_TEST_LANG_SEQUENCES_H +#define FENNEC_TEST_LANG_SEQUENCES_H + +#include + +namespace fennec +{ + +namespace test +{ + +inline void test_sequences() +{ + static_assert(fennec::is_same_v, index_sequence<0, 1>>); + static_assert(fennec::is_same_v, index_sequence<0, 1, 2>>); + static_assert(fennec::is_same_v, index_sequence<0, 1, 2, 3>>); +} + +} + +} + +#endif // FENNEC_TEST_LANG_SEQUENCES_H diff --git a/test/tests/math/test_matrix.h b/test/tests/math/test_matrix.h index 5cc47a6..828fe04 100644 --- a/test/tests/math/test_matrix.h +++ b/test/tests/math/test_matrix.h @@ -34,9 +34,89 @@ namespace test inline void fennec_test_math_matrix() { + fennec_test_section("matrixCompMult"); + + fennec_test_spacer(1); + + fennec_test_run(fennec::matrixCompMult(mat2(1, 2, 3, 4), mat2(1)), mat2(1, 0, 0, 4)); + fennec_test_run(fennec::matrixCompMult(mat3(1, 4, 8, 6, 2, 5, 9, 7, 3), mat3(1)), mat3(1, 0, 0, 0, 2, 0, 0, 0, 3)); + fennec_test_run(fennec::matrixCompMult(mat4(2, 1, -3, 4, -1, 0, 2, 5, 3, 2, 1, 0, 4, -2, 3, 1), mat4(1)), mat4(2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)); + + fennec_test_spacer(1); + fennec_test_section("outerProduct"); + + fennec_test_spacer(1); + + fennec_test_run(fennec::outerProduct(vec2(1, 2), vec2(3, 4)), mat2(3, 6, 4, 8)); + fennec_test_run(fennec::outerProduct(vec3(1, 2, 3), vec3(4, 5, 6)), mat3(4, 8, 12, 5, 10, 15, 6, 12, 18)); + fennec_test_run(fennec::outerProduct(vec4(1, 2, 3, 4), vec4(5, 6, 7, 8)), mat4(5, 10, 15, 20, 6, 12, 18, 24, 7, 14, 21, 28, 8, 16, 24, 32)); + + fennec_test_spacer(1); + + fennec_test_run(fennec::outerProduct(vec3(1, 2, 3), vec2(4, 5)), mat2x3(4, 8, 12, 5, 10, 15)); + fennec_test_run(fennec::outerProduct(vec2(1, 2), vec3(3, 4, 5)), mat3x2(3, 6, 4, 8, 5, 10)); + + fennec_test_spacer(1); + + fennec_test_run(fennec::outerProduct(vec4(1, 2, 3, 4), vec2(5, 6)), mat2x4(5, 10, 15, 20, 6, 12, 18, 24)); + fennec_test_run(fennec::outerProduct(vec2(1, 2), vec4(3, 4, 5, 6)), mat4x2(3, 6, 4, 8, 5, 10, 6, 12)); + + fennec_test_spacer(1); + + fennec_test_run(fennec::outerProduct(vec4(1, 2, 3, 4), vec3(5, 6, 7)), mat3x4(5, 10, 15, 20, 6, 12, 18, 24, 7, 14, 21, 28)); + fennec_test_run(fennec::outerProduct(vec3(1, 2, 3), vec4(4, 5, 6, 7)), mat4x3(4, 8, 12, 5, 10, 15, 6, 12, 18, 7, 14, 21)); + + fennec_test_spacer(1); + + + + fennec_test_section("transpose"); + + fennec_test_spacer(1); + + fennec_test_run(fennec::transpose(mat2(1, 2, 3, 4)), mat2(1, 3, 2, 4)); + fennec_test_run(fennec::transpose(mat3(1, 2, 3, 4, 5, 6, 7, 8, 9)), mat3(1, 4, 7, 2, 5, 8, 3, 6, 9)); + fennec_test_run(fennec::transpose(mat4(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16)), mat4(1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15, 4, 8, 12, 16)); + + fennec_test_spacer(1); + + fennec_test_run(fennec::transpose(mat3x2(1, 2, 3, 4, 5, 6)), mat2x3(1, 3, 5, 2, 4, 6)); + fennec_test_run(fennec::transpose(mat2x3(1, 2, 3, 4, 5, 6)), mat3x2(1, 4, 2, 5, 3, 6)); + + fennec_test_spacer(1); + + fennec_test_run(fennec::transpose(mat4x2(1, 2, 3, 4, 5, 6, 7, 8)), mat2x4(1, 3, 5, 7, 2, 4, 6, 8)); + fennec_test_run(fennec::transpose(mat2x4(1, 2, 3, 4, 5, 6, 7, 8)), mat4x2(1, 5, 2, 6, 3, 7, 4, 8)); + + fennec_test_spacer(1); + + fennec_test_run(fennec::transpose(mat4x3(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)), mat3x4(1, 4, 7, 10, 2, 5, 8, 11, 3, 6, 9, 12)); + fennec_test_run(fennec::transpose(mat3x4(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)), mat4x3(1, 5, 9, 2, 6, 10, 3, 7, 11, 4, 8, 12)); + + fennec_test_spacer(1); + + + + fennec_test_section("determinant"); + + fennec_test_spacer(1); + + fennec_test_run(fennec::determinant(mat2(1, 2, 3, 4)), -2.0f); + fennec_test_run(fennec::determinant(mat3(1, 4, 8, 6, 2, 5, 9, 7, 3)), 271.0f); + fennec_test_run(fennec::determinant(mat4(2, 1, -3, 4, -1, 0, 2, 5, 3, 2, 1, 0, 4, -2, 3, 1)), 414.0f); + + fennec_test_spacer(1); + + fennec_test_section("inverse"); + + fennec_test_spacer(1); + + fennec_test_run(fennec::inverse(mat2(1, 2, 3, 4)), mat2(-2, 1, 1.5, -0.5)); + fennec_test_run(fennec::inverse(mat3(1, 2, 3, 0, 1, 4, 5, 6, 0)), mat3(-24, 18, 5, 20, -15, -4, -5, 4, 1)); + fennec_test_run(fennec::inverse(mat4(2, 1, -3, 4, -1, 0, 2, 5, 3, 2, 1, 0, 4, -2, 3, 1)), (1.0f / 414.0f) * mat4(36, -39, 33, 51, -18, 31, 133, -83, -72, 55, 49, 13, 36, 53, -13, 5)); } } diff --git a/test/tests/math/test_vector.h b/test/tests/math/test_vector.h index d80a153..2abf919 100644 --- a/test/tests/math/test_vector.h +++ b/test/tests/math/test_vector.h @@ -22,7 +22,6 @@ #include -#include #include #include "../../test.h" @@ -39,38 +38,6 @@ inline void fennec_test_math_vector() fennec_test_spacer(1); - fennec_test_run((component_count_v == 1), true); - fennec_test_run((component_count_v == 1), true); - fennec_test_run((component_count_v == 1), true); - fennec_test_run((component_count_v == 1), true); - fennec_test_run((component_count_v == 1), true); - - fennec_test_spacer(1); - - fennec_test_run((component_count_v == 1), true); - fennec_test_run((component_count_v == 1), true); - fennec_test_run((component_count_v == 1), true); - fennec_test_run((component_count_v == 1), true); - fennec_test_run((component_count_v == 1), true); - - fennec_test_spacer(1); - - fennec_test_run((component_count_v == 1), true); - fennec_test_run((component_count_v == 1), true); - fennec_test_run((component_count_v == 1), true); - fennec_test_run((component_count_v == 1), true); - fennec_test_run((component_count_v == 1), true); - - fennec_test_spacer(1); - - fennec_test_run((component_count_v == 1), true); - fennec_test_run((component_count_v == 1), true); - fennec_test_run((component_count_v == 1), true); - fennec_test_run((component_count_v == 1), true); - fennec_test_run((component_count_v == 1), true); - - fennec_test_spacer(1); - fennec_test_run((component_count_v == 2), true); fennec_test_run((component_count_v == 3), true); fennec_test_run((component_count_v == 4), true); @@ -146,6 +113,19 @@ inline void fennec_test_math_vector() fennec_test_spacer(2); + + + fennec_test_section("vec2 equivalency operator"); + + fennec_test_spacer(1); + + fennec_test_run((vec2() == vec2()), true); + fennec_test_run((vec2() != vec2()), false); + + fennec_test_spacer(2); + + + fennec_test_section("vec2 constructors"); fennec_test_spacer(1); @@ -161,6 +141,8 @@ inline void fennec_test_math_vector() fennec_test_spacer(2); + + fennec_test_section("vec2 swizzles"); fennec_test_spacer(1); @@ -172,6 +154,8 @@ inline void fennec_test_math_vector() fennec_test_spacer(2); + + fennec_test_section("vec3 constructors"); fennec_test_spacer(1); @@ -187,6 +171,8 @@ inline void fennec_test_math_vector() fennec_test_spacer(2); + + fennec_test_section("vec3 swizzles"); fennec_test_spacer(1); @@ -233,10 +219,24 @@ inline void fennec_test_math_vector() fennec_test_spacer(2); - fennec_test_section("scalar-vector operations"); + + + fennec_test_section("scalar-vector arithmetic operations"); fennec_test_spacer(1); + fennec_test_run(2.0 + vec2(1, 2), vec2(3, 4)); + fennec_test_run(2.0 + vec3(1, 2, 3), vec3(3, 4, 5)); + fennec_test_run(2.0 + vec4(1, 2, 3, 4), vec4(3, 4, 5, 6)); + + fennec_test_spacer(2); + + fennec_test_run(2.0 - vec2(1, 2), vec2(1, 0)); + fennec_test_run(2.0 - vec3(1, 2, 3), vec3(1, 0, -1)); + fennec_test_run(2.0 - vec4(1, 2, 3, 4), vec4(1, 0, -1, -2)); + + fennec_test_spacer(2); + fennec_test_run(2.0 * vec2(1, 2), vec2(2, 4)); fennec_test_run(2.0 * vec3(1, 2, 3), vec3(2, 4, 6)); fennec_test_run(2.0 * vec4(1, 2, 3, 4), vec4(2, 4, 6, 8)); @@ -247,9 +247,87 @@ inline void fennec_test_math_vector() fennec_test_run(2.0 / vec3(1, 2, 4), vec3(2.0, 1.0, 0.5)); fennec_test_run(2.0 / vec4(1, 2, 4, 8), vec4(2.0, 1.0, 0.5, 0.25)); + fennec_test_run(2 % ivec2(1, 2), ivec2(0, 0)); + fennec_test_run(2 % ivec3(1, 2, 3), ivec3(0, 0, 2)); + fennec_test_run(2 % ivec4(1, 2, 3, 4), ivec4(0, 0, 2, 2)); + fennec_test_spacer(2); - fennec_test_section("vector-vector operations"); + + + fennec_test_section("vector-scalar arithmetic operations"); + + fennec_test_spacer(1); + + fennec_test_run(vec2(1, 2) + 2.0, vec2(3, 4)); + fennec_test_run(vec3(1, 2, 3) + 2.0, vec3(3, 4, 5)); + fennec_test_run(vec4(1, 2, 3, 4) + 2.0, vec4(3, 4, 5, 6)); + + fennec_test_spacer(2); + + fennec_test_run(vec2(1, 2) - 2.0, vec2(-1, 0)); + fennec_test_run(vec3(1, 2, 3) - 2.0, vec3(-1, 0, 1)); + fennec_test_run(vec4(1, 2, 3, 4) - 2.0, vec4(-1, 0, 1, 2)); + + fennec_test_spacer(2); + + fennec_test_run(vec2(1, 2) * 2.0, vec2(2, 4)); + fennec_test_run(vec3(1, 2, 3) * 2.0, vec3(2, 4, 6)); + fennec_test_run(vec4(1, 2, 3, 4) * 2.0, vec4(2, 4, 6, 8)); + + fennec_test_spacer(2); + + fennec_test_run(vec2(1, 2) / 2.0, vec2(0.5, 1.0)); + fennec_test_run(vec3(1, 2, 4) / 2.0, vec3(0.5, 1.0, 2.0)); + fennec_test_run(vec4(1, 2, 4, 8) / 2.0, vec4(0.5, 1.0, 2.0, 4.0)); + + fennec_test_spacer(2); + + fennec_test_run(ivec2(1, 2) % 2, ivec2(1, 0)); + fennec_test_run(ivec3(1, 2, 3) % 2, ivec3(1, 0, 1)); + fennec_test_run(ivec4(1, 2, 3, 4) % 2, ivec4(1, 0, 1, 0)); + + fennec_test_spacer(2); + + + + fennec_test_section("vector-scalar arithmetic assignment operations"); + + fennec_test_spacer(1); + + fennec_test_run(([]() -> vec2 { vec2 v{ 1, 2 }; return v += 2.0; }()), vec2(3, 4)); + fennec_test_run(([]() -> vec3 { vec3 v{ 1, 2, 3 }; return v += 2.0; }()), vec3(3, 4, 5)); + fennec_test_run(([]() -> vec4 { vec4 v{ 1, 2, 3, 4 }; return v += 2.0; }()), vec4(3, 4, 5, 6)); + + fennec_test_spacer(2); + + fennec_test_run(([]() -> vec2 { vec2 v{ 1, 2 }; return v -= 2.0; }()), vec2(-1, 0)); + fennec_test_run(([]() -> vec3 { vec3 v{ 1, 2, 3 }; return v -= 2.0; }()), vec3(-1, 0, 1)); + fennec_test_run(([]() -> vec4 { vec4 v{ 1, 2, 3, 4 }; return v -= 2.0; }()), vec4(-1, 0, 1, 2)); + + fennec_test_spacer(2); + + fennec_test_run(([]() -> vec2 { vec2 v{ 1, 2 }; return v *= 2.0; }()), vec2(2, 4)); + fennec_test_run(([]() -> vec3 { vec3 v{ 1, 2, 3 }; return v *= 2.0; }()), vec3(2, 4, 6)); + fennec_test_run(([]() -> vec4 { vec4 v{ 1, 2, 3, 4 }; return v *= 2.0; }()), vec4(2, 4, 6, 8)); + + fennec_test_spacer(2); + + fennec_test_run(([]() -> vec2 { vec2 v{ 1, 2 }; return v /= 2.0; }()), vec2(0.5, 1.0)); + fennec_test_run(([]() -> vec3 { vec3 v{ 1, 2, 3 }; return v /= 2.0; }()), vec3(0.5, 1.0, 1.5)); + fennec_test_run(([]() -> vec4 { vec4 v{ 1, 2, 3, 4 }; return v /= 2.0; }()), vec4(0.5, 1.0, 1.5, 2.0)); + + fennec_test_spacer(2); + + fennec_test_run(([]() -> ivec2 { ivec2 v{ 1, 2 }; return v %= 2; }()), ivec2(1, 0)); + fennec_test_run(([]() -> ivec3 { ivec3 v{ 1, 2, 3 }; return v %= 2; }()), ivec3(1, 0, 1)); + fennec_test_run(([]() -> ivec4 { ivec4 v{ 1, 2, 3, 4 }; return v %= 2; }()), ivec4(1, 0, 1, 0)); + + fennec_test_spacer(2); + + + + fennec_test_section("vector-vector arithmetic operations"); fennec_test_spacer(1); @@ -281,6 +359,122 @@ inline void fennec_test_math_vector() fennec_test_run(ivec3(1, 2, 4) % ivec3(1, 2, 4), ivec3(0, 0, 0)); fennec_test_run(ivec4(1, 2, 4, 8) % ivec4(1, 2, 4, 8), ivec4(0, 0, 0, 0)); + fennec_test_spacer(2); + + + + fennec_test_section("vector-vector arithmetic assignment operations"); + + fennec_test_spacer(1); + + fennec_test_run(([]() -> vec2 { vec2 v(1, 2); return v += vec2(1, 2); }()), vec2(2, 4)); + fennec_test_run(([]() -> vec3 { vec3 v(1, 2, 3); return v += vec3(1, 2, 3); }()), vec3(2, 4, 6)); + fennec_test_run(([]() -> vec4 { vec4 v(1, 2, 3, 4); return v += vec4(1, 2, 3, 4); }()), vec4(2, 4, 6, 8)); + + fennec_test_spacer(1); + + fennec_test_run(([]() -> vec2 { vec2 v(1, 2); return v -= vec2(1, 2); }()), vec2(0, 0)); + fennec_test_run(([]() -> vec3 { vec3 v(1, 2, 3); return v -= vec3(1, 2, 3); }()), vec3(0, 0, 0)); + fennec_test_run(([]() -> vec4 { vec4 v(1, 2, 3, 4); return v -= vec4(1, 2, 3, 4); }()), vec4(0, 0, 0, 0)); + + fennec_test_spacer(1); + + fennec_test_run(([]() -> vec2 { vec2 v(1, 2); return v *= vec2(1, 2); }()), vec2(1, 4)); + fennec_test_run(([]() -> vec3 { vec3 v(1, 2, 3); return v *= vec3(1, 2, 3); }()), vec3(1, 4, 9)); + fennec_test_run(([]() -> vec4 { vec4 v(1, 2, 3, 4); return v *= vec4(1, 2, 3, 4); }()), vec4(1, 4, 9, 16)); + + fennec_test_spacer(1); + + fennec_test_run(([]() -> vec2 { vec2 v(1, 2); return v /= vec2(1, 2); }()), vec2(1, 1)); + fennec_test_run(([]() -> vec3 { vec3 v(1, 2, 4); return v /= vec3(1, 2, 4); }()), vec3(1, 1, 1)); + fennec_test_run(([]() -> vec4 { vec4 v(1, 2, 4, 8); return v /= vec4(1, 2, 4, 8); }()), vec4(1, 1, 1, 1)); + + fennec_test_spacer(1); + + fennec_test_run(([]() -> ivec2 { ivec2 v(1, 2); return v %= ivec2(1, 2); }()), ivec2(0, 0)); + fennec_test_run(([]() -> ivec3 { ivec3 v(1, 2, 4); return v %= ivec3(1, 2, 4); }()), ivec3(0, 0, 0)); + fennec_test_run(([]() -> ivec4 { ivec4 v(1, 2, 4, 8); return v %= ivec4(1, 2, 4, 8); }()), ivec4(0, 0, 0, 0)); + + fennec_test_spacer(2); + + + + fennec_test_section("boolean operations"); + + fennec_test_spacer(1); + + fennec_test_run(bvec2(false, false) && true, bvec2(false, false)); + fennec_test_run(bvec3(false, false, true) && true, bvec3(false, false, true)); + fennec_test_run(bvec4(false, false, true, true) && true, bvec4(false, false, true, true)); + + fennec_test_spacer(1); + + fennec_test_run(bvec2(false, false) && bvec2(false, true), bvec2(false, false)); + fennec_test_run(bvec3(false, false, true) && bvec3(false, true, false), bvec3(false, false, false)); + fennec_test_run(bvec4(false, false, true, true) && bvec4(false, true, false, true), bvec4(false, false, false, true)); + + fennec_test_spacer(2); + + fennec_test_run(bvec2(false, false) || true, bvec2(true, true)); + fennec_test_run(bvec3(false, false, true) || true, bvec3(true, true, true)); + fennec_test_run(bvec4(false, false, true, true) || true, bvec4(true, true, true, true)); + + fennec_test_spacer(1); + + fennec_test_run(bvec2(false, false) || bvec2(false, true), bvec2(false, true)); + fennec_test_run(bvec3(false, false, true) || bvec3(false, true, false), bvec3(false, true, true)); + fennec_test_run(bvec4(false, false, true, true) || bvec4(false, true, false, true), bvec4(false, true, true, true)); + + fennec_test_spacer(2); + + + + fennec_test_section("boolean operations"); + + fennec_test_spacer(1); + + fennec_test_run(0b0101 & ivec2(0b0001, 0b0010), ivec2(0b0001, 0b0000)); + fennec_test_run(0b0101 & ivec3(0b0001, 0b0010, 0b0011), ivec3(0b0001, 0b0000, 0b0001)); + fennec_test_run(0b0101 & ivec4(0b0001, 0b0010, 0b0011, 0b0100), ivec4(0b0001, 0b0000, 0b0001, 0b0100)); + + fennec_test_spacer(1); + + fennec_test_run(ivec2(0b0001, 0b0010) & 0b0101, ivec2(0b0001, 0b0000)); + fennec_test_run(ivec3(0b0001, 0b0010, 0b0011) & 0b0101, ivec3(0b0001, 0b0000, 0b0001)); + fennec_test_run(ivec4(0b0001, 0b0010, 0b0011, 0b0100) & 0b0101, ivec4(0b0001, 0b0000, 0b0001, 0b0100)); + + fennec_test_spacer(1); + + fennec_test_run(([]() -> ivec2 { ivec2 v(0b0001, 0b0010); return v &= 0b0101; }()), ivec2(0b0001, 0b0000)); + fennec_test_run(([]() -> ivec3 { ivec3 v(0b0001, 0b0010, 0b0011); return v &= 0b0101; }()), ivec3(0b0001, 0b0000, 0b0001)); + fennec_test_run(([]() -> ivec4 { ivec4 v(0b0001, 0b0010, 0b0011, 0b0100); return v &= 0b0101; }()), ivec4(0b0001, 0b0000, 0b0001, 0b0100)); + + fennec_test_spacer(1); + + fennec_test_run(ivec2(0b0001, 0b0010) & ivec2(0b1000, 0b0100), ivec2(0b0000)); + fennec_test_run(ivec3(0b0001, 0b0010, 0b0011) & ivec3(0b1000, 0b0100, 0b1100), ivec3(0b0000)); + fennec_test_run(ivec4(0b0001, 0b0010, 0b0011, 0b0100) & ivec4(0b1000, 0b0100, 0b1100, 0b0010), ivec4(0b0000)); + + fennec_test_spacer(1); + + fennec_test_run(([]() -> ivec2 { ivec2 v(0b0001, 0b0010); return v &= ivec2(0b1000, 0b0100); }()), ivec2(0b0000)); + fennec_test_run(([]() -> ivec3 { ivec3 v(0b0001, 0b0010, 0b0011); return v &= ivec3(0b1000, 0b0100, 0b1100); }()), ivec3(0b0000)); + fennec_test_run(([]() -> ivec4 { ivec4 v(0b0001, 0b0010, 0b0011, 0b0100); return v &= ivec4(0b1000, 0b0100, 0b1100, 0b0010); }()), ivec4(0b0000)); + + + fennec_test_spacer(2); + + + fennec_test_run(ivec2(0b0001, 0b0010) & ivec2(0b1000, 0b0100), ivec2(0b0000)); + fennec_test_run(ivec3(0b0001, 0b0010, 0b0011) & ivec3(0b1000, 0b0100, 0b1100), ivec3(0b0000)); + fennec_test_run(ivec4(0b0001, 0b0010, 0b0011, 0b0100) & ivec4(0b1000, 0b0100, 0b1100, 0b0010), ivec4(0b0000)); + + fennec_test_spacer(1); + + fennec_test_run(([]() -> ivec2 { ivec2 v(0b0001, 0b0010); return v &= ivec2(0b1000, 0b0100); }()), ivec2(0b0000)); + fennec_test_run(([]() -> ivec3 { ivec3 v(0b0001, 0b0010, 0b0011); return v &= ivec3(0b1000, 0b0100, 0b1100); }()), ivec3(0b0000)); + fennec_test_run(([]() -> ivec4 { ivec4 v(0b0001, 0b0010, 0b0011, 0b0100); return v &= ivec4(0b1000, 0b0100, 0b1100, 0b0010); }()), ivec4(0b0000)); + }