#ifndef REXY_DETAIL_MATRIX_HPP #define REXY_DETAIL_MATRIX_HPP #include //size_t #include //integer_sequence namespace math::detail{ template struct gen_id_tup{ using tup = typename gen_id_tup::tup; }; template struct gen_id_tup{ using tup = typename gen_id_tup::tup; }; template struct gen_id_tup{ using tup = typename gen_id_tup::tup; }; template struct gen_id_tup{ using tup = std::integer_sequence; }; template struct gen_zero_tup{ using tup = typename gen_zero_tup::tup; }; template struct gen_zero_tup<0,Args...>{ using tup = std::integer_sequence; }; template struct id_initialization_matrix{ using tuple = typename gen_id_tup::tup; }; template struct default_initialization_matrix{ using tuple = typename gen_zero_tup::tup; }; template struct default_initialization_matrix{ using tuple = typename id_initialization_matrix::tuple; }; template 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 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 constexpr matrix_base(std::integer_sequence): m_data{Ss...}{} public: //Default construct as identity when square, zero otherwise constexpr matrix_base(void): matrix_base(typename detail::default_initialization_matrix::tuple{}){} //Range initializing constructors constexpr explicit matrix_base(zero_initialize_t): m_data{}{} constexpr explicit matrix_base(no_initialize_t){} template 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 constexpr explicit matrix_base(Args&&... args): m_data{std::forward(args)...}{} //Copying constructors constexpr matrix_base(const matrix_base&) = default; constexpr matrix_base(matrix_base&&) = default; template constexpr matrix_base(const matrix_base& 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 constexpr matrix_base& operator=(const matrix_base& 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{m_data, x}; } constexpr auto operator[](size_type x)const{ return detail::mat_ref_obj{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