191 lines
4.8 KiB
C++
191 lines
4.8 KiB
C++
#ifndef REXY_DETAIL_MATRIX_HPP
|
|
#define REXY_DETAIL_MATRIX_HPP
|
|
|
|
#include <cstdlib> //size_t
|
|
#include <utility> //integer_sequence
|
|
|
|
namespace math::detail{
|
|
|
|
template<size_t SW, size_t W = SW, size_t H = SW-1, size_t... Args>
|
|
struct gen_id_tup{
|
|
using tup = typename gen_id_tup<SW, W-1, H, Args..., 0>::tup;
|
|
};
|
|
template<size_t SW, size_t H, size_t... Args>
|
|
struct gen_id_tup<SW,SW,H,Args...>{
|
|
using tup = typename gen_id_tup<SW, SW-1, H, Args..., 1>::tup;
|
|
};
|
|
template<size_t SW, size_t H, size_t... Args>
|
|
struct gen_id_tup<SW,0,H,Args...>{
|
|
using tup = typename gen_id_tup<SW, SW, H-1, Args..., 0>::tup;
|
|
};
|
|
template<size_t SW, size_t... Args>
|
|
struct gen_id_tup<SW,SW,0,Args...>{
|
|
using tup = std::integer_sequence<size_t,Args...,1>;
|
|
};
|
|
|
|
|
|
template<size_t N, size_t... Args>
|
|
struct gen_zero_tup{
|
|
using tup = typename gen_zero_tup<N-1,Args...,0>::tup;
|
|
};
|
|
template<size_t... Args>
|
|
struct gen_zero_tup<0,Args...>{
|
|
using tup = std::integer_sequence<size_t,Args...>;
|
|
};
|
|
|
|
template<size_t W>
|
|
struct id_initialization_matrix{
|
|
using tuple = typename gen_id_tup<W>::tup;
|
|
};
|
|
|
|
|
|
template<size_t W, size_t H>
|
|
struct default_initialization_matrix{
|
|
using tuple = typename gen_zero_tup<W>::tup;
|
|
};
|
|
template<size_t W>
|
|
struct default_initialization_matrix<W,W>{
|
|
using tuple = typename id_initialization_matrix<W>::tuple;
|
|
};
|
|
|
|
template<class T, size_t R>
|
|
class mat_ref_obj
|
|
{
|
|
public:
|
|
using size_type = size_t;
|
|
|
|
protected:
|
|
T* m_data = nullptr;
|
|
public:
|
|
constexpr mat_ref_obj(T* d, size_type i):
|
|
m_data(d+i){}
|
|
|
|
constexpr T& operator[](size_type i){
|
|
return m_data[i*R];
|
|
}
|
|
constexpr const T& operator[](size_type i)const{
|
|
return m_data[i*R];
|
|
}
|
|
};
|
|
|
|
template<class T, size_t W, size_t H>
|
|
class matrix_base
|
|
{
|
|
static_assert(W > 0, "Cannot have 0 columns matrix");
|
|
static_assert(H > 0, "Cannot have 0 rows matrix");
|
|
public:
|
|
using value_type = T;
|
|
using size_type = size_t;
|
|
using pointer = value_type*;
|
|
using const_pointer = const value_type*;
|
|
using reference = value_type&;
|
|
using const_reference = const value_type&;
|
|
|
|
static constexpr size_type Columns = W;
|
|
static constexpr size_type Rows = H;
|
|
|
|
protected:
|
|
value_type m_data[W*H];
|
|
|
|
protected:
|
|
template<size_type... Ss>
|
|
constexpr matrix_base(std::integer_sequence<size_type,Ss...>):
|
|
m_data{Ss...}{}
|
|
|
|
public:
|
|
//Default construct as identity when square, zero otherwise
|
|
constexpr matrix_base(void):
|
|
matrix_base(typename detail::default_initialization_matrix<Columns,Rows>::tuple{}){}
|
|
|
|
//Range initializing constructors
|
|
constexpr explicit matrix_base(zero_initialize_t):
|
|
m_data{}{}
|
|
constexpr explicit matrix_base(no_initialize_t){}
|
|
template<class U = void>
|
|
constexpr explicit matrix_base(id_initialize_t):
|
|
matrix_base()
|
|
{
|
|
static_assert(Columns == Rows, "Identity initialization only supported on square matrices");
|
|
}
|
|
|
|
//Value initializing constructors
|
|
constexpr explicit matrix_base(value_type v){
|
|
for(size_type i = 0;i < Columns*Rows;++i)
|
|
m_data[i] = v;
|
|
}
|
|
template<class... Args>
|
|
constexpr explicit matrix_base(Args&&... args):
|
|
m_data{std::forward<Args>(args)...}{}
|
|
|
|
//Copying constructors
|
|
constexpr matrix_base(const matrix_base&) = default;
|
|
constexpr matrix_base(matrix_base&&) = default;
|
|
template<class U>
|
|
constexpr matrix_base(const matrix_base<U,Columns,Rows>& m){
|
|
using mat = decltype(m);
|
|
for(typename mat::size_type i = 0;i < mat::Columns*mat::Rows;++i)
|
|
m_data[i] = m.get(i);
|
|
}
|
|
~matrix_base(void) = default;
|
|
|
|
//Assignement
|
|
template<class U>
|
|
constexpr matrix_base& operator=(const matrix_base<U,Columns,Rows>& m){
|
|
using mat = decltype(m);
|
|
for(typename mat::size_type i = 0;i < mat::Columns*mat::Rows;++i)
|
|
m_data[i] = m.get(i);
|
|
return *this;
|
|
}
|
|
constexpr matrix_base& operator=(const matrix_base&) = default;
|
|
constexpr matrix_base& operator=(matrix_base&&) = default;
|
|
|
|
|
|
//Getters/Setters
|
|
constexpr auto operator[](size_type x){
|
|
return detail::mat_ref_obj<value_type,Rows>{m_data, x};
|
|
}
|
|
constexpr auto operator[](size_type x)const{
|
|
return detail::mat_ref_obj<const value_type,Rows>{m_data, x};
|
|
}
|
|
constexpr reference get(size_type x, size_type y){
|
|
return m_data[x+(y*Rows)];
|
|
}
|
|
constexpr const_reference get(size_type x, size_type y)const{
|
|
return m_data[x+(y*Rows)];
|
|
}
|
|
constexpr reference get(size_type i){
|
|
return m_data[i];
|
|
}
|
|
constexpr const_reference get(size_type i)const{
|
|
return m_data[i];
|
|
}
|
|
|
|
constexpr size_type columns(void)const{
|
|
return Columns;
|
|
}
|
|
constexpr size_type rows(void)const{
|
|
return Rows;
|
|
}
|
|
constexpr size_type size(void)const{
|
|
return Columns*Rows;
|
|
}
|
|
|
|
constexpr pointer raw(void){
|
|
return m_data;
|
|
}
|
|
constexpr const_pointer raw(void)const{
|
|
return m_data;
|
|
}
|
|
constexpr operator pointer(void){
|
|
return m_data;
|
|
}
|
|
constexpr operator const_pointer(void)const{
|
|
return m_data;
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
#endif
|