/*! \file pivecto2d.h * \brief 2D wrapper around PIVector * * This file declares PIVector */ /* PIP - Platform Independent Primitives 2D wrapper around PIVector Andrey Bychkov work.a.b@yandex.ru This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #ifndef PIVECTOR2D_H #define PIVECTOR2D_H #include "pivector.h" /*! \brief 2D array, * \details This class used to store 2D array of any type elements as plain vector. * You can read/write any element via operators [][], first dimension - row, second - column. * The first dimension is Row, and you can operate with Row as PIVector: modify any element, assign to another Row and etc. * You can't add values to array, but you can modify any elements or create another PIVector2D. * PIVector2D has constructors from PIVector and PIVector > */ template class PIVector2D { public: inline PIVector2D() {rows_ = cols_ = 0;} inline PIVector2D(size_t rows, size_t cols, const T & f = T()) { rows_ = rows; cols_ = cols; mat.resize(rows*cols, f); } inline PIVector2D(size_t rows, size_t cols, const PIVector & v) : rows_(rows), cols_(cols), mat(v) { mat.resize(rows*cols); } inline PIVector2D(size_t rows, size_t cols, PIVector && v) : rows_(rows), cols_(cols), mat(std::move(v)) { mat.resize(rows*cols); } inline PIVector2D(const PIVector > & v) { rows_ = v.size(); if (rows_) { cols_ = v[0].size(); for (size_t i = 0; i < rows_; i++) { mat.append(v[i]); } mat.resize(rows_*cols_); } if (mat.isEmpty()) rows_ = cols_ = 0; } inline size_t rows() const {return rows_;} inline size_t cols() const {return cols_;} inline size_t size() const {return mat.size();} inline ssize_t size_s() const {return mat.size_s();} inline size_t length() const {return mat.length();} inline size_t capacity() const {return mat.capacity();} inline bool isEmpty() const {return mat.isEmpty();} class Row { friend class PIVector2D; private: inline Row(PIVector2D * p, size_t row) : p_(&(p->mat)) {st_ = p->cols_ * row; sz_ = p->cols_;} PIVector * p_; size_t st_, sz_; public: inline size_t size() const {return sz_;} inline T & operator [](size_t index) {return (*p_)[st_ + index];} inline const T & operator [](size_t index) const {return (*p_)[st_ + index];} inline T * data(size_t index = 0) {return p_->data(st_ + index);} inline const T * data(size_t index = 0) const {return p_->data(st_ + index);} inline Row & operator =(const Row & other) { if (p_ == other.p_ && st_ == other.st_) return *this; size_t sz = piMin(sz_, other.sz_); p_->_copyRaw(p_->data(st_), other.data(), sz); return *this; } inline Row & operator =(const PIVector & other) { size_t sz = piMin(sz, other.size()); p_->_copyRaw(p_->data(st_), other.data(), sz); return *this; } inline PIVector toVector() const {return PIVector(p_->data(st_), sz_);} }; class Col { friend class PIVector2D; private: inline Col(PIVector2D * p, size_t row) : p_(&(p->mat)) {step_ = p->cols_; row_ = row; sz_ = p->rows_;} PIVector * p_; size_t step_, row_, sz_; public: inline size_t size() const {return sz_;} inline T & operator [](size_t index) {return (*p_)[index * step_ + row_];} inline const T & operator [](size_t index) const {return (*p_)[index * step_ + row_];} inline T * data(size_t index = 0) {return p_->data(index * step_ + row_);} inline const T * data(size_t index = 0) const {return p_->data(index * step_ + row_);} inline Col & operator =(const Col & other) { if (p_ == other.p_ && row_ == other.row_) return *this; size_t sz = piMin(sz_, other.sz_); for (int i=0; i & other) { size_t sz = piMin(sz_, other.size()); for (int i=0; i toVector() const { PIVector ret; ret.reserve(sz_); for (size_t i=0; i; private: inline RowConst(const PIVector2D * p, size_t row) : p_(&(p->mat)) {st_ = p->cols_ * row; sz_ = p->cols_;} const PIVector * p_; size_t st_, sz_; public: inline size_t size() const {return sz_;} inline const T & operator [](size_t index) const {return (*p_)[st_ + index];} inline const T * data(size_t index = 0) const {return p_->data(st_ + index);} inline PIVector toVector() const {return PIVector(p_->data(st_), sz_);} }; class ColConst { friend class PIVector2D; private: inline ColConst(const PIVector2D * p, size_t row) : p_(&(p->mat)) {step_ = p->cols_; row_ = row; sz_ = p->rows_;} const PIVector * p_; size_t step_, row_, sz_; public: inline size_t size() const {return p_->rows_;} inline const T & operator [](size_t index) const {return (*p_)[index * step_ + row_];} inline const T * data(size_t index = 0) const {return p_->data(index * step_ + row_);} inline PIVector toVector() const { PIVector ret; ret.reserve(sz_); for (int i=0; i & setRow(size_t row, const Row & other) { size_t sz = piMin(cols_, other.sz_); mat._copyRaw(mat.data(cols_ * row), other.data(), sz); return *this; } inline PIVector2D & setRow(size_t row, const RowConst & other) { size_t sz = piMin(cols_, other.sz_); mat._copyRaw(mat.data(cols_ * row), other.data(), sz); return *this; } inline PIVector2D & setRow(size_t row, const PIVector & other) { size_t sz = piMin(cols_, other.size()); mat._copyRaw(mat.data(cols_ * row), other.data(), sz); return *this; } inline PIVector2D & addRow(const Row & other) { if (cols_ == 0) cols_ = other.sz_; size_t sz = piMin(cols_, other.sz_); size_t ps = mat.size(); mat.resize(mat.size() + cols_); mat._copyRaw(mat.data(ps), other.data(), sz); rows_++; return *this; } inline PIVector2D & addRow(const RowConst & other) { if (cols_ == 0) cols_ = other.sz_; size_t sz = piMin(cols_, other.sz_); size_t ps = mat.size(); mat.resize(mat.size() + cols_); mat._copyRaw(mat.data(ps), other.data(), sz); rows_++; return *this; } inline PIVector2D & addRow(const PIVector & other) { if (cols_ == 0) cols_ = other.size(); size_t sz = piMin(cols_, other.size()); size_t ps = mat.size(); mat.resize(mat.size() + cols_); mat._copyRaw(mat.data(ps), other.data(), sz); rows_++; return *this; } inline PIVector2D & resize(size_t rows, size_t cols, const T & f = T()) { mat.resize(rows*cols_, f); rows_ = rows; int cs = (cols - cols_); if (cs < 0) { for (size_t r=0; r 0) { for (size_t r=0; r & t) const { if (cols_ != t.cols_ || rows_ != t.rows_) return false; return mat == t.mat; } inline bool operator !=(const PIVector2D & t) const {return !(*this == t);} PIVector > toVectors() const { PIVector > ret; ret.reserve(rows_); for(size_t i = 0; i < rows_; ++i) ret << PIVector(mat.data(i*cols_), cols_); return ret; } PIVector toPlainVector() const {return mat;} PIVector & plainVector() {return mat;} const PIVector & plainVector() const {return mat;} inline void swap(PIVector2D & other) { mat.swap(other.mat); piSwap(rows_, other.rows_); piSwap(cols_, other.cols_); } template::value , int>::type = 0> inline PIVector2D & _resizeRaw(size_t r, size_t c) { rows_ = r; cols_ = c; mat._resizeRaw(r*c); return *this; } inline void clear() { rows_ = cols_ = 0; mat.clear(); } protected: size_t rows_, cols_; PIVector mat; }; template inline PICout operator <<(PICout s, const PIVector2D & v) { s.setControl(0, true); s << "{"; for (size_t i = 0; i < v.rows(); ++i) { s << "{ "; for (size_t j = 0; j < v.cols(); ++j) { s << v[i][j]; if (j < v.cols() - 1) s << ", "; } s << " }"; if (i < v.rows() - 1) s << PICoutManipulators::NewLine ; } if (v.isEmpty()) s << "{ }"; s << "}"; s.restoreControl(); return s; } #endif // PIVECTOR2D_H