pivector2d fix add\remove rows\cols and resize

This commit is contained in:
2026-02-27 18:40:09 +03:00
parent 97691e888c
commit 0b7d565b93
2 changed files with 342 additions and 103 deletions

View File

@@ -777,66 +777,57 @@ public:
//! \~russian Добавляет новую строку в конец массива из \a PIVector.
inline PIVector2D<T> & addRow(const PIVector<T> & other) {
if (cols_ == 0) cols_ = other.size();
const size_t sz = piMin<size_t>(cols_, other.size());
const size_t ps = mat.size();
mat.resize(mat.size() + cols_);
mat._copyRaw(mat.data(ps), other.data(), sz);
mat.append(other);
rows_++;
mat.resize(rows_ * cols_);
return *this;
}
// TODO: fix - memove existing elements
inline PIVector2D<T> & addEmptyRows(size_t count, const T & f = T()) {
if (count == 0 || cols_ == 0) return *this;
inline PIVector2D<T> & appendRows(size_t count, const T & f = T()) {
if (count == 0) return *this;
if (cols_ == 0) ++cols_;
mat.resize(mat.size() + count * cols_, f);
rows_ += count;
return *this;
}
// TODO: fix - memove existing elements
inline PIVector2D<T> & 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);
}
inline PIVector2D<T> & appendColumns(size_t count, const T & f = T()) {
if (count == 0) return *this;
if (rows_ == 0) {
mat.resize(count, f);
rows_ = 1;
cols_ = count;
return *this;
}
const size_t newCols = cols_ + count;
mat.reserve(rows_ * newCols);
for (size_t r = rows_; r > 0; --r) {
mat.insert(r * cols_, f, count);
}
cols_ = newCols;
return *this;
}
inline PIVector2D<T> & deleteRows(size_t row, size_t count) {
if (row >= rows_) return *this;
mat.remove(row * cols_, cols_ * count);
rows_ -= count;
if (mat.isEmpty()) {
inline PIVector2D<T> & deleteRows(size_t row_start, size_t count) {
if (row_start >= rows_ || count == 0) return *this;
mat.remove(row_start * cols_, cols_ * count);
if (isEmpty()) {
cols_ = 0;
rows_ = 0;
} else {
rows_ -= count;
}
return *this;
}
inline PIVector2D<T> & deleteColumns(size_t col, size_t count) {
if (col >= cols_ || rows_ == 0 || count == 0) return *this;
count = piMin(count, cols_ - col);
inline PIVector2D<T> & deleteColumns(size_t col_start, size_t count) {
if (col_start >= cols_ || rows_ == 0) return *this;
count = piMin(count, cols_ - col_start);
if (count == 0) return *this;
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));
}
mat.remove(r * (cols_ - count) + col_start, count);
}
cols_ -= count;
mat.resize(rows_ * cols_);
@@ -847,32 +838,25 @@ public:
//! \~russian Добавляет новую строку в конец массива из \a ColConst.
inline PIVector2D<T> & addColumn(const ColConst & other) {
if (other.size() == 0) return *this;
if (size() == 0) {
_resizeRaw(other.size(), 1);
if (isEmpty()) {
mat.reserve(other.size());
for (size_t r = 0; r < other.size(); ++r) {
element(r, 0) = other[r];
mat.append(other[r]);
}
rows_ = mat.size();
cols_ = 1;
return *this;
}
const size_t oldCols = cols_;
const size_t newCols = oldCols + 1;
const size_t newSize = rows_ * newCols;
mat._resizeRaw(newSize);
for (size_t r = rows_ - 1; r > 0; --r) {
T * src = mat.data(r * oldCols);
T * dst = mat.data(r * newCols);
memmove(dst, src, oldCols * sizeof(T));
if (r < other.size()) {
mat._copyRaw(&(dst[oldCols]), &(other[r]), 1);
const size_t newCols = cols_ + 1;
mat.reserve(rows_ * newCols);
for (size_t r = rows_; r > 0; --r) {
if (r - 1 < other.size()) {
mat.insert(r * cols_, other[r - 1]);
} else {
const T tmp = T();
mat._copyRaw(&(dst[oldCols]), &tmp, 1);
mat.insert(r * cols_);
}
}
mat._copyRaw(mat.data(oldCols), &(other[0]), 1);
cols_ = newCols;
return *this;
@@ -882,32 +866,22 @@ public:
//! \~russian Добавляет новую строку в конец массива из \a PIVector.
inline PIVector2D<T> & addColumn(const PIVector<T> & other) {
if (other.size() == 0) return *this;
if (size() == 0) {
_resizeRaw(other.size(), 1);
for (size_t r = 0; r < other.size(); ++r) {
element(r, 0) = other[r];
}
if (isEmpty()) {
mat.append(other);
rows_ = mat.size();
cols_ = 1;
return *this;
}
const size_t oldCols = cols_;
const size_t newCols = oldCols + 1;
const size_t newSize = rows_ * newCols;
mat._resizeRaw(newSize);
for (size_t r = rows_ - 1; r > 0; --r) {
T * src = mat.data(r * oldCols);
T * dst = mat.data(r * newCols);
memmove(dst, src, oldCols * sizeof(T));
if (r < other.size()) {
mat._copyRaw(&(dst[oldCols]), &(other[r]), 1);
const size_t newCols = cols_ + 1;
mat.reserve(rows_ * newCols);
for (size_t r = rows_; r > 0; --r) {
if (r - 1 < other.size()) {
mat.insert(r * cols_, other[r - 1]);
} else {
const T tmp = T();
mat._copyRaw(&(dst[oldCols]), &tmp, 1);
mat.insert(r * cols_);
}
}
mat._copyRaw(mat.data(oldCols), &(other[0]), 1);
cols_ = newCols;
return *this;
@@ -938,7 +912,19 @@ public:
rows_ = rows;
return *this;
}
return __resize(rows, cols, f);
if (cols > cols_) {
appendColumns(cols - cols_, f);
}
if (rows > rows_) {
appendRows(rows - rows_, f);
}
if (cols < cols_) {
deleteColumns(cols, cols_ - cols);
}
if (rows < rows_) {
deleteRows(rows, rows_ - rows);
}
return *this;
}
//! \~english Equality operator.
@@ -1261,9 +1247,7 @@ public:
//! \~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<T> & removeRow(size_t row) {
return deleteRows(row, 1);
}
inline PIVector2D<T> & removeRow(size_t row) { return deleteRows(row, 1); }
//! \~english Removes a column from the 2D array.
//! \~russian Удаляет столбец из двумерного массива.
@@ -1271,9 +1255,7 @@ public:
//! \~english This operation is more expensive than removing a row because elements must be moved.
//! \~russian Эта операция дороже, чем удаление строки, поскольку требуется перемещение элементов.
//! \sa removeRow(), PIVector::remove()
inline PIVector2D<T> & removeColumn(size_t col) {
return deleteColumns(col, 1);
}
inline PIVector2D<T> & removeColumn(size_t col) { return deleteColumns(col, 1); }
//! \~english Removes all rows that satisfy a condition.
//! \~russian Удаляет все строки, удовлетворяющие условию.
@@ -1343,22 +1325,6 @@ public:
}
protected:
inline PIVector2D<T> & __resize(size_t rows, size_t cols, const T & f) {
if (cols > cols_) {
addEmptyColumns(cols - cols_, f);
}
if (rows > rows_) {
addEmptyRows(rows - rows_, f);
}
if (cols < cols_) {
deleteColumns(cols, cols_ - cols);
}
if (rows < rows_) {
deleteRows(rows, rows_ - rows);
}
return *this;
}
size_t rows_, cols_;
PIVector<T> mat;
};