|
|
@ -33,7 +33,7 @@ namespace math { |
|
|
|
/**
|
|
|
|
* *n* by *m* column-major matrix. |
|
|
|
* |
|
|
|
* @tparam T Matrix element data type. |
|
|
|
* @tparam T Element type. |
|
|
|
* @tparam N Number of columns. |
|
|
|
* @tparam M Number of rows. |
|
|
|
* |
|
|
@ -63,6 +63,58 @@ struct matrix |
|
|
|
/// Array of matrix column vectors.
|
|
|
|
column_vector_type columns[column_count]; |
|
|
|
|
|
|
|
/// @name Conversion
|
|
|
|
/// @{
|
|
|
|
|
|
|
|
/// @private
|
|
|
|
template <class U, std::size_t... I> |
|
|
|
constexpr inline matrix<U, N, M> type_cast(std::index_sequence<I...>) const noexcept |
|
|
|
{ |
|
|
|
return {vector<U, M>(columns[I])...}; |
|
|
|
} |
|
|
|
|
|
|
|
/**
|
|
|
|
* Type-casts the elements of this matrix using `static_cast`. |
|
|
|
* |
|
|
|
* @tparam U Target element type. |
|
|
|
* |
|
|
|
* @return Matrix containing the type-casted elements. |
|
|
|
*/ |
|
|
|
template <class U> |
|
|
|
constexpr inline explicit operator matrix<U, N, M>() const noexcept |
|
|
|
{ |
|
|
|
return type_cast<U>(std::make_index_sequence<N>{}); |
|
|
|
} |
|
|
|
|
|
|
|
/// @private
|
|
|
|
template <std::size_t P, std::size_t O, std::size_t... I> |
|
|
|
constexpr inline matrix<T, P, O> size_cast(std::index_sequence<I...>) const noexcept |
|
|
|
{ |
|
|
|
if constexpr (O == M) |
|
|
|
return {((I < N) ? columns[I] : matrix<T, P, O>::identity()[I]) ...}; |
|
|
|
else |
|
|
|
return {((I < N) ? vector<T, O>(columns[I]) : matrix<T, P, O>::identity()[I]) ...}; |
|
|
|
} |
|
|
|
|
|
|
|
/**
|
|
|
|
* Size-casts this matrix to a matrix with different dimensions. Casting to greater dimensions causes new elements to be set to identity matrix elements. |
|
|
|
* |
|
|
|
* @tparam P Target number of columns. |
|
|
|
* @tparam O Target number of rows. |
|
|
|
* |
|
|
|
* @return *p* by *o* matrix. |
|
|
|
*/ |
|
|
|
template <std::size_t P, std::size_t O> |
|
|
|
constexpr inline explicit operator matrix<T, P, O>() const noexcept |
|
|
|
{ |
|
|
|
return size_cast<P, O>(std::make_index_sequence<P>{}); |
|
|
|
} |
|
|
|
|
|
|
|
/// @}
|
|
|
|
|
|
|
|
/// @name Column access
|
|
|
|
/// @{
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns a reference to the column vector at a given index. |
|
|
|
* |
|
|
@ -90,25 +142,9 @@ struct matrix |
|
|
|
/// @}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns a reference to the element at a given column-major index. |
|
|
|
* |
|
|
|
* @param i Column-major index of a matrix element. |
|
|
|
* |
|
|
|
* @return Reference to the element at column-major index @p i. |
|
|
|
* Returns a reference to the first column vector. |
|
|
|
*/ |
|
|
|
/// @{
|
|
|
|
constexpr inline T& element(std::size_t i) noexcept |
|
|
|
{ |
|
|
|
return columns[i / row_count][i % row_count]; |
|
|
|
} |
|
|
|
constexpr inline const T& element(std::size_t i) const noexcept |
|
|
|
{ |
|
|
|
return columns[i / row_count][i % row_count]; |
|
|
|
} |
|
|
|
/// @}
|
|
|
|
|
|
|
|
/// Returns a reference to the first column vector.
|
|
|
|
/// @{
|
|
|
|
constexpr inline column_vector_type& front() noexcept |
|
|
|
{ |
|
|
|
return columns[0]; |
|
|
@ -119,7 +155,9 @@ struct matrix |
|
|
|
} |
|
|
|
/// @}
|
|
|
|
|
|
|
|
/// Returns a reference to the last column vector.
|
|
|
|
/**
|
|
|
|
* Returns a reference to the last column vector. |
|
|
|
*/ |
|
|
|
/// @{
|
|
|
|
constexpr inline column_vector_type& back() noexcept |
|
|
|
{ |
|
|
@ -131,6 +169,29 @@ struct matrix |
|
|
|
} |
|
|
|
/// @}
|
|
|
|
|
|
|
|
/// @}
|
|
|
|
|
|
|
|
/// @name Element access
|
|
|
|
/// @{
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns a reference to the element at a given column-major index. |
|
|
|
* |
|
|
|
* @param i Column-major index of a matrix element. |
|
|
|
* |
|
|
|
* @return Reference to the element at column-major index @p i. |
|
|
|
*/ |
|
|
|
/// @{
|
|
|
|
constexpr inline T& element(std::size_t i) noexcept |
|
|
|
{ |
|
|
|
return columns[i / row_count][i % row_count]; |
|
|
|
} |
|
|
|
constexpr inline const T& element(std::size_t i) const noexcept |
|
|
|
{ |
|
|
|
return columns[i / row_count][i % row_count]; |
|
|
|
} |
|
|
|
/// @}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns a pointer to the first element. |
|
|
|
* |
|
|
@ -147,7 +208,14 @@ struct matrix |
|
|
|
}; |
|
|
|
/// @}
|
|
|
|
|
|
|
|
/// Returns an iterator to the first column vector.
|
|
|
|
/// @}
|
|
|
|
|
|
|
|
/// @name Iterators
|
|
|
|
/// @{
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns an iterator to the first column vector. |
|
|
|
*/ |
|
|
|
/// @{
|
|
|
|
constexpr inline column_vector_type* begin() noexcept |
|
|
|
{ |
|
|
@ -163,7 +231,9 @@ struct matrix |
|
|
|
} |
|
|
|
/// @}
|
|
|
|
|
|
|
|
/// Returns an iterator to the column vector following the last column vector.
|
|
|
|
/**
|
|
|
|
* Returns an iterator to the column vector following the last column vector. |
|
|
|
*/ |
|
|
|
/// @{
|
|
|
|
constexpr inline column_vector_type* end() noexcept |
|
|
|
{ |
|
|
@ -179,7 +249,9 @@ struct matrix |
|
|
|
} |
|
|
|
/// @}
|
|
|
|
|
|
|
|
/// Returns a reverse iterator to the first column vector of the reversed matrix.
|
|
|
|
/**
|
|
|
|
* Returns a reverse iterator to the first column vector of the reversed matrix. |
|
|
|
*/ |
|
|
|
/// @{
|
|
|
|
constexpr inline std::reverse_iterator<column_vector_type*> rbegin() noexcept |
|
|
|
{ |
|
|
@ -195,7 +267,9 @@ struct matrix |
|
|
|
} |
|
|
|
/// @}
|
|
|
|
|
|
|
|
/// Returns a reverse iterator to the column vector following the last column vector of the reversed matrix.
|
|
|
|
/**
|
|
|
|
* Returns a reverse iterator to the column vector following the last column vector of the reversed matrix. |
|
|
|
*/ |
|
|
|
/// @{
|
|
|
|
constexpr inline std::reverse_iterator<column_vector_type*> rend() noexcept |
|
|
|
{ |
|
|
@ -211,57 +285,27 @@ struct matrix |
|
|
|
} |
|
|
|
/// @}
|
|
|
|
|
|
|
|
/// Returns the number of elements in the matrix.
|
|
|
|
constexpr inline std::size_t size() const noexcept |
|
|
|
{ |
|
|
|
return element_count; |
|
|
|
}; |
|
|
|
/// @}
|
|
|
|
|
|
|
|
/// @private
|
|
|
|
template <class U, std::size_t... I> |
|
|
|
constexpr inline matrix<U, N, M> type_cast(std::index_sequence<I...>) const noexcept |
|
|
|
{ |
|
|
|
return {vector<U, M>(columns[I])...}; |
|
|
|
} |
|
|
|
/// @name Capacity
|
|
|
|
/// @{
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Type-casts the elements of this matrix using `static_cast`. |
|
|
|
* |
|
|
|
* @tparam U Target element type. |
|
|
|
* |
|
|
|
* @return Matrix containing the type-casted elements. |
|
|
|
* Returns the number of elements in the matrix. |
|
|
|
*/ |
|
|
|
template <class U> |
|
|
|
constexpr inline explicit operator matrix<U, N, M>() const noexcept |
|
|
|
constexpr inline std::size_t size() const noexcept |
|
|
|
{ |
|
|
|
return type_cast<U>(std::make_index_sequence<N>{}); |
|
|
|
} |
|
|
|
return element_count; |
|
|
|
}; |
|
|
|
|
|
|
|
/// @private
|
|
|
|
template <std::size_t P, std::size_t O, std::size_t... I> |
|
|
|
constexpr inline matrix<T, P, O> size_cast(std::index_sequence<I...>) const noexcept |
|
|
|
{ |
|
|
|
if constexpr (O == M) |
|
|
|
return {((I < N) ? columns[I] : matrix<T, P, O>::identity()[I]) ...}; |
|
|
|
else |
|
|
|
return {((I < N) ? vector<T, O>(columns[I]) : matrix<T, P, O>::identity()[I]) ...}; |
|
|
|
} |
|
|
|
/// @}
|
|
|
|
|
|
|
|
/// @name Constants
|
|
|
|
/// @{
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Size-casts this matrix to a matrix with different dimensions. Casting to greater dimensions causes new elements to be set to identity matrix elements. |
|
|
|
* |
|
|
|
* @tparam P Target number of columns. |
|
|
|
* @tparam O Target number of rows. |
|
|
|
* |
|
|
|
* @return *p* by *o* matrix. |
|
|
|
* Returns a zero matrix, where every element is equal to zero. |
|
|
|
*/ |
|
|
|
template <std::size_t P, std::size_t O> |
|
|
|
constexpr inline explicit operator matrix<T, P, O>() const noexcept |
|
|
|
{ |
|
|
|
return size_cast<P, O>(std::make_index_sequence<P>{}); |
|
|
|
} |
|
|
|
|
|
|
|
/// Returns a zero matrix, where every element is equal to zero.
|
|
|
|
static constexpr matrix zero() noexcept |
|
|
|
{ |
|
|
|
return {}; |
|
|
@ -277,7 +321,9 @@ struct matrix |
|
|
|
return {(I ? column_vector_type::one() : column_vector_type::one()) ...}; |
|
|
|
} |
|
|
|
|
|
|
|
/// Returns a matrix of ones, where every element is equal to one.
|
|
|
|
/**
|
|
|
|
* Returns a matrix of ones, where every element is equal to one. |
|
|
|
*/ |
|
|
|
static constexpr matrix one() noexcept |
|
|
|
{ |
|
|
|
return one(std::make_index_sequence<column_count>{}); |
|
|
@ -297,11 +343,15 @@ struct matrix |
|
|
|
return {identity_column(I, std::make_index_sequence<row_count>{}) ...}; |
|
|
|
} |
|
|
|
|
|
|
|
/// Returns an identity matrix, with ones on the main diagonal and zeros elsewhere.
|
|
|
|
/**
|
|
|
|
* Returns an identity matrix, with ones on the main diagonal and zeros elsewhere. |
|
|
|
*/ |
|
|
|
static constexpr matrix identity() noexcept |
|
|
|
{ |
|
|
|
return identity(std::make_index_sequence<column_count>{}); |
|
|
|
} |
|
|
|
|
|
|
|
/// @}
|
|
|
|
}; |
|
|
|
|
|
|
|
/// 2x2 matrix.
|
|
|
@ -362,18 +412,6 @@ constexpr matrix add(const matrix& a, T b) noexcept; |
|
|
|
template <class T, std::size_t N> |
|
|
|
constexpr T determinant(const matrix<T, N, N>& m) noexcept; |
|
|
|
|
|
|
|
/**
|
|
|
|
* Calculates the inverse of a square matrix. |
|
|
|
* |
|
|
|
* @param m Square matrix. |
|
|
|
* |
|
|
|
* @return Inverse of matrix @p m. |
|
|
|
* |
|
|
|
* @warning Currently only implemented for 2x2, 3x3, and 4x4 matrices. |
|
|
|
*/ |
|
|
|
template <class T, std::size_t N> |
|
|
|
constexpr matrix<T, N, N> inverse(const matrix<T, N, N>& m) noexcept; |
|
|
|
|
|
|
|
/**
|
|
|
|
* Performs a component-wise multiplication of two matrices. |
|
|
|
* |
|
|
@ -418,6 +456,41 @@ constexpr matrix div(const matrix& a, T b) noexcept; |
|
|
|
template <class T, std::size_t N, std::size_t M> |
|
|
|
constexpr matrix<T, N, M> div(T a, const matrix<T, N, M>& b) noexcept; |
|
|
|
|
|
|
|
/**
|
|
|
|
* Extracts the Ith column from a matrix. |
|
|
|
* |
|
|
|
* @tparam I Index of a column. |
|
|
|
* @tparam T Element type. |
|
|
|
* @tparam N Number of columns. |
|
|
|
* @tparam M Number of rows. |
|
|
|
* |
|
|
|
* @param m Matrix from which to extract a column. |
|
|
|
* |
|
|
|
* @return Reference to the Ith column of @p m. |
|
|
|
*/ |
|
|
|
/// @{
|
|
|
|
template<std::size_t I, class T, std::size_t N, std::size_t M> |
|
|
|
constexpr typename matrix<T, N, M>::column_vector_type& get(math::matrix<T, N, M>& m) noexcept; |
|
|
|
template<std::size_t I, class T, std::size_t N, std::size_t M> |
|
|
|
constexpr typename matrix<T, N, M>::column_vector_type&& get(math::matrix<T, N, M>&& m) noexcept; |
|
|
|
template<std::size_t I, class T, std::size_t N, std::size_t M> |
|
|
|
constexpr const typename matrix<T, N, M>::column_vector_type& get(const math::matrix<T, N, M>& m) noexcept; |
|
|
|
template<std::size_t I, class T, std::size_t N, std::size_t M> |
|
|
|
constexpr const typename matrix<T, N, M>::column_vector_type&& get(const math::matrix<T, N, M>&& m) noexcept; |
|
|
|
/// @}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Calculates the inverse of a square matrix. |
|
|
|
* |
|
|
|
* @param m Square matrix. |
|
|
|
* |
|
|
|
* @return Inverse of matrix @p m. |
|
|
|
* |
|
|
|
* @warning Currently only implemented for 2x2, 3x3, and 4x4 matrices. |
|
|
|
*/ |
|
|
|
template <class T, std::size_t N> |
|
|
|
constexpr matrix<T, N, N> inverse(const matrix<T, N, N>& m) noexcept; |
|
|
|
|
|
|
|
/**
|
|
|
|
* Creates a viewing transformation matrix. |
|
|
|
* |
|
|
@ -659,6 +732,86 @@ constexpr T determinant(const matrix& m) noexcept |
|
|
|
m[0][1] * m[1][0] * m[2][2] * m[3][3] + m[0][0] * m[1][1] * m[2][2] * m[3][3]; |
|
|
|
} |
|
|
|
|
|
|
|
/// @private
|
|
|
|
template <class T, std::size_t N, std::size_t M, std::size_t... I> |
|
|
|
constexpr inline matrix<T, N, M> componentwise_mul(const matrix<T, N, M>& a, const matrix<T, N, M>& b, std::index_sequence<I...>) noexcept |
|
|
|
{ |
|
|
|
return {(a[I] * b[I]) ...}; |
|
|
|
} |
|
|
|
|
|
|
|
template <class T, std::size_t N, std::size_t M> |
|
|
|
constexpr matrix<T, N, M> componentwise_mul(const matrix<T, N, M>& a, const matrix<T, N, M>& b) noexcept |
|
|
|
{ |
|
|
|
return componentwise_mul(a, b, std::make_index_sequence<N>{}); |
|
|
|
} |
|
|
|
|
|
|
|
/// @private
|
|
|
|
template <class T, std::size_t N, std::size_t M, std::size_t... I> |
|
|
|
constexpr inline matrix<T, N, M> div(const matrix<T, N, M>& a, const matrix<T, N, M>& b, std::index_sequence<I...>) noexcept |
|
|
|
{ |
|
|
|
return {(a[I] / b[I]) ...}; |
|
|
|
} |
|
|
|
|
|
|
|
template <class T, std::size_t N, std::size_t M> |
|
|
|
constexpr matrix<T, N, M> div(const matrix<T, N, M>& a, const matrix<T, N, M>& b) noexcept |
|
|
|
{ |
|
|
|
return div(a, b, std::make_index_sequence<N>{}); |
|
|
|
} |
|
|
|
|
|
|
|
/// @private
|
|
|
|
template <class T, std::size_t N, std::size_t M, std::size_t... I> |
|
|
|
constexpr inline matrix<T, N, M> div(const matrix<T, N, M>& a, T b, std::index_sequence<I...>) noexcept |
|
|
|
{ |
|
|
|
return {(a[I] / b) ...}; |
|
|
|
} |
|
|
|
|
|
|
|
template <class T, std::size_t N, std::size_t M> |
|
|
|
constexpr matrix<T, N, M> div(const matrix<T, N, M>& a, T b) noexcept |
|
|
|
{ |
|
|
|
return div(a, b, std::make_index_sequence<N>{}); |
|
|
|
} |
|
|
|
|
|
|
|
/// @private
|
|
|
|
template <class T, std::size_t N, std::size_t M, std::size_t... I> |
|
|
|
constexpr inline matrix<T, N, M> div(T a, const matrix<T, N, M>& b, std::index_sequence<I...>) noexcept |
|
|
|
{ |
|
|
|
return {(a / b[I]) ...}; |
|
|
|
} |
|
|
|
|
|
|
|
template <class T, std::size_t N, std::size_t M> |
|
|
|
constexpr matrix<T, N, M> div(T a, const matrix<T, N, M>& b) noexcept |
|
|
|
{ |
|
|
|
return div(a, b, std::make_index_sequence<N>{}); |
|
|
|
} |
|
|
|
|
|
|
|
template<std::size_t I, class T, std::size_t N, std::size_t M> |
|
|
|
constexpr inline typename matrix<T, N, M>::column_vector_type& get(math::matrix<T, N, M>& m) noexcept |
|
|
|
{ |
|
|
|
static_assert(I < N); |
|
|
|
return m.columns[I]; |
|
|
|
} |
|
|
|
|
|
|
|
template<std::size_t I, class T, std::size_t N, std::size_t M> |
|
|
|
constexpr inline typename matrix<T, N, M>::column_vector_type&& get(math::matrix<T, N, M>&& m) noexcept |
|
|
|
{ |
|
|
|
static_assert(I < N); |
|
|
|
return std::move(m.columns[I]); |
|
|
|
} |
|
|
|
|
|
|
|
template<std::size_t I, class T, std::size_t N, std::size_t M> |
|
|
|
constexpr inline const typename matrix<T, N, M>::column_vector_type& get(const math::matrix<T, N, M>& m) noexcept |
|
|
|
{ |
|
|
|
static_assert(I < N); |
|
|
|
return m.columns[I]; |
|
|
|
} |
|
|
|
|
|
|
|
template<std::size_t I, class T, std::size_t N, std::size_t M> |
|
|
|
constexpr inline const typename matrix<T, N, M>::column_vector_type&& get(const math::matrix<T, N, M>&& m) noexcept |
|
|
|
{ |
|
|
|
static_assert(I < N); |
|
|
|
return std::move(m.columns[I]); |
|
|
|
} |
|
|
|
|
|
|
|
template <class T> |
|
|
|
constexpr matrix<T, 2, 2> inverse(const matrix<T, 2, 2>& m) noexcept |
|
|
|
{ |
|
|
@ -723,58 +876,6 @@ constexpr matrix inverse(const matrix& m) noexcept |
|
|
|
}; |
|
|
|
} |
|
|
|
|
|
|
|
/// @private
|
|
|
|
template <class T, std::size_t N, std::size_t M, std::size_t... I> |
|
|
|
constexpr inline matrix<T, N, M> componentwise_mul(const matrix<T, N, M>& a, const matrix<T, N, M>& b, std::index_sequence<I...>) noexcept |
|
|
|
{ |
|
|
|
return {(a[I] * b[I]) ...}; |
|
|
|
} |
|
|
|
|
|
|
|
template <class T, std::size_t N, std::size_t M> |
|
|
|
constexpr matrix<T, N, M> componentwise_mul(const matrix<T, N, M>& a, const matrix<T, N, M>& b) noexcept |
|
|
|
{ |
|
|
|
return componentwise_mul(a, b, std::make_index_sequence<N>{}); |
|
|
|
} |
|
|
|
|
|
|
|
/// @private
|
|
|
|
template <class T, std::size_t N, std::size_t M, std::size_t... I> |
|
|
|
constexpr inline matrix<T, N, M> div(const matrix<T, N, M>& a, const matrix<T, N, M>& b, std::index_sequence<I...>) noexcept |
|
|
|
{ |
|
|
|
return {(a[I] / b[I]) ...}; |
|
|
|
} |
|
|
|
|
|
|
|
template <class T, std::size_t N, std::size_t M> |
|
|
|
constexpr matrix<T, N, M> div(const matrix<T, N, M>& a, const matrix<T, N, M>& b) noexcept |
|
|
|
{ |
|
|
|
return div(a, b, std::make_index_sequence<N>{}); |
|
|
|
} |
|
|
|
|
|
|
|
/// @private
|
|
|
|
template <class T, std::size_t N, std::size_t M, std::size_t... I> |
|
|
|
constexpr inline matrix<T, N, M> div(const matrix<T, N, M>& a, T b, std::index_sequence<I...>) noexcept |
|
|
|
{ |
|
|
|
return {(a[I] / b) ...}; |
|
|
|
} |
|
|
|
|
|
|
|
template <class T, std::size_t N, std::size_t M> |
|
|
|
constexpr matrix<T, N, M> div(const matrix<T, N, M>& a, T b) noexcept |
|
|
|
{ |
|
|
|
return div(a, b, std::make_index_sequence<N>{}); |
|
|
|
} |
|
|
|
|
|
|
|
/// @private
|
|
|
|
template <class T, std::size_t N, std::size_t M, std::size_t... I> |
|
|
|
constexpr inline matrix<T, N, M> div(T a, const matrix<T, N, M>& b, std::index_sequence<I...>) noexcept |
|
|
|
{ |
|
|
|
return {(a / b[I]) ...}; |
|
|
|
} |
|
|
|
|
|
|
|
template <class T, std::size_t N, std::size_t M> |
|
|
|
constexpr matrix<T, N, M> div(T a, const matrix<T, N, M>& b) noexcept |
|
|
|
{ |
|
|
|
return div(a, b, std::make_index_sequence<N>{}); |
|
|
|
} |
|
|
|
|
|
|
|
template <class T> |
|
|
|
constexpr matrix<T, 4, 4> look_at(const vector<T, 3>& position, const vector<T, 3>& target, vector<T, 3> up) |
|
|
|
{ |
|
|
@ -1238,4 +1339,37 @@ std::istream& operator>>(std::istream& is, matrix& m) |
|
|
|
|
|
|
|
using namespace math::operators; |
|
|
|
|
|
|
|
// Structured binding support
|
|
|
|
namespace std |
|
|
|
{ |
|
|
|
/**
|
|
|
|
* Provides access to the number of columns in a math::matrix as a compile-time constant expression. |
|
|
|
* |
|
|
|
* @tparam T Element type. |
|
|
|
* @tparam N Number of columns. |
|
|
|
* @tparam M Number of rows. |
|
|
|
*/ |
|
|
|
template<class T, std::size_t N, std::size_t M> |
|
|
|
struct tuple_size<math::matrix<T, N, M>> |
|
|
|
{ |
|
|
|
/// Number of columns in the matrix.
|
|
|
|
static constexpr std::size_t value = math::matrix<T, N, M>::column_count; |
|
|
|
}; |
|
|
|
|
|
|
|
/**
|
|
|
|
* Provides compile-time indexed access to the type of the columns in a math::matrix using a tuple-like interface. |
|
|
|
* |
|
|
|
* @tparam I Index of a column. |
|
|
|
* @tparam T Element type. |
|
|
|
* @tparam N Number of columns. |
|
|
|
* @tparam M Number of rows. |
|
|
|
*/ |
|
|
|
template<std::size_t I, class T, std::size_t N, std::size_t M> |
|
|
|
struct tuple_element<I, math::matrix<T, N, M>> |
|
|
|
{ |
|
|
|
/// Type of columns in the matrix.
|
|
|
|
using type = math::matrix<T, N, M>::column_vector_type; |
|
|
|
}; |
|
|
|
} |
|
|
|
|
|
|
|
#endif // ANTKEEPER_MATH_MATRIX_HPP
|