// -*- c++ -*- #pragma once #include <utility> #include <valarray> #include <stdexcept> template<std::size_t N, std::size_t M> class ImatrixNM { public: ImatrixNM() : data(0, N * M) { } ImatrixNM(ImatrixNM<N, M>&& other) { *this = std::move(other); } ImatrixNM(const ImatrixNM<N, M>& other) { *this = other; } ImatrixNM& operator=(ImatrixNM<N, M>&& other) { data = std::move(other.data); return *this; } ImatrixNM& operator=(const ImatrixNM<N, M>& other) { data = other.data; return *this; } int& m(std::size_t x, std::size_t y) { if(x >= N || y >= M) throw std::out_of_range("Subscript out of range."); return data[x + y * N]; } const int& m(std::size_t x, std::size_t y) const { if(x >= N || y >= M) throw std::out_of_range("Subscript out of range."); return data[x + y * N]; } ImatrixNM<N, M> operator+(const ImatrixNM<N, M>& other) const { ImatrixNM m(*this); m.data += other.data; return m; } ImatrixNM<N, M> operator+(int val) { ImatrixNM<N, M> m(*this); m.data += val; return m; } ImatrixNM<N, M> operator-(const ImatrixNM<N, M>& other) const { ImatrixNM<N, M> m(*this); m.data -= other.data; return m; } ImatrixNM <N, M>operator-(int val) { ImatrixNM<N, M> m(*this); m.data -= val; return m; } ImatrixNM<N, M> operator%(const ImatrixNM<N, M>& other) const { ImatrixNM<N, M> m(*this); m.data %= other.data; return m; } ImatrixNM<N, M> operator%(int val) { ImatrixNM m(*this); m.data %= val; return m; } template<std::size_t R> ImatrixNM<N, R> operator*(const ImatrixNM<M, R>& other) const { ImatrixNM<N, R> out; for(std::size_t i = 0; i < N; ++i) { for(std::size_t j = 0; j < N; ++j) { out.m(i,j) = 0; for(std::size_t k = 0; k < M; ++k) { out.m(i,j) += m(i,k) * other.m(k,j); } } } return out; } ImatrixNM<N, M> operator*(int val) const { ImatrixNM<N, M> m(*this); m.data *= val; return m; } template<std::size_t R> ImatrixNM<N, R> operator/(const ImatrixNM<M, R>& other) const { ImatrixNM<N, R> out; for(std::size_t i = 0; i < N; ++i) { for(std::size_t j = 0; j < N; ++j) { out.m(i,j) = 0; for(std::size_t k = 0; k < M; ++k) { out.m(i,j) += m(i,k) / other.m(k,j); } } } return out; } ImatrixNM<N, M> operator/(int val) const { ImatrixNM<N, M> m(*this); m.data /= val; return m; } struct pos_t { std::size_t x; std::size_t y; }; void Move(pos_t from, pos_t to) { m(to.x, to.x) = m(from.x, from.x); m(from.x, from.y) = 0; } std::vector<int> Row(std::size_t n) const { if(n >= M) throw std::out_of_range("Subscript out of range."); std::vector<int> out; for(std::size_t x = 0; x < N; ++x) { out.push_back(m(x, n)); } return out; } std::vector<int> Column(std::size_t n) const { if(n >= N) throw std::out_of_range("Subscript out of range."); std::vector<int> out; for(std::size_t y = 0; y < M; ++y) { out.push_back(m(n, y)); } return out; } private: // Invariant; at all times data contains w * h initialized data members std::valarray<int> data; // default initialized to empty };