our_dick/include/detail/matrix.hpp
2020-08-15 13:56:43 -07:00

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