Compare commits

..

2 Commits

Author SHA1 Message Date
cbaf69310e Merge 2025-06-25 20:57:52 -04:00
d8954eafe5 - Added unit tests and debugged them 2025-06-25 20:55:57 -04:00
27 changed files with 812 additions and 167 deletions

View File

@@ -102,6 +102,10 @@ add_library(fennec STATIC
include/fennec/math/detail/__vector_traits.h include/fennec/math/detail/__vector_traits.h
source/debug/assert_impl.cpp 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 # add metaprogramming templates as a dependency and also force documentation to be generated when fennec is compiled

View File

@@ -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 <https://www.gnu.org/licenses/>.
// =====================================================================================================================
#ifndef FENNEC_LANG_DETAIL_INT_H
#define FENNEC_LANG_DETAIL_INT_H
#pragma push_macro("__cplusplus")
#undef __cplusplus
#include <stdint.h>
#pragma pop_macro("__cplusplus")
#endif // FENNEC_LANG_DETAIL_INT_H

View File

@@ -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 <https://www.gnu.org/licenses/>.
// =====================================================================================================================
#ifndef FENNEC_LANG_DETAIL_STDLIB_H
#define FENNEC_LANG_DETAIL_STDLIB_H
#pragma push_macro("__cplusplus")
#undef __cplusplus
extern "C" {
#include <stdlib.h>
}
#pragma pop_macro("__cplusplus")
#endif // FENNEC_LANG_DETAIL_STDLIB_H

View File

@@ -201,8 +201,6 @@
/// ///
/// ///
#include <cmath>
#include <fennec/lang/types.h> #include <fennec/lang/types.h>
#include <fennec/lang/type_traits.h> #include <fennec/lang/type_traits.h>

View File

@@ -203,23 +203,23 @@ template<typename SequenceT0, typename SequenceT1> using concat_sequence_t
// Internal ============================================================================================================ // Internal ============================================================================================================
// Implementation for Generating an \ref integer_sequence // Implementation for Generating an integer_sequence
template<typename T, size_t N> struct make_integer_sequence : concat_sequence_t<make_integer_sequence_t<T, N / 2>, make_integer_sequence_t<T, N - N / 2>>{}; template<typename T, size_t N> struct make_integer_sequence : concat_sequence_t<make_integer_sequence_t<T, N / 2>, make_integer_sequence_t<T, N - N / 2>>{};
// Base Case of \f$N=0\f$ // Base Case of N=0
template<typename T> struct make_integer_sequence<T, 0> : integer_sequence<T> {}; template<typename T> struct make_integer_sequence<T, 0> : integer_sequence<T> {};
// Base Case of \f$N=1\f$ // Base Case of N=1
template<typename T> struct make_integer_sequence<T, 1> : integer_sequence<T, 0>{}; template<typename T> struct make_integer_sequence<T, 1> : integer_sequence<T, 0>{};
// Implementation for Generating an \ref integer_sequence // Implementation for Generating an index_sequence
template<size_t N> struct make_index_sequence : concat_sequence_t<make_index_sequence_t<N / 2>, make_index_sequence_t<N - N / 2>>{}; template<size_t N> struct make_index_sequence : concat_sequence_t<make_index_sequence_t<N / 2>, make_index_sequence_t<N - N / 2>>{};
// Base Case of \f$N=0\f$ // Base Case of N=0
template<> struct make_index_sequence<0> : index_sequence<> {}; 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>{}; template<> struct make_index_sequence<1> : index_sequence<0>{};

View File

@@ -215,7 +215,7 @@
/// ///
/// ///
#include <cstdint> #include <fennec/lang/detail/__int.h>
namespace fennec namespace fennec
{ {

View File

@@ -72,10 +72,10 @@ namespace fennec
/// \tparam T base type of the object /// \tparam T base type of the object
/// \param x reference to the object /// \param x reference to the object
/// \returns /// \returns
template<typename T> constexpr T&& forward(remove_reference_t<T>& x) noexcept { return x; } template<typename T> constexpr T&& forward(remove_reference_t<T>& x) noexcept { return static_cast<T&&>(x); }
// specialization for T&& // specialization for T&&
template<typename T> constexpr T&& forward(remove_reference_t<T>&& x) noexcept { return x; } template<typename T> constexpr T&& forward(remove_reference_t<T>&& x) noexcept { return static_cast<T&&>(x); }
/// ///

View File

@@ -274,8 +274,7 @@
/// ///
/// ///
#include <fennec/math/detail/__math.h>
#include <cmath>
#include <fennec/math/vector.h> #include <fennec/math/vector.h>
@@ -357,7 +356,7 @@ constexpr vector<genType, i...> sign(const vector<genType, i...>& x)
/// \param x input value /// \param x input value
template<typename genType> template<typename genType>
constexpr genType floor(genType x) constexpr genType floor(genType x)
{ return std::floor(x); } { return ::floor(x); }
// Vector Specializations ---------------------------------------------------------------------------------------------- // Vector Specializations ----------------------------------------------------------------------------------------------
@@ -380,7 +379,7 @@ constexpr vector<genType, i...> floor(const vector<genType, i...>& x)
/// \param x input value /// \param x input value
template<typename genType> template<typename genType>
constexpr genType ceil(genType x) constexpr genType ceil(genType x)
{ return std::ceil(x); } { return ::ceil(x); }
// Vector Specializations ---------------------------------------------------------------------------------------------- // Vector Specializations ----------------------------------------------------------------------------------------------
@@ -403,7 +402,7 @@ constexpr vector<genType, i...> ceil(const vector<genType, i...>& x)
/// ///
/// \param x input value /// \param x input value
template<typename genType> constexpr genType round(genType x) template<typename genType> constexpr genType round(genType x)
{ return std::round(x); } { return ::round(x); }
// Vector Specializations ---------------------------------------------------------------------------------------------- // Vector Specializations ----------------------------------------------------------------------------------------------
@@ -451,7 +450,7 @@ constexpr vector<genType, i...> roundEven(const vector<genType, i...>& x)
/// \param x input value /// \param x input value
template<typename genType> template<typename genType>
constexpr genType trunc(genType x) constexpr genType trunc(genType x)
{ return std::trunc(x); } { return ::trunc(x); }
// Vector Specializations ---------------------------------------------------------------------------------------------- // Vector Specializations ----------------------------------------------------------------------------------------------
@@ -482,7 +481,7 @@ constexpr vector<genType, i...> trunc(const vector<genType, i...>& x)
/// \param x input value /// \param x input value
template<typename genType> template<typename genType>
constexpr genType fract(genType x) constexpr genType fract(genType x)
{ return x - std::floor(x); } { return x - ::floor(x); }
// Vector Specializations ---------------------------------------------------------------------------------------------- // Vector Specializations ----------------------------------------------------------------------------------------------
@@ -534,7 +533,7 @@ constexpr vector<genType, i...> mod(const vector<genType, i...>& x, const vector
/// \param i integral out /// \param i integral out
template<typename genType> template<typename genType>
constexpr genType modf(genType x, genType& i) constexpr genType modf(genType x, genType& i)
{ return std::modf(x, &i); } { return ::modf(x, &i); }
// Vector Specializations ---------------------------------------------------------------------------------------------- // Vector Specializations ----------------------------------------------------------------------------------------------
@@ -562,7 +561,7 @@ constexpr vector<genType, i...> modf(const vector<genType, i...>& x, vector<genT
/// \param x input value /// \param x input value
template<typename genType, typename genBType = bool_t> requires(is_bool_v<genBType>) template<typename genType, typename genBType = bool_t> requires(is_bool_v<genBType>)
constexpr genBType isnan(genType x) constexpr genBType isnan(genType x)
{ return std::isnan(x); } { return ::isnan(x); }
// Vector Specializations ---------------------------------------------------------------------------------------------- // Vector Specializations ----------------------------------------------------------------------------------------------
@@ -585,7 +584,7 @@ constexpr vector<genBType, i...> isnan(const vector<genType, i...>& x)
/// \param x input value /// \param x input value
template<typename genType, typename genBType = bool_t> requires(is_bool_v<genBType>) template<typename genType, typename genBType = bool_t> requires(is_bool_v<genBType>)
constexpr genBType isinf(genType x) constexpr genBType isinf(genType x)
{ return std::isinf(x); } { return ::isinf(x); }
// Vector Specializations ---------------------------------------------------------------------------------------------- // Vector Specializations ----------------------------------------------------------------------------------------------
@@ -684,7 +683,7 @@ constexpr vector<genType, i...> uintBitsToFloat(const vector<genUType, i...>& x)
/// \param c the addend /// \param c the addend
template<typename genType> template<typename genType>
constexpr genType fma(genType a, genType b, genType c) constexpr genType fma(genType a, genType b, genType c)
{ return std::fma(a, b, c); } { return ::fma(a, b, c); }
// Vector Specializations ---------------------------------------------------------------------------------------------- // Vector Specializations ----------------------------------------------------------------------------------------------
@@ -713,7 +712,7 @@ constexpr vector<genType, i...> fma(const vector<genType, i...>& a, const vector
/// \param exp The variable to store the exponent in /// \param exp The variable to store the exponent in
template<typename genType, typename genIType = int_t> requires(is_integral_v<genIType>) template<typename genType, typename genIType = int_t> requires(is_integral_v<genIType>)
constexpr genType frexp(genType x, genIType& exp) constexpr genType frexp(genType x, genIType& exp)
{ return std::frexp(x, &exp); } { return ::frexp(x, &exp); }
// Vector Specializations ---------------------------------------------------------------------------------------------- // Vector Specializations ----------------------------------------------------------------------------------------------
@@ -744,7 +743,7 @@ constexpr vector<genType, i...> frexp(const vector<genType, i...>& x, vector<gen
/// \param exp The exponent /// \param exp The exponent
template<typename genType, typename genIType = int_t> requires(is_integral_v<genIType>) template<typename genType, typename genIType = int_t> requires(is_integral_v<genIType>)
constexpr genType ldexp(genType x, genIType exp) constexpr genType ldexp(genType x, genIType exp)
{ return std::ldexp(x, exp); } { return ::ldexp(x, exp); }
// Vector Specializations ---------------------------------------------------------------------------------------------- // Vector Specializations ----------------------------------------------------------------------------------------------

View File

@@ -31,7 +31,7 @@ template<typename ScalarT, size_t RowsV, size_t...ColIndicesV> struct matrix; //
template<typename ScalarT, size_t SizeV> using vec template<typename ScalarT, size_t SizeV> using vec
= decltype(detail::__gen_vector<vector, ScalarT>(make_index_sequence<SizeV>{})); // Gets the type returned by this function = decltype(detail::__gen_vector<vector, ScalarT>(make_index_sequence<SizeV>{})); // Gets the type returned by this function
template<typename ScalarT, size_t RowsV, size_t ColsV> using mat template<typename ScalarT, size_t ColsV, size_t RowsV> using mat
= decltype(detail::__gen_matrix<matrix, ScalarT, RowsV>(make_index_sequence<ColsV>{})); // Gets the type returned by this function = decltype(detail::__gen_matrix<matrix, ScalarT, RowsV>(make_index_sequence<ColsV>{})); // Gets the type returned by this function
} }

View File

@@ -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 <https://www.gnu.org/licenses/>.
// =====================================================================================================================
#ifndef FENNEC_MATH_DETAIL_MATH_H
#define FENNEC_MATH_DETAIL_MATH_H
#pragma push_macro("__cplusplus")
#undef __cplusplus
#include <math.h>
#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

View File

@@ -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 <https://www.gnu.org/licenses/>.
// =====================================================================================================================
#ifndef FENNEC_MATH_DETAIL_MATRIX_H
#define FENNEC_MATH_DETAIL_MATRIX_H
#include <fennec/math/detail/__fwd.h>
namespace fennec
{
// specialization for mat2
template<typename scalar, size_t rows, size_t...cols> requires(rows == 2 && sizeof...(cols) == 2)
constexpr scalar determinant(const matrix<scalar, rows, cols...>& m)
{
return m[0][0] * m[1][1] - m[1][0] * m[0][1];
}
// specialization for mat3
template<typename scalar, size_t rows, size_t...cols> requires(rows == 3 && sizeof...(cols) == 3)
constexpr scalar determinant(const matrix<scalar, rows, cols...>& 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<typename scalar, size_t rows, size_t...cols> requires(rows == 4 && sizeof...(cols) == 4)
constexpr scalar determinant(const matrix<scalar, rows, cols...>& 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<typename scalar, size_t rows, size_t...cols> requires(rows == 2 && sizeof...(cols) == 2)
constexpr matrix<scalar, rows, cols...> inverse(const matrix<scalar, rows, cols...>& m)
{
scalar di = scalar(1) / fennec::determinant(m);
return matrix<scalar, rows, cols...>(
m[1][1] * di, -m[0][1] * di, -m[1][0] * di, m[0][0] * di
);
}
// specialization for mat3
template<typename scalar, size_t rows, size_t...cols> requires(rows == 3 && sizeof...(cols) == 3)
constexpr matrix<scalar, rows, cols...> inverse(const matrix<scalar, rows, cols...>& m)
{
scalar di = scalar(1) / fennec::determinant(m);
matrix<scalar, rows, cols...> 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<typename scalar, size_t rows, size_t...cols> requires(rows == 4 && sizeof...(cols) == 4)
constexpr matrix<scalar, rows, cols...> inverse(const matrix<scalar, rows, cols...>& 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<scalar, rows, cols...> 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

View File

@@ -32,11 +32,6 @@
#ifndef FENNEC_MATH_EXPONENTIAL_H #ifndef FENNEC_MATH_EXPONENTIAL_H
#define FENNEC_MATH_EXPONENTIAL_H #define FENNEC_MATH_EXPONENTIAL_H
#pragma push_macro("__cplusplus")
#undef __cplusplus
#include <math.h>
#pragma pop_macro("__cplusplus")
/// ///
/// ///
/// ///
@@ -93,6 +88,8 @@
/// ///
/// ///
#include <fennec/math/detail/__math.h>
namespace fennec namespace fennec
{ {
@@ -206,7 +203,7 @@ template<typename genType, size_t...i> constexpr genType sqrt(const vector<genTy
/// ///
/// \param x the input value /// \param x the input value
template<typename genType> constexpr genType inversesqrt(genType x) template<typename genType> constexpr genType inversesqrt(genType x)
{ return 1.0f / std::sqrt(x); } { return 1.0f / ::sqrt(x); }
template<typename genType, size_t...i> template<typename genType, size_t...i>
constexpr vector<genType, i...> inversesqrt(const vector<genType, i...>& x) constexpr vector<genType, i...> inversesqrt(const vector<genType, i...>& x)

View File

@@ -32,9 +32,6 @@
#ifndef FENNEC_MATH_GEOMETRIC_H #ifndef FENNEC_MATH_GEOMETRIC_H
#define FENNEC_MATH_GEOMETRIC_H #define FENNEC_MATH_GEOMETRIC_H
#include <fennec/math/vector.h>
#include <fennec/math/exponential.h>
/// ///
/// ///
@@ -111,6 +108,9 @@
/// ///
/// ///
#include <fennec/math/vector.h>
#include <fennec/math/exponential.h>
namespace fennec namespace fennec
{ {

View File

@@ -44,6 +44,7 @@
/// ///
#include <fennec/math/detail/__fwd.h> #include <fennec/math/detail/__fwd.h>
#include <fennec/math/detail/__matrix.h>
#include <fennec/containers/array.h> #include <fennec/containers/array.h>
@@ -56,9 +57,6 @@ namespace fennec
/// ///
/// \brief returns a **copy** of the column \f$i\f$ of matrix \f$m\f$ /// \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 m the matrix
/// \param i the index of the row /// \param i the index of the row
/// \returns a **copy** of the column at index \f$i\f$ /// \returns a **copy** of the column at index \f$i\f$
@@ -69,9 +67,6 @@ constexpr vec<scalar, rows> column(const matrix<scalar, rows, cols...>& m, size_
/// ///
/// \brief returns a **copy** of the row \f$i\f$ of matrix \f$m\f$ /// \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 m the matrix
/// \param i the index of the row /// \param i the index of the row
/// \returns a **copy** of the row at index \f$i\f$ /// \returns a **copy** of the row at index \f$i\f$
@@ -80,7 +75,8 @@ constexpr vec<scalar, sizeof...(cols)> row(const matrix<scalar, rows, cols...>&
{ return vec<scalar, sizeof...(cols)>(m[cols][i]...); } { return vec<scalar, sizeof...(cols)>(m[cols][i]...); }
template<typename ScalarT> using tmat2x2 = mat<ScalarT, 2, 2>; ///< helper for creating 2x2 matrices of the specified type. template<typename ScalarT>
using tmat2x2 = mat<ScalarT, 2, 2>; ///< helper for creating 2x2 matrices of the specified type.
template<typename ScalarT> using tmat2x3 = mat<ScalarT, 2, 3>; ///< helper for creating 2x3 matrices of the specified type. template<typename ScalarT> using tmat2x3 = mat<ScalarT, 2, 3>; ///< helper for creating 2x3 matrices of the specified type.
template<typename ScalarT> using tmat2x4 = mat<ScalarT, 2, 4>; ///< helper for creating 2x4 matrices of the specified type. template<typename ScalarT> using tmat2x4 = mat<ScalarT, 2, 4>; ///< helper for creating 2x4 matrices of the specified type.
template<typename ScalarT> using tmat3x2 = mat<ScalarT, 3, 2>; ///< helper for creating 3x2 matrices of the specified type. template<typename ScalarT> using tmat3x2 = mat<ScalarT, 3, 2>; ///< helper for creating 3x2 matrices of the specified type.
@@ -92,7 +88,7 @@ template<typename ScalarT> using tmat4x4 = mat<ScalarT, 4, 4>; ///< helper for c
using mat2 = tmat2x2<float_t>; ///< Specification for glsl float matrices using mat2 = tmat2x2<float_t>; ///< Specification for glsl float matrices
using mat3 = tmat3x3<float_t>; ///< Specification for glsl float matrices using mat3 = tmat3x3<float_t>; ///< Specification for glsl float matrices
using mat4 = tmat3x3<float_t>; ///< Specification for glsl float matrices using mat4 = tmat4x4<float_t>; ///< Specification for glsl float matrices
using mat2x2 = tmat2x2<float_t>; ///< Specification for sized glsl float matrices using mat2x2 = tmat2x2<float_t>; ///< Specification for sized glsl float matrices
using mat2x3 = tmat2x3<float_t>; ///< Specification for sized glsl float matrices using mat2x3 = tmat2x3<float_t>; ///< Specification for sized glsl float matrices
@@ -120,6 +116,70 @@ using dmat4x4 = tmat4x4<double_t>; ///< 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].<br><br>
/// 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<typename scalar, size_t rows, size_t...cols>
constexpr matrix<scalar, rows, cols...> matrixCompMult(const matrix<scalar, rows, cols...>& x, const matrix<scalar, rows, cols...>& y) noexcept
{ return matrix<scalar, rows, cols...>(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<typename scalar, size_t...s0, size_t...s1>
constexpr matrix<scalar, sizeof...(s0), s1...> outerProduct(const vector<scalar, s0...>& c, const vector<scalar, s1...>& r) noexcept
{
return matrix<scalar, sizeof...(s0), s1...>(
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<typename scalar, size_t rows, size_t...cols>
constexpr mat<scalar, rows, sizeof...(cols)> transpose(const matrix<scalar, rows, cols...>& m) noexcept
{
return [m]<size_t...i>(index_sequence<i...>) -> mat<scalar, rows, sizeof...(cols)> {
return mat<scalar, rows, sizeof...(cols)>(fennec::row(m, i) ...);
}(make_index_sequence<rows>{});
}
///
/// \brief Returns the determinant of m.
/// \param m the matrix
/// \returns the determinant of m.
template<typename scalar, size_t rows, size_t...cols>
constexpr scalar determinant(const matrix<scalar, rows, cols...>&) noexcept
{
// ReSharper disable once CppStaticAssertFailure
static_assert(false, "implementation undefined");
return 0;
}
template<typename scalar, size_t rows, size_t...cols>
constexpr matrix<scalar, rows, cols...> inverse(const matrix<scalar, rows, cols...>&) noexcept
{
// ReSharper disable once CppStaticAssertFailure
static_assert(false, "implementation undefined");
return 1;
}
/// ///
/// \brief /// \brief
/// \tparam ScalarT /// \tparam ScalarT
@@ -196,7 +256,6 @@ struct matrix
constexpr matrix(const matrix_t& mat) constexpr matrix(const matrix_t& mat)
: data{ mat.data } {} : data{ mat.data } {}
/// ///
/// \brief move constructor /// \brief move constructor
/// ///
@@ -232,7 +291,7 @@ struct matrix
/// \param args /// \param args
template<typename...ArgsT> requires(total_component_count_v<ArgsT...> == num_components) template<typename...ArgsT> requires(total_component_count_v<ArgsT...> == num_components)
constexpr matrix(ArgsT&&...args) constexpr matrix(ArgsT&&...args)
{ matrix::__construct(std::forward<ArgsT>(args)...); } { matrix::__construct(fennec::forward<ArgsT>(args)...); }
/// @} /// @}
@@ -279,12 +338,12 @@ struct matrix
/// \param i the index /// \param i the index
/// \returns the column at index \f$i\f$ /// \returns the column at index \f$i\f$
constexpr const column_t& operator[](size_t i) const 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 /// \copydetails matrix::operator()(size_t, size_t) const
constexpr scalar_t& operator()(size_t i, size_t j) 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 /// \brief returns the cell in row \p j column \p i
@@ -292,7 +351,7 @@ struct matrix
/// \param j the row /// \param j the row
/// \returns the cell at the specified index. /// \returns the cell at the specified index.
constexpr scalar_t operator()(size_t i, size_t j) const 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 lhs the rows to multiply with
/// \param rhs the columns to multiply with /// \param rhs the columns to multiply with
constexpr friend matrix_t operator*(const matrix_t& lhs, const transpose_t& rhs) constexpr friend matrix_t operator*(const matrix_t& lhs, const transpose_t& rhs)
{ return [lhs, rhs]<size_t...i>(index_sequence<i...>) -> matrix_t {
{ return matrix_t(rhs * fennec::row(lhs, i)...); }(make_index_sequence<rows>{}); } return [lhs, rhs]<size_t...i>(index_sequence<i...>) -> matrix_t {
return matrix_t(rhs * fennec::row(lhs, i)...);
}(make_index_sequence<rows>{});
}
/// @} /// @}
@@ -606,26 +668,33 @@ private:
template<size_t i0 = 0, typename HeadT, typename...ArgsT> template<size_t i0 = 0, typename HeadT, typename...ArgsT>
constexpr void __construct(HeadT&& head, ArgsT&&...args) constexpr void __construct(HeadT&& head, ArgsT&&...args)
{ {
matrix::__insert(head); matrix::__insert<i0>(head);
matrix::__construct<i0 + component_count_v<HeadT>>(std::forward<ArgsT>(args)...); matrix::__construct<i0 + component_count_v<HeadT>>(std::forward<ArgsT>(args)...);
} }
template<size_t i0 = 0> template<size_t i0 = 0>
constexpr void __insert(scalar_t s) constexpr void __insert(scalar_t s)
{ data[i0 / columns][i0 % columns] = s; } { data[i0 / rows][i0 % rows] = s; }
template<size_t i0 = 0, typename OScalarT> requires(is_arithmetic_v<OScalarT>) template<size_t i0 = 0, typename OScalarT> requires(is_arithmetic_v<OScalarT>)
constexpr void __insert(OScalarT s) constexpr void __insert(OScalarT s)
{ data[i0 / columns][i0 % columns] = scalar_t(s); } { data[i0 / rows][i0 % rows] = scalar_t(s); }
template<size_t i0 = 0, size_t...i> template<size_t i0 = 0, size_t...i>
constexpr void __insert(const vector<scalar_t, i...>& v) constexpr void __insert(const vector<scalar_t, i...>& v)
{ (matrix::__insert<i0 + i>(v[i]), ...); } { (matrix::__insert<i0 + i>(v[i]), ...); }
template<size_t i0 = 0, typename OScalarT, size_t...i>
constexpr void __insert(const vector<OScalarT, i...>& v)
{ (matrix::__insert<i0 + i>(v[i]), ...); }
}; };
// Internal ============================================================================================================
} }

View File

@@ -31,8 +31,6 @@
#ifndef FENNEC_MATH_RELATIONAL_H #ifndef FENNEC_MATH_RELATIONAL_H
#define FENNEC_MATH_RELATIONAL_H #define FENNEC_MATH_RELATIONAL_H
#include <fennec/lang/types.h>
/// ///
/// \page fennec_math_relational Relational /// \page fennec_math_relational Relational
/// ///
@@ -114,7 +112,7 @@
/// ///
/// ///
// TODO: Document #include <fennec/lang/types.h>
namespace fennec namespace fennec
{ {

View File

@@ -31,8 +31,6 @@
#ifndef FENNEC_MATH_SCALAR_H #ifndef FENNEC_MATH_SCALAR_H
#define FENNEC_MATH_SCALAR_H #define FENNEC_MATH_SCALAR_H
#include <fennec/lang/types.h>
/// ///
/// ///
/// ///
@@ -59,6 +57,8 @@
/// ///
/// ///
#include <fennec/lang/types.h>
#include <fennec/math/detail/__fwd.h> #include <fennec/math/detail/__fwd.h>
#include <fennec/math/detail/__types.h> #include <fennec/math/detail/__types.h>

View File

@@ -42,6 +42,7 @@
/// ///
#include <fennec/lang/sequences.h> #include <fennec/lang/sequences.h>
#include <fennec/math/swizzle_storage.h> #include <fennec/math/swizzle_storage.h>
namespace fennec namespace fennec

View File

@@ -147,7 +147,7 @@
/// ///
/// ///
#include <cmath> #include <fennec/math/detail/__math.h>
namespace fennec namespace fennec
{ {
@@ -209,7 +209,7 @@ constexpr vector<genType, i...> degrees(const vector<genType, i...>& radians)
/// \param x the angle \f$\theta\f$ in \f$radians\f$ /// \param x the angle \f$\theta\f$ in \f$radians\f$
template<typename genType> template<typename genType>
constexpr genType sin(genType x) constexpr genType sin(genType x)
{ return std::sin(x); } { return ::sin(x); }
template<typename genType, size_t...i> template<typename genType, size_t...i>
constexpr vector<genType, i...> sin(const vector<genType, i...>& x) constexpr vector<genType, i...> sin(const vector<genType, i...>& x)
@@ -226,7 +226,7 @@ constexpr vector<genType, i...> sin(const vector<genType, i...>& x)
/// \param x the angle \f$\theta\f$ in \f$radians\f$ /// \param x the angle \f$\theta\f$ in \f$radians\f$
template<typename genType> template<typename genType>
constexpr genType cos(genType x) constexpr genType cos(genType x)
{ return std::cos(x); } { return ::cos(x); }
template<typename genType, size_t...i> template<typename genType, size_t...i>
constexpr vector<genType, i...> cos(const vector<genType, i...>& x) constexpr vector<genType, i...> cos(const vector<genType, i...>& x)
@@ -243,7 +243,7 @@ constexpr vector<genType, i...> cos(const vector<genType, i...>& x)
/// \param x The Angle \f$\theta\f$ in \f$radians\f$ /// \param x The Angle \f$\theta\f$ in \f$radians\f$
template<typename genType> template<typename genType>
constexpr genType tan(genType x) constexpr genType tan(genType x)
{ return std::tan(x); } { return ::tan(x); }
template<typename genType, size_t...i> template<typename genType, size_t...i>
constexpr vector<genType, i...> tan(const vector<genType, i...>& x) constexpr vector<genType, i...> tan(const vector<genType, i...>& x)
@@ -267,7 +267,7 @@ constexpr vector<genType, i...> tan(const vector<genType, i...>& x)
/// \param x The Sine Value produced by \f$\theta\f$ /// \param x The Sine Value produced by \f$\theta\f$
template<typename genType> template<typename genType>
constexpr genType asin(genType x) constexpr genType asin(genType x)
{ return std::asin(x); } { return ::asin(x); }
template<typename genType, size_t...i> template<typename genType, size_t...i>
constexpr vector<genType, i...> asin(const vector<genType, i...>& x) constexpr vector<genType, i...> asin(const vector<genType, i...>& x)
@@ -285,7 +285,7 @@ constexpr vector<genType, i...> asin(const vector<genType, i...>& x)
/// \param x The Cosine Value produced by \f$\theta\f$ /// \param x The Cosine Value produced by \f$\theta\f$
template<typename genType> template<typename genType>
constexpr genType acos(genType x) constexpr genType acos(genType x)
{ return std::acos(x); } { return ::acos(x); }
template<typename genType, size_t...i> template<typename genType, size_t...i>
constexpr vector<genType, i...> acos(const vector<genType, i...>& x) constexpr vector<genType, i...> acos(const vector<genType, i...>& x)
@@ -303,7 +303,7 @@ constexpr vector<genType, i...> acos(const vector<genType, i...>& x)
/// \param y_over_x The Cosine Value produced by \f$\theta\f$ /// \param y_over_x The Cosine Value produced by \f$\theta\f$
template<typename genType> template<typename genType>
constexpr genType atan(genType y_over_x) constexpr genType atan(genType y_over_x)
{ return std::atan(y_over_x); } { return ::atan(y_over_x); }
template<typename genType, size_t...i> template<typename genType, size_t...i>
constexpr vector<genType, i...> atan(const vector<genType, i...>& y_over_x) constexpr vector<genType, i...> atan(const vector<genType, i...>& y_over_x)
@@ -322,7 +322,7 @@ constexpr vector<genType, i...> atan(const vector<genType, i...>& y_over_x)
/// \param x The Cosine Value produced by \f$\theta\f$ /// \param x The Cosine Value produced by \f$\theta\f$
template<typename genType> template<typename genType>
constexpr genType atan(genType y, genType x) constexpr genType atan(genType y, genType x)
{ return std::atan2(y, x); } { return ::atan2(y, x); }
template<typename genType, size_t...i> template<typename genType, size_t...i>
constexpr vector<genType, i...> atan(const vector<genType, i...>& y, const vector<genType, i...>& x) constexpr vector<genType, i...> atan(const vector<genType, i...>& y, const vector<genType, i...>& x)
@@ -345,7 +345,7 @@ constexpr vector<genType, i...> atan(const vector<genType, i...>& y, const vecto
/// \param x The Hyperbolic Angle \f$\alpha\f$ /// \param x The Hyperbolic Angle \f$\alpha\f$
template<typename genType> template<typename genType>
constexpr genType sinh(genType x) constexpr genType sinh(genType x)
{ return std::sinh(x); } { return ::sinh(x); }
template<typename genType, size_t...i> template<typename genType, size_t...i>
constexpr vector<genType, i...> sinh(const vector<genType, i...>& x) constexpr vector<genType, i...> sinh(const vector<genType, i...>& x)
@@ -360,7 +360,7 @@ constexpr vector<genType, i...> sinh(const vector<genType, i...>& x)
/// \param x The Hyperbolic Angle \f$\alpha\f$ /// \param x The Hyperbolic Angle \f$\alpha\f$
template<typename genType> template<typename genType>
constexpr genType cosh(genType x) constexpr genType cosh(genType x)
{ return std::cosh(x); } { return ::cosh(x); }
template<typename genType, size_t...i> template<typename genType, size_t...i>
constexpr vector<genType, i...> cosh(const vector<genType, i...>& x) constexpr vector<genType, i...> cosh(const vector<genType, i...>& x)
@@ -375,7 +375,7 @@ constexpr vector<genType, i...> cosh(const vector<genType, i...>& x)
/// \param x The Hyperbolic Angle \f$\alpha\f$ /// \param x The Hyperbolic Angle \f$\alpha\f$
template<typename genType, size_t...i> template<typename genType, size_t...i>
constexpr genType tanh(genType x) constexpr genType tanh(genType x)
{ return std::tanh(x); } { return ::tanh(x); }
template<typename genType, size_t...i> template<typename genType, size_t...i>
constexpr vector<genType, i...> tanh(const vector<genType, i...>& x) constexpr vector<genType, i...> tanh(const vector<genType, i...>& x)
@@ -396,7 +396,7 @@ constexpr vector<genType, i...> tanh(const vector<genType, i...>& x)
/// \param x the hyperbolic angle \f$\alpha\f$ /// \param x the hyperbolic angle \f$\alpha\f$
template<typename genType, size_t...i> template<typename genType, size_t...i>
constexpr genType asinh(genType x) constexpr genType asinh(genType x)
{ return std::asinh(x); } { return ::asinh(x); }
template<typename genType, size_t...i> template<typename genType, size_t...i>
constexpr vector<genType, i...> asinh(const vector<genType, i...>& x) constexpr vector<genType, i...> asinh(const vector<genType, i...>& x)
@@ -412,7 +412,7 @@ constexpr vector<genType, i...> asinh(const vector<genType, i...>& x)
/// \param x the hyperbolic angle \f$\alpha\f$ /// \param x the hyperbolic angle \f$\alpha\f$
template<typename genType, size_t...i> template<typename genType, size_t...i>
constexpr genType acosh(genType x) constexpr genType acosh(genType x)
{ return std::acosh(x); } { return ::acosh(x); }
template<typename genType, size_t...i> template<typename genType, size_t...i>
constexpr vector<genType, i...> acosh(const vector<genType, i...>& x) constexpr vector<genType, i...> acosh(const vector<genType, i...>& x)
@@ -428,7 +428,7 @@ constexpr vector<genType, i...> acosh(const vector<genType, i...>& x)
/// \param x The Hyperbolic Angle \f$\alpha\f$ /// \param x The Hyperbolic Angle \f$\alpha\f$
template<typename genType, size_t...i> template<typename genType, size_t...i>
constexpr genType atanh(genType x) constexpr genType atanh(genType x)
{ return std::atanh(x); } { return ::atanh(x); }
template<typename genType, size_t...i> template<typename genType, size_t...i>
constexpr vector<genType, i...> atanh(const vector<genType, i...>& x) constexpr vector<genType, i...> atanh(const vector<genType, i...>& x)

View File

@@ -468,7 +468,7 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// \param lhs left hand side /// \param lhs left hand side
/// \param rhs right hand side /// \param rhs right hand side
constexpr friend vector_t operator+(scalar_t lhs, const vector_t& rhs) 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 /// \brief \ref fennec_math_scalar "scalar" - \ref fennec_math_vector "vector" subtraction operator
@@ -478,7 +478,7 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// \param lhs left hand side /// \param lhs left hand side
/// \param rhs right hand side /// \param rhs right hand side
constexpr friend vector_t operator-(scalar_t lhs, const vector_t& rhs) 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 /// \brief \ref fennec_math_scalar "scalar" - \ref fennec_math_vector "vector" multiplication operator
@@ -796,17 +796,7 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// \param rhs Right 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$ /// \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<scalar_t>) constexpr friend vector_t operator&(scalar_t rhs, const vector_t& lhs) requires(is_integral_v<scalar_t>)
{ return vector_t((lhs & rhs[IndicesV]) ...); } { return vector_t((lhs[IndicesV] & rhs) ...); }
///
/// \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<scalar_t>)
{ return ((lhs[IndicesV] &= rhs), ..., lhs); }
/// ///
/// \brief \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" bitwise and operator /// \brief \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" bitwise and operator
@@ -819,13 +809,13 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
{ return vector_t((lhs[IndicesV] & rhs) ...); } { 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 /// \details
/// \param lhs Left Hand Side of the Expression /// \param lhs Left Hand Side of the Expression
/// \param rhs Right 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$ /// \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<scalar_t>) constexpr friend vector_t operator&=(vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>)
{ return ((lhs[IndicesV] &= rhs), ..., lhs); } { return ((lhs[IndicesV] &= rhs), ..., lhs); }
/// ///
@@ -838,6 +828,16 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
constexpr friend vector_t operator&(const vector_t& lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>) constexpr friend vector_t operator&(const vector_t& lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>)
{ 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 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<scalar_t>)
{ return ((lhs[IndicesV] &= rhs[IndicesV]), ..., lhs); }
/// ///
@@ -850,16 +850,6 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
constexpr friend vector_t operator|(scalar_t rhs, const vector_t& lhs) requires(is_integral_v<scalar_t>) constexpr friend vector_t operator|(scalar_t rhs, const vector_t& lhs) requires(is_integral_v<scalar_t>)
{ return vector_t((lhs & rhs[IndicesV]) ...); } { 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<scalar_t>)
{ return ((lhs[IndicesV] |= rhs), ..., lhs); }
/// ///
/// \brief \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" bitwise or operator /// \brief \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" bitwise or operator
/// ///
@@ -871,13 +861,13 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
{ return vector_t((lhs[IndicesV] | rhs) ...); } { 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 /// \details
/// \param lhs Left Hand Side of the Expression /// \param lhs Left Hand Side of the Expression
/// \param rhs Right 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$ /// \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<scalar_t>) constexpr friend vector_t operator|=(vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>)
{ return ((lhs[IndicesV] |= rhs), ..., lhs); } { return ((lhs[IndicesV] |= rhs), ..., lhs); }
/// ///
@@ -888,7 +878,17 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// \param rhs Right 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$ /// \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<scalar_t>) constexpr friend vector_t operator|(const vector_t& lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>)
{ 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<scalar_t>)
{ return ((lhs[IndicesV] |= rhs), ..., lhs); }
@@ -900,14 +900,6 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
constexpr friend vector_t operator^(scalar_t rhs, const vector_t& lhs) requires(is_integral_v<scalar_t>) constexpr friend vector_t operator^(scalar_t rhs, const vector_t& lhs) requires(is_integral_v<scalar_t>)
{ return vector_t((lhs ^ rhs[IndicesV]) ...); } { 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<scalar_t>)
{ return ((lhs[IndicesV] ^= rhs), ..., lhs); }
/// ///
/// \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" bitwise xor operator /// \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" bitwise xor operator
/// \param lhs Left Hand Side of the Expression /// \param lhs Left Hand Side of the Expression
@@ -917,11 +909,11 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
{ return vector_t((lhs[IndicesV] ^ rhs) ...); } { 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 lhs Left Hand Side of the Expression
/// \param rhs Right 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$ /// \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<scalar_t>) constexpr friend vector_t operator^=(vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>)
{ return ((lhs[IndicesV] ^= rhs), ..., lhs); } { return ((lhs[IndicesV] ^= rhs), ..., lhs); }
/// ///
@@ -932,15 +924,15 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
constexpr friend vector_t operator^(const vector_t& lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>) constexpr friend vector_t operator^(const vector_t& lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>)
{ return vector_t((lhs[IndicesV] ^ rhs[IndicesV]) ...); } { 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 lhs Left Hand Side of the Expression
/// \param rhs Right 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$ /// \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<scalar_t>) constexpr friend vector_t operator^=(vector_t& lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>)
{ return ((lhs[IndicesV] <<= rhs), ..., lhs); } { return ((lhs[IndicesV] ^= rhs), ..., lhs); }
/// ///
/// \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" bitwise or operator /// \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" bitwise or operator
@@ -951,11 +943,11 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
{ return vector_t((lhs[IndicesV] << rhs) ...); } { 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 lhs Left Hand Side of the Expression
/// \param rhs Right 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$ /// \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<scalar_t>) constexpr friend vector_t operator<<=(vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>)
{ return ((lhs[IndicesV] <<= rhs), ..., lhs); } { return ((lhs[IndicesV] <<= rhs), ..., lhs); }
/// ///
@@ -966,15 +958,15 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
constexpr friend vector_t operator<<(const vector_t& lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>) constexpr friend vector_t operator<<(const vector_t& lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>)
{ return vector_t((lhs[IndicesV] << rhs[IndicesV]) ...); } { 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 lhs Left Hand Side of the Expression
/// \param rhs Right 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$ /// \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<scalar_t>) constexpr friend vector_t operator<<=(vector_t& lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>)
{ return ((lhs[IndicesV] >>= rhs), ..., lhs); } { return ((lhs[IndicesV] <<= rhs), ..., lhs); }
/// ///
/// \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" bitwise or operator /// \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" bitwise or operator
@@ -985,11 +977,11 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
{ return vector_t((lhs[IndicesV] >> rhs) ...); } { 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 lhs Left Hand Side of the Expression
/// \param rhs Right 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$ /// \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<scalar_t>) constexpr friend vector_t operator>>=(vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>)
{ return ((lhs[IndicesV] >>= rhs), ..., lhs); } { return ((lhs[IndicesV] >>= rhs), ..., lhs); }
/// ///
@@ -1000,6 +992,14 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
constexpr friend vector_t operator>>(const vector_t& lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>) constexpr friend vector_t operator>>(const vector_t& lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>)
{ return vector_t((lhs[IndicesV] >> rhs[IndicesV]) ...); } { 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<scalar_t>)
{ return ((lhs[IndicesV] >>= rhs), ..., lhs); }
/// @} /// @}

View File

@@ -20,7 +20,6 @@
#ifndef FENNEC_MEMORY_NEW_H #ifndef FENNEC_MEMORY_NEW_H
#define FENNEC_MEMORY_NEW_H #define FENNEC_MEMORY_NEW_H
#include <cstdlib>
#include <new> #include <new>
#include <fennec/lang/types.h> #include <fennec/lang/types.h>
@@ -44,10 +43,10 @@ template<typename TypeT> void construct(TypeT* ptr, const TypeT& val)
{ ptr->TypeT(val); } { ptr->TypeT(val); }
template<typename TypeT> void construct(TypeT* ptr, TypeT&& val) template<typename TypeT> void construct(TypeT* ptr, TypeT&& val)
{ ptr->TypeT(fennec::forward(val)); } { ptr->TypeT(fennec::forward<TypeT>(val)); }
template<typename TypeT, typename...ArgsT> void construct(TypeT* ptr, ArgsT...args) template<typename TypeT, typename...ArgsT> void construct(TypeT* ptr, ArgsT...args)
{ ptr->TypeT(fennec::forward(args)...); } { ptr->TypeT(fennec::forward<TypeT>(args)...); }
template<typename TypeT> void destruct(TypeT* ptr) template<typename TypeT> void destruct(TypeT* ptr)
{ ptr->~TypeT(); } { ptr->~TypeT(); }

View File

@@ -16,7 +16,7 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
// ===================================================================================================================== // =====================================================================================================================
#include <stdlib.h> #include <fennec/lang/detail/__stdlib.h>
using assert_handler = void (*)(const char *, const char *, int , const char *); using assert_handler = void (*)(const char *, const char *, int , const char *);

View File

@@ -16,9 +16,9 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
// ===================================================================================================================== // =====================================================================================================================
#include <fennec/memory/new.h> #include <fennec/lang/detail/__stdlib.h>
#include <cstdlib> #include <fennec/memory/new.h>
#ifdef FENNEC_MEMORY_DEBUGGER #ifdef FENNEC_MEMORY_DEBUGGER

View File

@@ -14,6 +14,7 @@ add_executable(fennec-test main.cpp
tests/test_lang.h tests/test_lang.h
tests/lang/test_conditional_types.h tests/lang/test_conditional_types.h
tests/lang/test_bits.h tests/lang/test_bits.h
tests/lang/test_sequences.h
) )
target_link_libraries(fennec-test PRIVATE target_link_libraries(fennec-test PRIVATE

View File

@@ -25,6 +25,7 @@
#include <fennec/lang/limits.h> #include <fennec/lang/limits.h>
#include <fennec/math/common.h> #include <fennec/math/common.h>
#include <fennec/math/matrix.h>
#include <fennec/math/relational.h> #include <fennec/math/relational.h>
namespace fennec namespace fennec
@@ -56,7 +57,10 @@ inline std::ostream& operator<<(std::ostream& os, const matrix<ScalarT, RowsV, C
{ {
os << "[ "; os << "[ ";
((os << m[ColIndicesV] << " "), ...); ((os << m[ColIndicesV] << " "), ...);
os << " ]"; //[m]<size_t...i>(std::ostream& os, index_sequence<i...>) {
// ((os << fennec::row(m, i) << " "), ...);
//}(os, make_index_sequence<RowsV>{});
os << "]";
return os; return os;
} }

View File

@@ -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 <https://www.gnu.org/licenses/>.
// =====================================================================================================================
#ifndef FENNEC_TEST_LANG_SEQUENCES_H
#define FENNEC_TEST_LANG_SEQUENCES_H
#include <fennec/lang/sequences.h>
namespace fennec
{
namespace test
{
inline void test_sequences()
{
static_assert(fennec::is_same_v<make_index_sequence_t<2>, index_sequence<0, 1>>);
static_assert(fennec::is_same_v<make_index_sequence_t<3>, index_sequence<0, 1, 2>>);
static_assert(fennec::is_same_v<make_index_sequence_t<4>, index_sequence<0, 1, 2, 3>>);
}
}
}
#endif // FENNEC_TEST_LANG_SEQUENCES_H

View File

@@ -34,9 +34,89 @@ namespace test
inline void fennec_test_math_matrix() 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));
} }
} }

View File

@@ -22,7 +22,6 @@
#include <iostream> #include <iostream>
#include <fennec/lang/types.h>
#include <fennec/math/vector.h> #include <fennec/math/vector.h>
#include "../../test.h" #include "../../test.h"
@@ -39,38 +38,6 @@ inline void fennec_test_math_vector()
fennec_test_spacer(1); fennec_test_spacer(1);
fennec_test_run((component_count_v<bool_t&> == 1), true);
fennec_test_run((component_count_v<int_t&> == 1), true);
fennec_test_run((component_count_v<uint_t&> == 1), true);
fennec_test_run((component_count_v<float_t&> == 1), true);
fennec_test_run((component_count_v<double_t&> == 1), true);
fennec_test_spacer(1);
fennec_test_run((component_count_v<const bool_t&> == 1), true);
fennec_test_run((component_count_v<const int_t&> == 1), true);
fennec_test_run((component_count_v<const uint_t&> == 1), true);
fennec_test_run((component_count_v<const float_t&> == 1), true);
fennec_test_run((component_count_v<const double_t&> == 1), true);
fennec_test_spacer(1);
fennec_test_run((component_count_v<volatile bool_t&> == 1), true);
fennec_test_run((component_count_v<volatile int_t&> == 1), true);
fennec_test_run((component_count_v<volatile uint_t&> == 1), true);
fennec_test_run((component_count_v<volatile float_t&> == 1), true);
fennec_test_run((component_count_v<volatile double_t&> == 1), true);
fennec_test_spacer(1);
fennec_test_run((component_count_v<const volatile bool_t&> == 1), true);
fennec_test_run((component_count_v<const volatile int_t&> == 1), true);
fennec_test_run((component_count_v<const volatile uint_t&> == 1), true);
fennec_test_run((component_count_v<const volatile float_t&> == 1), true);
fennec_test_run((component_count_v<const volatile double_t&> == 1), true);
fennec_test_spacer(1);
fennec_test_run((component_count_v<bvec2> == 2), true); fennec_test_run((component_count_v<bvec2> == 2), true);
fennec_test_run((component_count_v<bvec3> == 3), true); fennec_test_run((component_count_v<bvec3> == 3), true);
fennec_test_run((component_count_v<bvec4> == 4), true); fennec_test_run((component_count_v<bvec4> == 4), true);
@@ -146,6 +113,19 @@ inline void fennec_test_math_vector()
fennec_test_spacer(2); 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_section("vec2 constructors");
fennec_test_spacer(1); fennec_test_spacer(1);
@@ -161,6 +141,8 @@ inline void fennec_test_math_vector()
fennec_test_spacer(2); fennec_test_spacer(2);
fennec_test_section("vec2 swizzles"); fennec_test_section("vec2 swizzles");
fennec_test_spacer(1); fennec_test_spacer(1);
@@ -172,6 +154,8 @@ inline void fennec_test_math_vector()
fennec_test_spacer(2); fennec_test_spacer(2);
fennec_test_section("vec3 constructors"); fennec_test_section("vec3 constructors");
fennec_test_spacer(1); fennec_test_spacer(1);
@@ -187,6 +171,8 @@ inline void fennec_test_math_vector()
fennec_test_spacer(2); fennec_test_spacer(2);
fennec_test_section("vec3 swizzles"); fennec_test_section("vec3 swizzles");
fennec_test_spacer(1); fennec_test_spacer(1);
@@ -233,10 +219,24 @@ inline void fennec_test_math_vector()
fennec_test_spacer(2); fennec_test_spacer(2);
fennec_test_section("scalar-vector operations");
fennec_test_section("scalar-vector arithmetic operations");
fennec_test_spacer(1); 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 * vec2(1, 2), vec2(2, 4));
fennec_test_run(2.0 * vec3(1, 2, 3), vec3(2, 4, 6)); 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)); 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 / 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.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_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); 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(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_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));
} }