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