|
|
|
|
@@ -154,11 +154,7 @@ constexpr matrix<scalar, sizeof...(s0), s1...> outerProduct(const vector<scalar,
|
|
|
|
|
/// \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>{});
|
|
|
|
|
}
|
|
|
|
|
{ return mat<scalar, rows, sizeof...(cols)>::transpose(m); }
|
|
|
|
|
|
|
|
|
|
///
|
|
|
|
|
/// \brief Returns the determinant of m.
|
|
|
|
|
@@ -225,7 +221,7 @@ struct matrix
|
|
|
|
|
|
|
|
|
|
///
|
|
|
|
|
/// \brief alias for the transpose matrix type
|
|
|
|
|
using transpose_t = mat<ScalarT, columns, rows>;
|
|
|
|
|
using transpose_t = mat<ScalarT, rows, columns>;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
///
|
|
|
|
|
@@ -244,8 +240,7 @@ struct matrix
|
|
|
|
|
/// \brief default constructor, initializes elements with 0
|
|
|
|
|
///
|
|
|
|
|
/// \details
|
|
|
|
|
constexpr matrix()
|
|
|
|
|
: data{ scalar_t(0) }{}
|
|
|
|
|
constexpr matrix() = default;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
///
|
|
|
|
|
@@ -329,7 +324,7 @@ struct matrix
|
|
|
|
|
///
|
|
|
|
|
/// \copydetails matrix::operator[](size_t) const
|
|
|
|
|
constexpr column_t& operator[](size_t i)
|
|
|
|
|
{ assert(i < rows); return data[i]; }
|
|
|
|
|
{ assert(i < columns); return data[i]; }
|
|
|
|
|
|
|
|
|
|
///
|
|
|
|
|
/// \brief returns the column at index \f$i\f$
|
|
|
|
|
@@ -367,9 +362,7 @@ struct matrix
|
|
|
|
|
/// \returns a copy of the matrix with each component having been added by the scalar
|
|
|
|
|
constexpr friend matrix_t operator+(const matrix_t& lhs, scalar_t rhs)
|
|
|
|
|
{
|
|
|
|
|
matrix_t retval = lhs;
|
|
|
|
|
((retval[ColIndicesV] += rhs), ...);
|
|
|
|
|
return retval;
|
|
|
|
|
return matrix_t(lhs[ColIndicesV] + rhs ...);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
///
|
|
|
|
|
@@ -379,9 +372,7 @@ struct matrix
|
|
|
|
|
/// \returns a copy of the matrix with each component having been added by the scalar
|
|
|
|
|
constexpr friend matrix_t operator+(scalar_t lhs, const matrix_t& rhs)
|
|
|
|
|
{
|
|
|
|
|
matrix_t retval = rhs;
|
|
|
|
|
((retval[ColIndicesV] += lhs), ...);
|
|
|
|
|
return retval;
|
|
|
|
|
return matrix_t(lhs + rhs[ColIndicesV] ...);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
///
|
|
|
|
|
@@ -391,9 +382,7 @@ struct matrix
|
|
|
|
|
/// \returns a copy of the matrix with each component having been subtracted by the scalar
|
|
|
|
|
constexpr friend matrix_t operator-(const matrix_t& lhs, scalar_t rhs)
|
|
|
|
|
{
|
|
|
|
|
matrix_t retval = lhs;
|
|
|
|
|
((retval[ColIndicesV] -= rhs), ...);
|
|
|
|
|
return retval;
|
|
|
|
|
return matrix_t(lhs[ColIndicesV] - rhs ...);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
///
|
|
|
|
|
@@ -403,9 +392,7 @@ struct matrix
|
|
|
|
|
/// \returns a copy of the matrix with each component having been subtracted by the scalar
|
|
|
|
|
constexpr friend matrix_t operator-(scalar_t lhs, const matrix_t& rhs)
|
|
|
|
|
{
|
|
|
|
|
matrix_t retval = rhs;
|
|
|
|
|
((retval[ColIndicesV] -= lhs), ...);
|
|
|
|
|
return retval;
|
|
|
|
|
return matrix_t(lhs - rhs[ColIndicesV] ...);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
///
|
|
|
|
|
@@ -415,9 +402,7 @@ struct matrix
|
|
|
|
|
/// \returns a copy of the matrix with each component having been multiplied by the scalar
|
|
|
|
|
constexpr friend matrix_t operator*(const matrix_t& lhs, scalar_t rhs)
|
|
|
|
|
{
|
|
|
|
|
matrix_t retval = lhs;
|
|
|
|
|
((retval[ColIndicesV] *= rhs), ...);
|
|
|
|
|
return retval;
|
|
|
|
|
return matrix_t(lhs[ColIndicesV] * rhs ...);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
///
|
|
|
|
|
@@ -427,9 +412,7 @@ struct matrix
|
|
|
|
|
/// \returns a copy of the matrix with each component having been multiplied by the scalar
|
|
|
|
|
constexpr friend matrix_t operator*(scalar_t lhs, const matrix_t& rhs)
|
|
|
|
|
{
|
|
|
|
|
matrix_t retval = rhs;
|
|
|
|
|
((retval[ColIndicesV] *= lhs), ...);
|
|
|
|
|
return retval;
|
|
|
|
|
return matrix_t(lhs * rhs[ColIndicesV] ...);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
///
|
|
|
|
|
@@ -439,9 +422,7 @@ struct matrix
|
|
|
|
|
/// \returns a copy of the matrix with each component having been divided by the scalar
|
|
|
|
|
constexpr friend matrix_t operator/(const matrix_t& lhs, scalar_t rhs)
|
|
|
|
|
{
|
|
|
|
|
matrix_t retval = lhs;
|
|
|
|
|
((retval[ColIndicesV] /= rhs), ...);
|
|
|
|
|
return retval;
|
|
|
|
|
return matrix_t(lhs[ColIndicesV] / rhs ...);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
///
|
|
|
|
|
@@ -451,9 +432,7 @@ struct matrix
|
|
|
|
|
/// \returns a copy of the matrix with each component having been divided by the scalar
|
|
|
|
|
constexpr friend matrix_t operator/(scalar_t lhs, const matrix_t& rhs)
|
|
|
|
|
{
|
|
|
|
|
matrix_t retval = rhs;
|
|
|
|
|
((retval[ColIndicesV] /= lhs), ...);
|
|
|
|
|
return retval;
|
|
|
|
|
return matrix_t(lhs / rhs[ColIndicesV] ...);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -607,8 +586,9 @@ struct matrix
|
|
|
|
|
/// \param rhs the vector
|
|
|
|
|
/// \returns a vector containing the dot products of \f$rhs\f$ with each row of \f$lhs\f$
|
|
|
|
|
constexpr friend column_t operator*(const matrix_t& lhs, const row_t& rhs)
|
|
|
|
|
{ return [lhs, rhs]<size_t...i>(index_sequence<i...>) -> column_t
|
|
|
|
|
{ return column_t(fennec::dot(fennec::row(lhs, i), rhs) ...); }(make_index_sequence<rows>{}); }
|
|
|
|
|
{
|
|
|
|
|
return __mul(lhs, rhs);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
///
|
|
|
|
|
/// \brief performs a linear algebraic multiply
|
|
|
|
|
@@ -616,7 +596,7 @@ struct matrix
|
|
|
|
|
/// \param rhs the matrix
|
|
|
|
|
/// \returns a vector containing the dot products of \f$lhs\f$ with each column of \f$rhs\f$
|
|
|
|
|
constexpr friend row_t operator*(const column_t& lhs, const matrix_t& rhs)
|
|
|
|
|
{ return row_t(fennec::dot(fennec::column(rhs, ColIndicesV), lhs) ...); }
|
|
|
|
|
{ return row_t(fennec::dot(fennec::column(rhs, ColIndicesV), lhs) ...); }
|
|
|
|
|
|
|
|
|
|
/// @}
|
|
|
|
|
|
|
|
|
|
@@ -647,11 +627,12 @@ struct matrix
|
|
|
|
|
/// \brief performs a linear algebraic matrix multiplication
|
|
|
|
|
/// \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)
|
|
|
|
|
template<size_t ORowsV, size_t...OColIndicesV> requires(columns == ORowsV)
|
|
|
|
|
constexpr friend matrix<scalar_t, RowsV, OColIndicesV...> operator*(const matrix_t& lhs, const matrix<scalar_t, ORowsV, OColIndicesV...>& 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 matrix<scalar_t, RowsV, OColIndicesV...>(
|
|
|
|
|
matrix::__mul(lhs, rhs[OColIndicesV])...
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// @}
|
|
|
|
|
@@ -660,36 +641,53 @@ struct matrix
|
|
|
|
|
|
|
|
|
|
// Helpers =============================================================================================================
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
|
|
static constexpr matrix_t transpose(const transpose_t& mat)
|
|
|
|
|
{ return matrix_t(fennec::row(mat, ColIndicesV)...); }
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
|
|
// ReSharper disable once CppMemberFunctionMayBeStatic
|
|
|
|
|
template<size_t i0 = 0>
|
|
|
|
|
constexpr void __construct() { }
|
|
|
|
|
constexpr void __construct() { } // base case, does nothing, this will get optimized away
|
|
|
|
|
|
|
|
|
|
template<size_t i0 = 0, typename HeadT, typename...ArgsT>
|
|
|
|
|
constexpr void __construct(HeadT&& head, ArgsT&&...args)
|
|
|
|
|
// helper for parsing parameter packs
|
|
|
|
|
template<size_t i0 = 0, typename HeadT, typename...RestT>
|
|
|
|
|
constexpr void __construct(HeadT&& head, RestT&&...rest)
|
|
|
|
|
{
|
|
|
|
|
matrix::__insert<i0>(head);
|
|
|
|
|
matrix::__construct<i0 + component_count_v<HeadT>>(std::forward<ArgsT>(args)...);
|
|
|
|
|
matrix::__insert<i0>(head); // insert the head element
|
|
|
|
|
matrix::__construct<i0 + component_count_v<HeadT>>(std::forward<RestT>(rest)...); // propagate to the rest of the arguments
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// helper for inserting a scalar value
|
|
|
|
|
template<size_t i0 = 0>
|
|
|
|
|
constexpr void __insert(scalar_t s)
|
|
|
|
|
{ data[i0 / rows][i0 % rows] = s; }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// helper for inserting a scalar value of differing type
|
|
|
|
|
template<size_t i0 = 0, typename OScalarT> requires(is_arithmetic_v<OScalarT>)
|
|
|
|
|
constexpr void __insert(OScalarT s)
|
|
|
|
|
{ data[i0 / rows][i0 % rows] = scalar_t(s); }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// helper for inserting a vector
|
|
|
|
|
template<size_t i0 = 0, size_t...i>
|
|
|
|
|
constexpr void __insert(const vector<scalar_t, i...>& v)
|
|
|
|
|
{ (matrix::__insert<i0 + i>(v[i]), ...); }
|
|
|
|
|
|
|
|
|
|
// helper for inserting a vector of differing type
|
|
|
|
|
template<size_t i0 = 0, typename OScalarT, size_t...i>
|
|
|
|
|
constexpr void __insert(const vector<OScalarT, i...>& v)
|
|
|
|
|
{ (matrix::__insert<i0 + i>(v[i]), ...); }
|
|
|
|
|
|
|
|
|
|
// helper for a linear algebraic multiply
|
|
|
|
|
static constexpr column_t __mul(const matrix_t& lhs, const row_t& rhs)
|
|
|
|
|
{
|
|
|
|
|
// the compiler will optimize this better than writing out a specific definition
|
|
|
|
|
// when compared to glm or CxxSwizzle, this is faster by a significant margin
|
|
|
|
|
// all implementations provide 7 decimal places of precision
|
|
|
|
|
return ((lhs[ColIndicesV] * rhs[ColIndicesV]) + ...);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|