diff --git a/libs/main/containers/pivector2d.h b/libs/main/containers/pivector2d.h index bd434075..dd21f4c5 100644 --- a/libs/main/containers/pivector2d.h +++ b/libs/main/containers/pivector2d.h @@ -785,6 +785,64 @@ public: return *this; } + // TODO: fix - memove existing elements + inline PIVector2D & addEmptyRows(size_t count, const T & f = T()) { + if (count == 0 || cols_ == 0) return *this; + mat.resize(mat.size() + count * cols_, f); + rows_ += count; + return *this; + } + + // TODO: fix - memove existing elements + inline PIVector2D & addEmptyColumns(size_t count, const T & f = T()) { + if (count == 0 || rows_ == 0) return *this; + const size_t newCols = cols_ + count; + const size_t newSize = rows_ * newCols; + mat.resize(newSize); + for (size_t r = rows_ - 1; r < rows_; --r) { + for (size_t c = newCols - 1; c >= cols_; --c) { + element(r, c) = f; + } + for (size_t c = cols_; c > 0; --c) { + element(r, c - 1 + count) = element(r, c - 1); + } + } + cols_ = newCols; + return *this; + } + + inline PIVector2D & deleteRows(size_t row, size_t count) { + if (row >= rows_) return *this; + mat.remove(row * cols_, cols_ * count); + rows_ -= count; + if (mat.isEmpty()) { + cols_ = 0; + rows_ = 0; + } + return *this; + } + + inline PIVector2D & deleteColumns(size_t col, size_t count) { + if (col >= cols_ || rows_ == 0 || count == 0) return *this; + count = piMin(count, cols_ - col); + for (size_t r = 0; r < rows_; ++r) { + T * dst = mat.data(r * (cols_ - count)); + T * src = mat.data(r * cols_); + if (col > 0) { + memmove(dst, src, col * sizeof(T)); + dst += col; + src += col; + } + size_t remaining = (cols_ - count) - col; + if (remaining > 0) { + memmove(dst, src + 1, remaining * sizeof(T)); + } + } + cols_ -= count; + mat.resize(rows_ * cols_); + return *this; + } + //! \~english Appends a new column to the right of the array from a \a ColConst. //! \~russian Добавляет новую строку в конец массива из \a ColConst. inline PIVector2D & addColumn(const ColConst & other) { @@ -880,7 +938,7 @@ public: rows_ = rows; return *this; } - return __resize(rows, cols, f, std::is_trivially_copyable()); + return __resize(rows, cols, f); } //! \~english Equality operator. @@ -1200,17 +1258,11 @@ public: //! \~english Removes a row from the 2D array. //! \~russian Удаляет строку из двумерного массива. //! \details - //! \~english The elements of the specified row are destroyed, and all subsequent rows are shifted up. - //! If the last row is removed and the array becomes empty, \a cols() is set to 0. - //! \~russian Элементы указанной строки уничтожаются, а все последующие строки сдвигаются вверх. - //! Если удаляется последняя строка и массив становится пустым, \a cols() устанавливается в 0. + //! \~english If the last row is removed and the array becomes empty, \a cols() is set to 0. + //! \~russian Если удаляется последняя строка и массив становится пустым, \a cols() устанавливается в 0. //! \sa removeColumn(), PIVector::remove() inline PIVector2D & removeRow(size_t row) { - if (row >= rows_) return *this; - mat.remove(row * cols_, cols_); - rows_--; - if (rows_ == 0) cols_ = 0; - return *this; + return deleteRows(row, 1); } //! \~english Removes a column from the 2D array. @@ -1220,23 +1272,7 @@ public: //! \~russian Эта операция дороже, чем удаление строки, поскольку требуется перемещение элементов. //! \sa removeRow(), PIVector::remove() inline PIVector2D & removeColumn(size_t col) { - if (col >= cols_ || rows_ == 0) return *this; - for (size_t r = 0; r < rows_; ++r) { - T * dst = mat.data(r * (cols_ - 1)); - T * src = mat.data(r * cols_); - if (col > 0) { - memmove(dst, src, col * sizeof(T)); - dst += col; - src += col; - } - size_t remaining = (cols_ - 1) - col; - if (remaining > 0) { - memmove(dst, src + 1, remaining * sizeof(T)); - } - } - cols_--; - mat.resize(rows_ * cols_); - return *this; + return deleteColumns(col, 1); } //! \~english Removes all rows that satisfy a condition. @@ -1307,31 +1343,19 @@ public: } protected: - template::value, int>::type = 0> - inline PIVector2D & __resize(size_t rows, size_t cols, const T & f, std::true_type) { - PIVector2D tmp(rows, cols, f); - const size_t copyRows = piMin(rows_, rows); - const size_t copyCols = piMin(cols_, cols); - for (size_t r = 0; r < copyRows; ++r) { - T * dst = tmp.mat.data() + r * cols; - T * src = mat.data() + r * cols_; - memmove(dst, src, copyCols * sizeof(T)); + inline PIVector2D & __resize(size_t rows, size_t cols, const T & f) { + if (cols > cols_) { + addEmptyColumns(cols - cols_, f); } - swap(tmp); - return *this; - } - - template::value, int>::type = 0> - inline PIVector2D & __resize(size_t rows, size_t cols, const T & f, std::false_type) { - PIVector2D tmp(rows, cols, f); - const size_t copyRows = piMin(rows_, rows); - const size_t copyCols = piMin(cols_, cols); - for (size_t r = 0; r < copyRows; ++r) { - for (size_t c = 0; c < copyCols; ++c) { - tmp.element(r, c) = element(r, c); - } + if (rows > rows_) { + addEmptyRows(rows - rows_, f); + } + if (cols < cols_) { + deleteColumns(cols, cols_ - cols); + } + if (rows < rows_) { + deleteRows(rows, rows_ - rows); } - swap(tmp); return *this; }