/* mmmatrix.hpp * Part of Mathematical library built (ab)using Modern C++ 17 abstractions. * * This library is not intended to be _performant_, it does not contain * hand written SMID / SSE / AVX optimizations. It is instead an example * of highly inefficient (but abstract!) code, where matrices can contain any * data type. * * Naoki Pross * 2018 ~ 2019 */ #pragma once #include "mm/debug.hpp" #include #include #include #include #include #include /* * Forward declarations */ namespace mm { using index = std::size_t; template class basic_matrix; /* specialisations */ template class matrix; template class vector; template class square_matrix; template class diagonal_matrix; } /* * Matrix Classes */ namespace mm { template struct basic_matrix { public: using type = T; static constexpr std::size_t rows = Rows; static constexpr std::size_t cols = Cols; template friend class mm::basic_matrix; virtual ~basic_matrix() {}; // copy from another matrix // template // basic_matrix(const basic_matrix& other) { // static_assert(ORows <= Rows); // static_assert(OCols <= Cols); // for (index row = 0; row < Rows; row++) // for (index col = 0; col < Cols; col++) // at(row, col) = other.at(row, col); // } virtual T& at(index row, index col) = 0; virtual const T& at(index row, index col) const = 0; // constexpr std::size_t rows() { return Rows; } // constexpr std::size_t cols() { return Cols; } protected: basic_matrix() { npdebug("default construtor"); } basic_matrix(const basic_matrix& other) { npdebug("copy constructor"); } basic_matrix(basic_matrix&& other) { npdebug("move constructor"); } }; /* Specializations */ template struct matrix : public basic_matrix { public: // aggregate initialization template::value >::type... > matrix(E ...e) : m_data({{std::forward(e)...}}) {} matrix(const matrix& o) : basic_matrix(o), m_data(o.m_data) {} matrix(matrix&& o) : basic_matrix(std::move(o)), m_data(std::move(o.m_data)) {} virtual ~matrix() = default; virtual T& at(index row, index col) override { return m_data[row * Cols + col]; } virtual const T& at(index row, index col) const override { return m_data[row * Cols + col]; } private: std::array m_data; }; template struct vector : public matrix {}; template struct square_matrix : public matrix {}; template struct identity_matrix : public basic_matrix { public: const T& at(index row, index col) const override { return (row != col) ? static_cast(1) : static_cast(0); } private: // not allowed T& at(index row, index col) { return static_cast(0); } }; template struct diagonal_matrix : public basic_matrix { public: T& at(index row, index col) override { m_null_element = static_cast(0); return (row != col) ? m_data[row] : m_null_element; } const T& at(index row, index col) const override { return (row != col) ? m_data[row] : static_cast(0); } private: T m_null_element; std::array m_data; }; } /* * Matrix Opertors */ namespace mm { } template std::ostream& operator<<(std::ostream& os, const mm::basic_matrix& m) { for (mm::index row = 0; row < Rows; row++) { os << "[ "; for (mm::index col = 0; col < (Cols -1); col++) { os << std::setw(NumW) << m.at(row, col) << ", "; } os << std::setw(NumW) << m.at(row, (Cols -1)) << " ]\n"; } return os; }