Specialize on square matrices

This commit is contained in:
rexy712 2020-08-16 06:47:52 -07:00
parent 1c89b24ce4
commit 932335bdc5
2 changed files with 118 additions and 67 deletions

View File

@ -27,7 +27,7 @@
namespace math{ namespace math{
template<typename T, size_t W, size_t H> template<typename T, size_t W, size_t H>
class matrix class matrix_base
{ {
static_assert(W > 0, "Cannot have 0 columns matrix"); static_assert(W > 0, "Cannot have 0 columns matrix");
static_assert(H > 0, "Cannot have 0 rows matrix"); static_assert(H > 0, "Cannot have 0 rows matrix");
@ -46,37 +46,32 @@ namespace math{
value_type m_data[W*H]; value_type m_data[W*H];
protected: protected:
template<size_type... Ss> template<size_t... Ss>
constexpr matrix(std::integer_sequence<size_type,Ss...>); constexpr matrix_base(std::integer_sequence<size_type,Ss...>);
public: public:
//Default construct as identity when square, zero otherwise //Default construct as identity when square, zero otherwise
constexpr matrix(); constexpr matrix_base();
//Range initializing constructors //Range initializing constructors
constexpr explicit matrix(detail::zero_initialize_t); constexpr explicit matrix_base(detail::zero_initialize_t);
constexpr explicit matrix(detail::no_initialize_t); constexpr explicit matrix_base(detail::no_initialize_t);
template<typename U = void>
constexpr explicit matrix(detail::id_initialize_t);
//Value initializing constructors //Value initializing constructors
constexpr explicit matrix(value_type v); constexpr explicit matrix_base(value_type v);
template<typename... Args> template<typename... Args>
constexpr explicit matrix(Args&&... args); constexpr explicit matrix_base(Args&&... args);
//Copying constructors //Copying constructors
constexpr matrix(const matrix&) = default; constexpr matrix_base(const matrix_base&) = default;
constexpr matrix(matrix&&) = default; constexpr matrix_base(matrix_base&&) = default;
template<typename U> template<typename U>
constexpr matrix(const matrix<U,Columns,Rows>& m); constexpr matrix_base(const matrix_base<U,Columns,Rows>& m);
~matrix() = default; ~matrix_base() = default;
//Assignement constexpr matrix_base& operator=(const matrix_base&) = default;
constexpr matrix_base& operator=(matrix_base&&) = default;
template<typename U> template<typename U>
constexpr matrix& operator=(const matrix<U,Columns,Rows>& m); constexpr matrix_base& operator=(const matrix_base<U,Columns,Rows>& m);
constexpr matrix& operator=(const matrix&) = default;
constexpr matrix& operator=(matrix&&) = default;
//Getters/Setters //Getters/Setters
constexpr auto operator[](size_type x); constexpr auto operator[](size_type x);
@ -95,14 +90,66 @@ namespace math{
constexpr operator pointer(); constexpr operator pointer();
constexpr operator const_pointer()const; constexpr operator const_pointer()const;
};
template<typename T, size_t W, size_t H>
class matrix : public matrix_base<T,W,H>
{
private:
using base = matrix_base<T,W,H>;
public:
using value_type = typename base::value_type;
using size_type = typename base::size_type;
using pointer = typename base::pointer;
using const_pointer = typename base::const_pointer;
using reference = typename base::reference;
using const_reference = typename base::const_reference;
public:
using base::base;
constexpr matrix(const matrix&) = default;
constexpr matrix(matrix&&) = default;
~matrix() = default;
//Assignement
constexpr matrix& operator=(const matrix&) = default;
constexpr matrix& operator=(matrix&&) = default;
template<typename U>
constexpr matrix& operator=(const matrix<U,W,H>& m);
};
template<typename T, size_t W>
class matrix<T,W,W> : public matrix_base<T,W,W>
{
private:
using base = matrix_base<T,W,W>;
public:
using value_type = typename base::value_type;
using size_type = typename base::size_type;
using pointer = typename base::pointer;
using const_pointer = typename base::const_pointer;
using reference = typename base::reference;
using const_reference = typename base::const_reference;
public:
using base::base;
constexpr matrix(const matrix&) = default;
constexpr matrix(matrix&&) = default;
constexpr explicit matrix(detail::id_initialize_t);
~matrix() = default;
//Assignement
constexpr matrix& operator=(const matrix&) = default;
constexpr matrix& operator=(matrix&&) = default;
template<typename U>
constexpr matrix& operator=(const matrix<U,W,W>& m);
//square matrix arithmetic operations //square matrix arithmetic operations
template<typename U = T>
constexpr value_type determinate()const; constexpr value_type determinate()const;
template<typename U = T>
constexpr value_type trace()const; constexpr value_type trace()const;
template<typename U = T>
constexpr matrix transpose()const; constexpr matrix transpose()const;
template<typename U = T>
constexpr matrix inverse()const; constexpr matrix inverse()const;
}; };

View File

@ -27,40 +27,33 @@
namespace math{ namespace math{
template<typename T, size_t W, size_t H> template<typename T, size_t W, size_t H>
template<typename matrix<T,W,H>::size_type... Ss> template<size_t... Ss>
constexpr matrix<T,W,H>::matrix(std::integer_sequence<size_type,Ss...>): constexpr matrix_base<T,W,H>::matrix_base(std::integer_sequence<size_type,Ss...>):
m_data{Ss...}{} m_data{Ss...}{}
template<typename T, size_t W, size_t H> template<typename T, size_t W, size_t H>
constexpr matrix<T,W,H>::matrix(): constexpr matrix_base<T,W,H>::matrix_base():
matrix(typename detail::default_initialization_matrix<Columns,Rows>::tuple{}){} matrix_base(typename detail::default_initialization_matrix<Columns,Rows>::tuple{}){}
template<typename T, size_t W, size_t H> template<typename T, size_t W, size_t H>
constexpr matrix<T,W,H>::matrix(detail::zero_initialize_t): constexpr matrix_base<T,W,H>::matrix_base(detail::zero_initialize_t):
m_data{}{} m_data{}{}
template<typename T, size_t W, size_t H> template<typename T, size_t W, size_t H>
constexpr matrix<T,W,H>::matrix(detail::no_initialize_t){} constexpr matrix_base<T,W,H>::matrix_base(detail::no_initialize_t){}
template<typename T, size_t W, size_t H>
template<typename U>
constexpr matrix<T,W,H>::matrix(detail::id_initialize_t):
matrix()
{
static_assert(Columns == Rows, "Identity initialization only supported on square matrices");
}
template<typename T, size_t W, size_t H> template<typename T, size_t W, size_t H>
constexpr matrix<T,W,H>::matrix(value_type v){ constexpr matrix_base<T,W,H>::matrix_base(value_type v){
for(size_type i = 0;i < Columns*Rows;++i) for(size_type i = 0;i < Columns*Rows;++i)
m_data[i] = v; m_data[i] = v;
} }
template<typename T, size_t W, size_t H> template<typename T, size_t W, size_t H>
template<typename... Args> template<typename... Args>
constexpr matrix<T,W,H>::matrix(Args&&... args): constexpr matrix_base<T,W,H>::matrix_base(Args&&... args):
m_data{std::forward<Args>(args)...}{} m_data{std::forward<Args>(args)...}{}
template<typename T, size_t W, size_t H> template<typename T, size_t W, size_t H>
template<typename U> template<typename U>
constexpr matrix<T,W,H>::matrix(const matrix<U,Columns,Rows>& m){ constexpr matrix_base<T,W,H>::matrix_base(const matrix_base<U,Columns,Rows>& m){
using mat = decltype(m); using mat = decltype(m);
for(typename mat::size_type i = 0;i < mat::Columns*mat::Rows;++i) for(typename mat::size_type i = 0;i < mat::Columns*mat::Rows;++i)
m_data[i] = m.get(i); m_data[i] = m.get(i);
@ -68,7 +61,7 @@ namespace math{
template<typename T, size_t W, size_t H> template<typename T, size_t W, size_t H>
template<typename U> template<typename U>
constexpr matrix<T,W,H>& matrix<T,W,H>::operator=(const matrix<U,Columns,Rows>& m){ constexpr matrix_base<T,W,H>& matrix_base<T,W,H>::operator=(const matrix_base<U,Columns,Rows>& m){
using mat = decltype(m); using mat = decltype(m);
for(typename mat::size_type i = 0;i < mat::Columns*mat::Rows;++i) for(typename mat::size_type i = 0;i < mat::Columns*mat::Rows;++i)
m_data[i] = m.get(i); m_data[i] = m.get(i);
@ -77,77 +70,90 @@ namespace math{
template<typename T, size_t W, size_t H> template<typename T, size_t W, size_t H>
constexpr auto matrix<T,W,H>::operator[](size_type x){ constexpr auto matrix_base<T,W,H>::operator[](size_type x){
return detail::mat_ref_obj<value_type,Rows>{m_data, x}; return detail::mat_ref_obj<value_type,Rows>{m_data, x};
} }
template<typename T, size_t W, size_t H> template<typename T, size_t W, size_t H>
constexpr auto matrix<T,W,H>::operator[](size_type x)const{ constexpr auto matrix_base<T,W,H>::operator[](size_type x)const{
return detail::mat_ref_obj<const value_type,Rows>{m_data, x}; return detail::mat_ref_obj<const value_type,Rows>{m_data, x};
} }
template<typename T, size_t W, size_t H> template<typename T, size_t W, size_t H>
constexpr auto matrix<T,W,H>::get(size_type x, size_type y) -> reference{ constexpr auto matrix_base<T,W,H>::get(size_type x, size_type y) -> reference{
return m_data[x+(y*Rows)]; return m_data[x+(y*Rows)];
} }
template<typename T, size_t W, size_t H> template<typename T, size_t W, size_t H>
constexpr auto matrix<T,W,H>::get(size_type x, size_type y)const -> const_reference{ constexpr auto matrix_base<T,W,H>::get(size_type x, size_type y)const -> const_reference{
return m_data[x+(y*Rows)]; return m_data[x+(y*Rows)];
} }
template<typename T, size_t W, size_t H> template<typename T, size_t W, size_t H>
constexpr auto matrix<T,W,H>::get(size_type i) -> reference{ constexpr auto matrix_base<T,W,H>::get(size_type i) -> reference{
return m_data[i]; return m_data[i];
} }
template<typename T, size_t W, size_t H> template<typename T, size_t W, size_t H>
constexpr auto matrix<T,W,H>::get(size_type i)const -> const_reference{ constexpr auto matrix_base<T,W,H>::get(size_type i)const -> const_reference{
return m_data[i]; return m_data[i];
} }
template<typename T, size_t W, size_t H> template<typename T, size_t W, size_t H>
constexpr auto matrix<T,W,H>::columns()const -> size_type{ constexpr auto matrix_base<T,W,H>::columns()const -> size_type{
return Columns; return Columns;
} }
template<typename T, size_t W, size_t H> template<typename T, size_t W, size_t H>
constexpr auto matrix<T,W,H>::rows()const -> size_type{ constexpr auto matrix_base<T,W,H>::rows()const -> size_type{
return Rows; return Rows;
} }
template<typename T, size_t W, size_t H> template<typename T, size_t W, size_t H>
constexpr auto matrix<T,W,H>::size()const -> size_type{ constexpr auto matrix_base<T,W,H>::size()const -> size_type{
return Columns*Rows; return Columns*Rows;
} }
template<typename T, size_t W, size_t H> template<typename T, size_t W, size_t H>
constexpr auto matrix<T,W,H>::raw() -> pointer{ constexpr auto matrix_base<T,W,H>::raw() -> pointer{
return m_data; return m_data;
} }
template<typename T, size_t W, size_t H> template<typename T, size_t W, size_t H>
constexpr auto matrix<T,W,H>::raw()const -> const_pointer{ constexpr auto matrix_base<T,W,H>::raw()const -> const_pointer{
return m_data; return m_data;
} }
template<typename T, size_t W, size_t H> template<typename T, size_t W, size_t H>
constexpr matrix<T,W,H>::operator pointer(){ constexpr matrix_base<T,W,H>::operator pointer(){
return m_data; return m_data;
} }
template<typename T, size_t W, size_t H> template<typename T, size_t W, size_t H>
constexpr matrix<T,W,H>::operator const_pointer()const{ constexpr matrix_base<T,W,H>::operator const_pointer()const{
return m_data; return m_data;
} }
template<typename T, size_t W, size_t H> template<typename T, size_t W, size_t H>
template<typename U> template<typename U>
constexpr auto matrix<T,W,H>::determinate()const -> value_type{ constexpr matrix<T,W,H>& matrix<T,W,H>::operator=(const matrix<U,W,H>& m){
static_assert(W == H, "Determinate can only be calculated on square matrix"); base::operator=(m);
return *this;
}
template<typename T, size_t W>
constexpr matrix<T,W,W>::matrix(detail::id_initialize_t):
base(){}
template<typename T, size_t W>
template<typename U>
constexpr matrix<T,W,W>& matrix<T,W,W>::operator=(const matrix<U,W,W>& m){
base::operator=(m);
return *this;
}
template<typename T, size_t W>
constexpr auto matrix<T,W,W>::determinate()const -> value_type{
return math::determinate(*this); return math::determinate(*this);
} }
template<typename T, size_t W, size_t H> template<typename T, size_t W>
template<typename U> constexpr auto matrix<T,W,W>::trace()const -> value_type{
constexpr auto matrix<T,W,H>::trace()const -> value_type{
static_assert(W == H, "Trace can only be calculated on square matrix");
value_type sum = 0; value_type sum = 0;
for(size_type i = 0;i < W;++i){ for(size_type i = 0;i < W;++i){
sum += get(i, i); sum += get(i, i);
} }
} }
template<typename T, size_t W, size_t H> template<typename T, size_t W>
template<typename U> constexpr matrix<T,W,W> matrix<T,W,W>::transpose()const{
constexpr matrix<T,W,H> matrix<T,W,H>::transpose()const{
matrix m(no_initialize); matrix m(no_initialize);
for(size_type i = 0;i < W;++i){ for(size_type i = 0;i < W;++i){
for(size_type j = 0;j < W;++j){ for(size_type j = 0;j < W;++j){
@ -156,10 +162,8 @@ namespace math{
} }
return m; return m;
} }
template<typename T, size_t W, size_t H> template<typename T, size_t W>
template<typename U> constexpr matrix<T,W,W> matrix<T,W,W>::inverse()const{
constexpr matrix<T,W,H> matrix<T,W,H>::inverse()const{
static_assert(W == H, "Trace can only be calculated on square matrix");
return math::inverse(*this); return math::inverse(*this);
} }