PIVector2D - add funcs, optimize, tests, fixes, doxygen #194

Merged
andrey merged 29 commits from vibecoding_pivector2d into master 2026-02-27 23:58:45 +03:00
Showing only changes of commit 525dbf8e9e - Show all commits

View File

@@ -785,6 +785,64 @@ public:
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;
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);
}
}
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()) {
cols_ = 0;
rows_ = 0;
}
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);
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<T> & addColumn(const ColConst & other) {
@@ -880,7 +938,7 @@ public:
rows_ = rows;
return *this;
}
return __resize(rows, cols, f, std::is_trivially_copyable<T>());
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<T> & 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<T> & 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<typename T1 = T, typename std::enable_if<std::is_trivially_copyable<T1>::value, int>::type = 0>
inline PIVector2D<T> & __resize(size_t rows, size_t cols, const T & f, std::true_type) {
PIVector2D<T> tmp(rows, cols, f);
const size_t copyRows = piMin<size_t>(rows_, rows);
const size_t copyCols = piMin<size_t>(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<T> & __resize(size_t rows, size_t cols, const T & f) {
if (cols > cols_) {
addEmptyColumns(cols - cols_, f);
}
swap(tmp);
return *this;
if (rows > rows_) {
addEmptyRows(rows - rows_, f);
}
template<typename T1 = T, typename std::enable_if<!std::is_trivially_copyable<T1>::value, int>::type = 0>
inline PIVector2D<T> & __resize(size_t rows, size_t cols, const T & f, std::false_type) {
PIVector2D<T> tmp(rows, cols, f);
const size_t copyRows = piMin<size_t>(rows_, rows);
const size_t copyCols = piMin<size_t>(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 (cols < cols_) {
deleteColumns(cols, cols_ - cols);
}
if (rows < rows_) {
deleteRows(rows, rows_ - rows);
}
swap(tmp);
return *this;
}