From 95d3c9c658e568fc592593e1aab8d117187600d3 Mon Sep 17 00:00:00 2001 From: "andrey.bychkov" Date: Wed, 18 Feb 2026 14:59:08 +0300 Subject: [PATCH] add more comments --- libs/main/containers/pivector2d.h | 411 +++++++++++++++++++++++++++--- 1 file changed, 375 insertions(+), 36 deletions(-) diff --git a/libs/main/containers/pivector2d.h b/libs/main/containers/pivector2d.h index 809277e8..a0abede9 100644 --- a/libs/main/containers/pivector2d.h +++ b/libs/main/containers/pivector2d.h @@ -47,26 +47,30 @@ //! строками можно работать как с объектами \a PIVector, что позволяет изменять отдельные элементы или присваивать целые строки. Нельзя //! напрямую добавлять или удалять элементы, чтобы изменить размеры массива после создания (используйте \a resize(), \a addRow(), \a //! removeRow(), \a removeColumn() для этого), но можно изменять значения существующих элементов. - +//! \sa PIVector template class PIVector2D { public: - //! \~english Constructs an empty 2D array. - //! \~russian Создает пустой двумерный массив. + //! \~english Constructs an empty 2D array. No memory is allocated. + //! \~russian Создаёт пустой двумерный массив. Память не выделяется. + //! \details + //! \~english After this constructor, \a rows() and \a cols() return 0, and \a isEmpty() returns true. + //! \~russian После этого конструктора \a rows() и \a cols() возвращают 0, а \a isEmpty() возвращает true. + //! \sa PIVector::PIVector() inline PIVector2D() { rows_ = cols_ = 0; } //! \~english Constructs a 2D array with the given dimensions, filled with copies of `f`. - //! \~russian Создает двумерный массив заданного размера, заполненный копиями `f`. + //! \~russian Создаёт двумерный массив заданного размера, заполненный копиями `f`. //! \param rows Number of rows. //! \param cols Number of columns. - //! \param f Value to fill the array with. - //! \~english \param rows Количество строк. - //! \~russian \param rows Количество строк. - //! \~english \param cols Количество столбцов. - //! \~russian \param cols Количество столбцов. - //! \~english \param f Значение для заполнения массива. - //! \~russian \param f Значение для заполнения массива. + //! \param f Value to fill the array with. Defaults to default-constructed T. + //! \details + //! \~english The underlying storage is a single contiguous block of memory of size `rows * cols`. + //! All elements are initialized with the value `f`. + //! \~russian Внутреннее хранилище представляет собой единый непрерывный блок памяти размером `rows * cols`. + //! Все элементы инициализируются значением `f`. + //! \sa PIVector::PIVector(size_t, const T&) inline PIVector2D(size_t rows, size_t cols, const T & f = T()) { rows_ = rows; cols_ = cols; @@ -74,10 +78,18 @@ public: } //! \~english Constructs a 2D array from an existing 1D vector, reshaping it. - //! \~russian Создает двумерный массив из существующего одномерного вектора, изменяя его форму. + //! \~russian Создаёт двумерный массив из существующего одномерного вектора, изменяя его форму. //! \param rows Number of rows. //! \param cols Number of columns. //! \param v The source 1D vector. Its size must be at least `rows * cols`. + //! \details + //! \~english The constructor copies the data from `v` into the internal flat vector. + //! If `v` is larger than `rows * cols`, the excess elements are ignored (the vector is truncated). + //! If `v` is smaller, the behaviour is undefined (an assertion may fail in debug mode). + //! \~russian Конструктор копирует данные из `v` во внутренний плоский вектор. + //! Если `v` больше, чем `rows * cols`, лишние элементы игнорируются (вектор обрезается). + //! Если `v` меньше, поведение не определено (в отладочном режиме может сработать assertion). + //! \sa PIVector::PIVector(const PIVector&), reshape() inline PIVector2D(size_t rows, size_t cols, const PIVector & v): rows_(rows), cols_(cols), mat(v) { mat.resize(rows * cols); } //! \~english Move constructs a 2D array from an existing 1D vector, reshaping it. @@ -85,11 +97,21 @@ public: //! \param rows Number of rows. //! \param cols Number of columns. //! \param v The source 1D vector (rvalue reference). Its size must be at least `rows * cols`. + //! \details + //! \~english The data is moved from `v` into the internal flat vector, avoiding a copy. + //! After construction, `v` is left in a valid but unspecified state. + //! \~russian Данные перемещаются из `v` во внутренний плоский вектор, что позволяет избежать копирования. + //! После завершения конструктора `v` остаётся в корректном, но неопределённом состоянии. + //! \sa PIVector::PIVector(PIVector&&) inline PIVector2D(size_t rows, size_t cols, PIVector && v): rows_(rows), cols_(cols), mat(std::move(v)) { mat.resize(rows * cols); } //! \~english Constructs a 2D array from a vector of vectors (jagged array). Assumes all inner vectors have the same size. - //! \~russian Создает двумерный массив из вектора векторов (рваного массива). Предполагается, что все внутренние векторы имеют - //! одинаковый размер. \param v The source vector of vectors. + //! \~russian Создаёт двумерный массив из вектора векторов (рваного массива). Предполагается, что все внутренние векторы имеют + //! одинаковый размер. \param v The source vector of vectors. \details + //! \~english If the input is empty, the constructed array is also empty. Otherwise, the number of columns is taken from the size of the + //! first inner vector. All inner vectors are concatenated in the internal flat storage. + //! \~russian Если входной массив пуст, создаётся пустой двумерный массив. В противном случае количество столбцов берётся из размера + //! первого внутреннего вектора. Все внутренние векторы конкатенируются во внутреннем плоском хранилище. \sa PIVector::append() inline PIVector2D(const PIVector> & v) { rows_ = v.size(); if (rows_) { @@ -103,36 +125,67 @@ public: if (mat.isEmpty()) rows_ = cols_ = 0; } - //! \~english Number of rows. - //! \~russian Количество строк. + //! \~english Returns the number of rows in the 2D array. + //! \~russian Возвращает количество строк в двумерном массиве. + //! \return Number of rows. + //! \details + //! \~english The result is always non-negative. If the array is empty, returns 0. + //! \~russian Результат всегда неотрицательный. Если массив пуст, возвращает 0. + //! \sa cols(), size(), PIVector::size() inline size_t rows() const { return rows_; } - //! \~english Number of columns. - //! \~russian Количество столбцов. + //! \~english Returns the number of columns in the 2D array. + //! \~russian Возвращает количество столбцов в двумерном массиве. + //! \return Number of columns. + //! \details + //! \~english The result is always non-negative. If the array is empty, returns 0. + //! \~russian Результат всегда неотрицательный. Если массив пуст, возвращает 0. + //! \sa rows(), size(), PIVector::size() inline size_t cols() const { return cols_; } - //! \~english Total number of elements (`rows * cols`). - //! \~russian Общее количество элементов (`строки * столбцы`). + //! \~english Returns the total number of elements (`rows * cols`). + //! \~russian Возвращает общее количество элементов (`строки * столбцы`). + //! \return Total number of elements. + //! \details + //! \~english This is equivalent to the size of the underlying flat vector. + //! \~russian Это эквивалентно размеру внутреннего плоского вектора. + //! \sa rows(), cols(), PIVector::size() inline size_t size() const { return mat.size(); } - //! \~english Total number of elements as signed value. - //! \~russian Общее количество элементов в виде знакового числа. + //! \~english Returns the total number of elements as a signed value. + //! \~russian Возвращает общее количество элементов в виде знакового числа. + //! \return Signed size. + //! \sa size(), PIVector::size_s() inline ssize_t size_s() const { return mat.size_s(); } - //! \~english Total number of elements. - //! \~russian Общее количество элементов. + //! \~english Returns the total number of elements (same as \a size()). + //! \~russian Возвращает общее количество элементов (то же, что и \a size()). + //! \return Total number of elements. + //! \sa size(), PIVector::length() inline size_t length() const { return mat.length(); } - //! \~english Number of elements that the underlying container has currently allocated space for. - //! \~russian Количество элементов, для которого сейчас выделена память во внутреннем контейнере. + //! \~english Returns the number of elements that the underlying container has currently allocated space for. + //! \~russian Возвращает количество элементов, для которого сейчас выделена память во внутреннем контейнере. + //! \return Capacity of the flat vector. + //! \details + //! \~english This value may be larger than \a size(). It indicates how many elements can be added before a reallocation is needed. + //! \~russian Это значение может быть больше, чем \a size(). Оно показывает, сколько элементов можно добавить до того, как потребуется + //! перераспределение памяти. \sa reserve(), PIVector::capacity() inline size_t capacity() const { return mat.capacity(); } //! \~english Checks if the array has no elements. //! \~russian Проверяет, пуст ли массив. + //! \return \c true if the array is empty, \c false otherwise. + //! \details + //! \~english An empty array has both rows and columns equal to 0. + //! \~russian Пустой массив имеет и строки, и столбцы равные 0. + //! \sa isNotEmpty(), PIVector::isEmpty() inline bool isEmpty() const { return mat.isEmpty(); } - //! \~english Checks if the array has elements. + //! \~english Checks if the array has at least one element. //! \~russian Проверяет, не пуст ли массив. + //! \return \c true if the array is not empty, \c false otherwise. + //! \sa isEmpty(), PIVector::isNotEmpty() inline bool isNotEmpty() const { return mat.isNotEmpty(); } @@ -140,6 +193,13 @@ public: //! \brief //! \~english Proxy class representing a single row in a \a PIVector2D for modification. //! \~russian Прокси-класс, представляющий одну строку в \a PIVector2D для модификации. + //! \details + //! \~english Objects of this class are returned by non-const \a operator[] or \a row(). + //! They provide array-like access to the elements of a specific row and allow operations such as assignment from another row or a \a + //! PIVector, searching, filling, and iteration. + //! \~russian Объекты этого класса возвращаются неконстантными операторами \a operator[] или методом \a row(). + //! Они предоставляют доступ к элементам конкретной строки, подобный массиву, и позволяют выполнять такие операции, как присваивание из + //! другой строки или \a PIVector, поиск, заполнение и итерацию. \sa Col, RowConst class Row { friend class PIVector2D; @@ -152,28 +212,55 @@ public: size_t st_, sz_; public: - //! \~english Size of the row (number of columns). - //! \~russian Размер строки (количество столбцов). + //! \~english Returns the number of columns in this row. + //! \~russian Возвращает количество столбцов в этой строке. + //! \return Row size (number of columns). + //! \sa PIVector::size() inline size_t size() const { return sz_; } //! \~english Accesses the element at the given column index within the row. //! \~russian Доступ к элементу по заданному индексу столбца в строке. + //! \param index Column index (must be less than size()). + //! \return Reference to the element. + //! \details + //! \~english No bounds checking is performed in release builds; use with caution. + //! \~russian В релизной сборке проверка границ не выполняется; используйте с осторожностью. + //! \sa PIVector::operator[] inline T & operator[](size_t index) { return (*p_)[st_ + index]; } //! \~english Const access to the element at the given column index within the row. //! \~russian Константный доступ к элементу по заданному индексу столбца в строке. + //! \param index Column index (must be less than size()). + //! \return Const reference to the element. + //! \sa operator[] (non-const) inline const T & operator[](size_t index) const { return (*p_)[st_ + index]; } //! \~english Returns a pointer to the row data starting at an optional offset. //! \~russian Возвращает указатель на данные строки, начиная с опционального смещения. + //! \param index Offset within the row (default 0). + //! \return Pointer to the first element at the given offset. + //! \details + //! \~english The pointer can be used for direct memory operations. It remains valid as long as the underlying 2D array is not + //! reallocated. + //! \~russian Указатель можно использовать для прямых операций с памятью. Он остаётся действительным, пока не произойдёт + //! перераспределение памяти внутреннего двумерного массива. \sa PIVector::data() inline T * data(size_t index = 0) { return p_->data(st_ + index); } //! \~english Returns a const pointer to the row data starting at an optional offset. //! \~russian Возвращает константный указатель на данные строки, начиная с опционального смещения. + //! \param index Offset within the row (default 0). + //! \return Const pointer. + //! \sa data() (non-const) inline const T * data(size_t index = 0) const { return p_->data(st_ + index); } //! \~english Assigns the contents of another Row to this row. //! \~russian Присваивает этой строке содержимое другой строки. + //! \param other Source row. + //! \return Reference to this row. + //! \details + //! \~english Only the minimum of the two row sizes is copied; if this row is shorter, excess elements in `other` are ignored. + //! \~russian Копируется только минимум из размеров двух строк; если эта строка короче, лишние элементы из `other` игнорируются. + //! \sa PIVector::operator= inline Row & operator=(const Row & other) { if (p_ == other.p_ && st_ == other.st_) return *this; const size_t sz = piMin(sz_, other.sz_); @@ -183,6 +270,12 @@ public: //! \~english Assigns the contents of a \a PIVector to this row. //! \~russian Присваивает этой строке содержимое \a PIVector. + //! \param other Source vector. + //! \return Reference to this row. + //! \details + //! \~english Only the minimum of the row size and vector size is copied. + //! \~russian Копируется только минимум из размера строки и размера вектора. + //! \sa PIVector::operator= inline Row & operator=(const PIVector & other) { const size_t sz = piMin(sz_, other.size()); p_->_copyRaw(p_->data(st_), other.data(), sz); @@ -191,8 +284,19 @@ public: //! \~english Converts the row to a \a PIVector. //! \~russian Преобразует строку в \a PIVector. + //! \return A new \a PIVector containing a copy of the row elements. + //! \sa PIVector::PIVector(const T*, size_t) inline PIVector toVector() const { return PIVector(p_->data(st_), sz_); } + //! \~english Returns the first index of element `e` in the row, starting from `start`. + //! \~russian Возвращает первый индекс элемента `e` в строке, начиная с позиции `start`. + //! \param e Element to search for. + //! \param start Starting index (negative values count from the end). Default 0. + //! \return Index if found, -1 otherwise. + //! \details + //! \~english See \a PIVector::indexOf() for details on negative start handling. + //! \~russian Подробнее об обработке отрицательного `start` см. \a PIVector::indexOf(). + //! \sa PIVector::indexOf() inline ssize_t indexOf(const T & e, ssize_t start = 0) const { if (start < 0) start = 0; for (size_t i = (size_t)start; i < sz_; ++i) { @@ -201,6 +305,12 @@ public: return -1; } + //! \~english Returns the last index of element `e` in the row, searching backwards from `start`. + //! \~russian Возвращает последний индекс элемента `e` в строке, выполняя поиск в обратном направлении от `start`. + //! \param e Element to search for. + //! \param start Starting index (negative values count from the end). Default -1 (last element). + //! \return Index if found, -1 otherwise. + //! \sa PIVector::lastIndexOf() inline ssize_t lastIndexOf(const T & e, ssize_t start = -1) const { ssize_t from = (start < 0 || (size_t)start >= sz_) ? (ssize_t)sz_ - 1 : start; for (ssize_t i = from; i >= 0; --i) { @@ -209,6 +319,12 @@ public: return -1; } + //! \~english Returns the first index where the predicate `test` returns true, starting from `start`. + //! \~russian Возвращает первый индекс, для которого предикат `test` возвращает true, начиная с `start`. + //! \param test Predicate function: `bool(const T&)`. + //! \param start Starting index (negative values count from the end). Default 0. + //! \return Index if found, -1 otherwise. + //! \sa PIVector::indexWhere() inline ssize_t indexWhere(std::function test, ssize_t start = 0) const { if (start < 0) start = 0; for (size_t i = (size_t)start; i < sz_; ++i) { @@ -217,6 +333,10 @@ public: return -1; } + //! \~english Returns the last index where the predicate `test` returns true, searching backwards from `start`. + //! \~russian Возвращает последний индекс, для которого предикат `test` возвращает true, выполняя поиск в обратном направлении от + //! `start`. \param test Predicate function: `bool(const T&)`. \param start Starting index (negative values count from the end). + //! Default -1. \return Index if found, -1 otherwise. \sa PIVector::lastIndexWhere() inline ssize_t lastIndexWhere(std::function test, ssize_t start = -1) const { ssize_t from = (start < 0 || (size_t)start >= sz_) ? (ssize_t)sz_ - 1 : start; for (ssize_t i = from; i >= 0; --i) { @@ -227,6 +347,11 @@ public: //! \~english Applies a function to each element of the row (modifiable). //! \~russian Применяет функцию к каждому элементу строки (с возможностью изменения). + //! \param func Function that takes a reference to T. + //! \details + //! \~english The function can modify the elements. + //! \~russian Функция может изменять элементы. + //! \sa PIVector::forEach() inline void forEach(std::function func) { for (size_t i = 0; i < sz_; ++i) { func((*p_)[st_ + i]); @@ -235,6 +360,8 @@ public: //! \~english Applies a function to each element of the row (read-only). //! \~russian Применяет функцию к каждому элементу строки (только чтение). + //! \param func Function that takes a const reference to T. + //! \sa forEach (modifiable) inline void forEach(std::function func) const { for (size_t i = 0; i < sz_; ++i) { func((*p_)[st_ + i]); @@ -243,6 +370,8 @@ public: //! \~english Fills the row with copies of `value`. //! \~russian Заполняет строку копиями `value`. + //! \param value Value to fill with. + //! \sa PIVector::fill() inline void fill(const T & value) { for (size_t i = 0; i < sz_; ++i) { (*p_)[st_ + i] = value; @@ -251,10 +380,18 @@ public: //! \~english Checks if the row contains the element `e`. //! \~russian Проверяет, содержит ли строка элемент `e`. + //! \param e Element to check. + //! \param start Starting index (negative allowed). Default 0. + //! \return \c true if found, \c false otherwise. + //! \sa PIVector::contains() inline bool contains(const T & e, ssize_t start = 0) const { return indexOf(e, start) != -1; } //! \~english Counts occurrences of `e` in the row. //! \~russian Подсчитывает количество вхождений `e` в строке. + //! \param e Element to count. + //! \param start Starting index (negative allowed). Default 0. + //! \return Number of occurrences. + //! \sa PIVector::entries() inline int entries(const T & e, ssize_t start = 0) const { if (start < 0) start = 0; int count = 0; @@ -266,6 +403,10 @@ public: //! \~english Counts elements in the row that pass the `test`. //! \~russian Подсчитывает элементы в строке, проходящие `test`. + //! \param test Predicate function. + //! \param start Starting index (negative allowed). Default 0. + //! \return Count of matching elements. + //! \sa PIVector::entries(std::function) inline int entries(std::function test, ssize_t start = 0) const { if (start < 0) start = 0; int count = 0; @@ -277,6 +418,9 @@ public: //! \~english Tests if any element in the row passes the `test`. //! \~russian Проверяет, проходит ли какой-либо элемент в строке `test`. + //! \param test Predicate function. + //! \return \c true if at least one element satisfies the predicate. + //! \sa PIVector::any() inline bool any(std::function test) const { for (size_t i = 0; i < sz_; ++i) { if (test((*p_)[st_ + i])) return true; @@ -286,6 +430,9 @@ public: //! \~english Tests if all elements in the row pass the `test`. //! \~russian Проверяет, проходят ли все элементы в строке `test`. + //! \param test Predicate function. + //! \return \c true if all elements satisfy the predicate. + //! \sa PIVector::every() inline bool every(std::function test) const { for (size_t i = 0; i < sz_; ++i) { if (!test((*p_)[st_ + i])) return false; @@ -298,6 +445,11 @@ public: //! \brief //! \~english Proxy class representing a single column in a \a PIVector2D for modification. //! \~russian Прокси-класс, представляющий один столбец в \a PIVector2D для модификации. + //! \details + //! \~english Objects of this class are returned by non-const \a col(). They provide column-wise access and operations similar to \a + //! Row. + //! \~russian Объекты этого класса возвращаются неконстантным методом \a col(). Они предоставляют доступ к столбцам и операции, + //! аналогичные \a Row. \sa Row, ColConst class Col { friend class PIVector2D; @@ -311,12 +463,14 @@ public: size_t step_, col_, sz_; public: - //! \~english Size of the column (number of rows). - //! \~russian Размер столбца (количество строк). + //! \~english Returns the size of the column (number of rows). + //! \~russian Возвращает размер столбца (количество строк). inline size_t size() const { return sz_; } //! \~english Accesses the element at the given row index within the column. //! \~russian Доступ к элементу по заданному индексу строки в столбце. + //! \param index Row index. + //! \return Reference to the element. inline T & operator[](size_t index) { return (*p_)[index * step_ + col_]; } //! \~english Const access to the element at the given row index within the column. @@ -325,6 +479,13 @@ public: //! \~english Returns a pointer to the column data starting at an optional row offset. //! \~russian Возвращает указатель на данные столбца, начиная с опционального смещения по строкам. + //! \param index Row offset (default 0). + //! \return Pointer to the element at the given row. + //! \details + //! \~english Note that column elements are not stored contiguously in memory, so this pointer cannot be used to iterate over the + //! whole column. + //! \~russian Обратите внимание, что элементы столбца не хранятся в памяти непрерывно, поэтому этот указатель нельзя использовать + //! для итерации по всему столбцу. inline T * data(size_t index = 0) { return p_->data(index * step_ + col_); } //! \~english Returns a const pointer to the column data starting at an optional row offset. @@ -333,6 +494,8 @@ public: //! \~english Assigns the contents of another Col to this column. //! \~russian Присваивает этому столбцу содержимое другого столбца. + //! \param other Source column. + //! \return Reference to this column. inline Col & operator=(const Col & other) { if (p_ == other.p_ && col_ == other.col_) return *this; const size_t sz = piMin(sz_, other.sz_); @@ -343,6 +506,8 @@ public: //! \~english Assigns the contents of a \a PIVector to this column. //! \~russian Присваивает этому столбцу содержимое \a PIVector. + //! \param other Source vector. + //! \return Reference to this column. inline Col & operator=(const PIVector & other) { const size_t sz = piMin(sz_, other.size()); for (size_t i = 0; i < sz; ++i) @@ -352,6 +517,7 @@ public: //! \~english Converts the column to a \a PIVector. //! \~russian Преобразует столбец в \a PIVector. + //! \return A new \a PIVector containing a copy of the column elements. inline PIVector toVector() const { PIVector ret; ret.reserve(sz_); @@ -360,6 +526,8 @@ public: return ret; } + //! \~english Returns the first index (row) where element `e` appears in the column. + //! \~russian Возвращает первый индекс (строку), в которой элемент `e` появляется в столбце. inline ssize_t indexOf(const T & e, ssize_t start = 0) const { if (start < 0) start = 0; for (size_t i = (size_t)start; i < sz_; ++i) { @@ -368,6 +536,7 @@ public: return -1; } + //! \~english Returns the last index (row) where element `e` appears in the column. inline ssize_t lastIndexOf(const T & e, ssize_t start = -1) const { ssize_t from = (start < 0 || (size_t)start >= sz_) ? (ssize_t)sz_ - 1 : start; for (ssize_t i = from; i >= 0; --i) { @@ -376,6 +545,7 @@ public: return -1; } + //! \~english Returns the first row index where the predicate `test` returns true. inline ssize_t indexWhere(std::function test, ssize_t start = 0) const { if (start < 0) start = 0; for (size_t i = (size_t)start; i < sz_; ++i) { @@ -384,6 +554,7 @@ public: return -1; } + //! \~english Returns the last row index where the predicate `test` returns true. inline ssize_t lastIndexWhere(std::function test, ssize_t start = -1) const { ssize_t from = (start < 0 || (size_t)start >= sz_) ? (ssize_t)sz_ - 1 : start; for (ssize_t i = from; i >= 0; --i) { @@ -465,6 +636,10 @@ public: //! \brief //! \~english Proxy class representing a single read-only row in a \a PIVector2D. //! \~russian Прокси-класс, представляющий одну строку в \a PIVector2D только для чтения. + //! \details + //! \~english Returned by const \a operator[] or \a row(). Provides const access to row elements. + //! \~russian Возвращается константными версиями \a operator[] или \a row(). Предоставляет константный доступ к элементам строки. + //! \sa Row, ColConst class RowConst { friend class PIVector2D; @@ -501,6 +676,7 @@ public: return -1; } + //! \~english Searches for element `e` backwards (see Row::lastIndexOf). inline ssize_t lastIndexOf(const T & e, ssize_t start = -1) const { ssize_t from = (start < 0 || (size_t)start >= sz_) ? (ssize_t)sz_ - 1 : start; for (ssize_t i = from; i >= 0; --i) { @@ -509,6 +685,7 @@ public: return -1; } + //! \~english Searches with predicate (see Row::indexWhere). inline ssize_t indexWhere(std::function test, ssize_t start = 0) const { if (start < 0) start = 0; for (size_t i = (size_t)start; i < sz_; ++i) { @@ -517,6 +694,7 @@ public: return -1; } + //! \~english Searches with predicate backwards (see Row::lastIndexWhere). inline ssize_t lastIndexWhere(std::function test, ssize_t start = -1) const { ssize_t from = (start < 0 || (size_t)start >= sz_) ? (ssize_t)sz_ - 1 : start; for (ssize_t i = from; i >= 0; --i) { @@ -582,6 +760,10 @@ public: //! \brief //! \~english Proxy class representing a single read-only column in a \a PIVector2D. //! \~russian Прокси-класс, представляющий один столбец в \a PIVector2D только для чтения. + //! \details + //! \~english Returned by const \a col(). Provides const access to column elements. + //! \~russian Возвращается константной версией \a col(). Предоставляет константный доступ к элементам столбца. + //! \sa Col, RowConst class ColConst { friend class PIVector2D; @@ -617,6 +799,7 @@ public: return ret; } + //! \~english Searches for element `e` (see Col::indexOf). inline ssize_t indexOf(const T & e, ssize_t start = 0) const { if (start < 0) start = 0; for (size_t i = (size_t)start; i < sz_; ++i) { @@ -625,6 +808,7 @@ public: return -1; } + //! \~english Searches for element `e` backwards (see Col::lastIndexOf). inline ssize_t lastIndexOf(const T & e, ssize_t start = -1) const { ssize_t from = (start < 0 || (size_t)start >= sz_) ? (ssize_t)sz_ - 1 : start; for (ssize_t i = from; i >= 0; --i) { @@ -633,6 +817,7 @@ public: return -1; } + //! \~english Searches with predicate (see Col::indexWhere). inline ssize_t indexWhere(std::function test, ssize_t start = 0) const { if (start < 0) start = 0; for (size_t i = (size_t)start; i < sz_; ++i) { @@ -641,6 +826,7 @@ public: return -1; } + //! \~english Searches with predicate backwards (see Col::lastIndexWhere). inline ssize_t lastIndexWhere(std::function test, ssize_t start = -1) const { ssize_t from = (start < 0 || (size_t)start >= sz_) ? (ssize_t)sz_ - 1 : start; for (ssize_t i = from; i >= 0; --i) { @@ -704,6 +890,13 @@ public: //! \~english Returns a reference to the element at the given row and column. //! \~russian Возвращает ссылку на элемент по заданной строке и столбцу. + //! \param row Row index. + //! \param col Column index. + //! \return Reference to the element. + //! \details + //! \~english No bounds checking is performed. + //! \~russian Проверка границ не выполняется. + //! \sa at() (const version), PIVector::operator[] inline T & element(size_t row, size_t col) { return mat[row * cols_ + col]; } //! \~english Returns a const reference to the element at the given row and column. @@ -716,6 +909,9 @@ public: //! \~english Returns a proxy object for the row at the given index for modification. //! \~russian Возвращает прокси-объект для строки по заданному индексу для модификации. + //! \param index Row index. + //! \return Row proxy. + //! \sa row(), Col inline Row operator[](size_t index) { return Row(this, index); } //! \~english Returns a proxy object for the row at the given index for read-only access. @@ -724,6 +920,9 @@ public: //! \~english Returns a pointer to the underlying flat data starting at an optional offset. //! \~russian Возвращает указатель на внутренние плоские данные, начиная с опционального смещения. + //! \param index Flat index offset. + //! \return Pointer to data. + //! \sa PIVector::data() inline T * data(size_t index = 0) { return mat.data(index); } //! \~english Returns a const pointer to the underlying flat data starting at an optional offset. @@ -733,6 +932,7 @@ public: //! \~english Returns a proxy object for the row at the given index for modification. //! \~russian Возвращает прокси-объект для строки по заданному индексу для модификации. + //! \sa operator[] inline Row row(size_t index) { return Row(this, index); } //! \~english Returns a proxy object for the row at the given index for read-only access. @@ -741,6 +941,9 @@ public: //! \~english Returns a proxy object for the column at the given index for modification. //! \~russian Возвращает прокси-объект для столбца по заданному индексу для модификации. + //! \param index Column index. + //! \return Column proxy. + //! \sa col() const inline Col col(size_t index) { return Col(this, index); } //! \~english Returns a proxy object for the column at the given index for read-only access. @@ -750,6 +953,9 @@ public: //! \~english Replaces a row with the contents of another Row object. //! \~russian Заменяет строку содержимым другого объекта Row. + //! \param row Row index. + //! \param other Source row. + //! \return Reference to this 2D array. inline PIVector2D & setRow(size_t row, const Row & other) { const size_t sz = piMin(cols_, other.sz_); mat._copyRaw(mat.data(cols_ * row), other.data(), sz); @@ -774,6 +980,14 @@ public: //! \~english Appends a new row to the bottom of the array from another Row object. //! \~russian Добавляет новую строку в конец массива из другого объекта Row. + //! \param other Source row. + //! \return Reference to this array. + //! \details + //! \~english If the array was empty, its column count is set to the size of the source row. + //! Otherwise, only `min(cols(), other.size())` elements are copied; the rest of the new row is default-initialized. + //! \~russian Если массив был пуст, количество столбцов устанавливается равным размеру исходной строки. + //! В противном случае копируется только `min(cols(), other.size())` элементов; остальные элементы новой строки инициализируются по + //! умолчанию. \sa PIVector::push_back() inline PIVector2D & addRow(const Row & other) { if (cols_ == 0) cols_ = other.sz_; const size_t sz = piMin(cols_, other.sz_); @@ -810,11 +1024,20 @@ public: //! \~english Resizes the 2D array to new dimensions. //! \~russian Изменяет размер двумерного массива. + //! \param rows New number of rows. + //! \param cols New number of columns. + //! \param f Value to fill newly created elements (if growing). Defaults to default-constructed T. + //! \return Reference to this array. //! \details - //! \~english If the new dimensions are larger, new elements are filled with `f`. - //! If they are smaller, the array is truncated. - //! \~russian Если новые размеры больше, новые элементы заполняются `f`. - //! Если они меньше, массив обрезается. + //! \~english If the new dimensions are larger, new elements are appended and filled with copies of `f`. + //! If they are smaller, the array is truncated (excess elements are destroyed). The underlying memory may be reallocated. + //! \~russian Если новые размеры больше текущих, новые элементы добавляются в конец и заполняются копиями `f`. + //! Если новые размеры меньше, массив усекается (лишние элементы уничтожаются). Внутренняя память может быть перераспределена. + //! \code + //! PIVector2D mat(2, 3, 0); // 2x3 matrix filled with 0 + //! mat.resize(3, 4, 1); // becomes 3x4, new elements filled with 1 + //! \endcode + //! \sa PIVector::resize() inline PIVector2D & resize(size_t rows, size_t cols, const T & f = T()) { if (rows == rows_ && cols == cols_) return *this; PIVector2D tmp(rows, cols, f); @@ -831,6 +1054,9 @@ public: //! \~english Equality operator. //! \~russian Оператор равенства. + //! \param t Another 2D array. + //! \return \c true if both arrays have the same dimensions and all elements are equal. + //! \sa PIVector::operator== inline bool operator==(const PIVector2D & t) const { if (cols_ != t.cols_ || rows_ != t.rows_) return false; return mat == t.mat; @@ -842,6 +1068,11 @@ public: //! \~english Converts the 2D array to a vector of vectors (PIVector>). //! \~russian Преобразует двумерный массив в вектор векторов (PIVector>). + //! \return A new vector where each element is a \a PIVector representing a row. + //! \details + //! \~english Each row vector is a copy of the corresponding row. + //! \~russian Каждый вектор-строка является копией соответствующей строки. + //! \sa fromVectors(), PIVector::PIVector(const T*, size_t) inline PIVector> toVectors() const { PIVector> ret; ret.reserve(rows_); @@ -864,6 +1095,11 @@ public: //! \~english Swaps this 2D array with another. //! \~russian Меняет местами этот двумерный массив с другим. + //! \param other Another array. + //! \details + //! \~english Swaps the flat vectors and the dimension members. Very fast, no memory allocation. + //! \~russian Обменивает внутренние плоские векторы и члены, хранящие размеры. Очень быстро, без выделения памяти. + //! \sa PIVector::swap() inline void swap(PIVector2D & other) { mat.swap(other.mat); piSwap(rows_, other.rows_); @@ -881,6 +1117,10 @@ public: //! \~english Clears the array, removing all elements and setting dimensions to 0. //! \~russian Очищает массив, удаляя все элементы и устанавливая размеры в 0. + //! \details + //! \~english The capacity of the underlying flat vector may remain unchanged. + //! \~russian Ёмкость внутреннего плоского вектора может остаться неизменной. + //! \sa PIVector::clear() inline void clear() { rows_ = cols_ = 0; mat.clear(); @@ -889,23 +1129,31 @@ public: //! \~english Checks if the underlying flat vector contains the element `e`. //! \~russian Проверяет, содержит ли внутренний плоский вектор элемент `e`. + //! \sa PIVector::contains() inline bool contains(const T & e, ssize_t start = 0) const { return mat.contains(e, start); } //! \~english Checks if the underlying flat vector contains all elements of `v`. //! \~russian Проверяет, содержит ли внутренний плоский вектор все элементы `v`. + //! \sa PIVector::contains(const PIVector&) inline bool contains(const PIVector & v, ssize_t start = 0) const { return mat.contains(v, start); } //! \~english Counts occurrences of `e` in the underlying flat vector. //! \~russian Подсчитывает количество вхождений `e` во внутреннем плоском векторе. + //! \sa PIVector::entries() inline int entries(const T & e, ssize_t start = 0) const { return mat.entries(e, start); } //! \~english Counts elements in the flat vector that pass the `test`. //! \~russian Подсчитывает элементы в плоском векторе, проходящие `test`. + //! \sa PIVector::entries(std::function) inline int entries(std::function test, ssize_t start = 0) const { return mat.entries(test, start); } //! \~english Returns the first index (row, col) of `e` in the 2D array. //! \~russian Возвращает первый индекс (строка, столбец) элемента `e` в двумерном массиве. + //! \param e Element to search for. + //! \param start Starting flat index (negative allowed). Default 0. + //! \return A \a PIPair where first is row, second is column. If not found, both are -1. + //! \sa PIVector::indexOf() inline PIPair indexOf(const T & e, ssize_t start = 0) const { ssize_t flat = mat.indexOf(e, start); if (flat < 0 || cols_ == 0) return PIPair(-1, -1); @@ -914,6 +1162,7 @@ public: //! \~english Returns the first index (row, col) in the 2D array that passes the `test`. //! \~russian Возвращает первый индекс (строка, столбец) в двумерном массиве, проходящий `test`. + //! \sa PIVector::indexWhere() inline PIPair indexWhere(std::function test, ssize_t start = 0) const { ssize_t flat = mat.indexWhere(test, start); if (flat < 0 || cols_ == 0) return PIPair(-1, -1); @@ -922,6 +1171,7 @@ public: //! \~english Returns the last index (row, col) of `e` in the 2D array. //! \~russian Возвращает последний индекс (строка, столбец) элемента `e` в двумерном массиве. + //! \sa PIVector::lastIndexOf() inline PIPair lastIndexOf(const T & e, ssize_t start = -1) const { ssize_t flat = mat.lastIndexOf(e, start); if (flat < 0 || cols_ == 0) return PIPair(-1, -1); @@ -930,6 +1180,7 @@ public: //! \~english Returns the last index (row, col) in the 2D array that passes the `test`. //! \~russian Возвращает последний индекс (строка, столбец) в двумерном массиве, проходящий `test`. + //! \sa PIVector::lastIndexWhere() inline PIPair lastIndexWhere(std::function test, ssize_t start = -1) const { ssize_t flat = mat.lastIndexWhere(test, start); if (flat < 0 || cols_ == 0) return PIPair(-1, -1); @@ -939,14 +1190,18 @@ public: //! \~english Tests if any element in the flat vector passes the `test`. //! \~russian Проверяет, проходит ли какой-либо элемент в плоском векторе `test`. + //! \sa PIVector::any() inline bool any(std::function test) const { return mat.any(test); } //! \~english Tests if all elements in the flat vector pass the `test`. //! \~russian Проверяет, проходят ли все элементы в плоском векторе `test`. + //! \sa PIVector::every() inline bool every(std::function test) const { return mat.every(test); } //! \~english Fills the entire 2D array with copies of `e`. //! \~russian Заполняет весь двумерный массив копиями `e`. + //! \return Reference to this array. + //! \sa PIVector::fill() inline PIVector2D & fill(const T & e = T()) { mat.fill(e); return *this; @@ -954,6 +1209,9 @@ public: //! \~english Fills the entire 2D array using a generator function `f` based on flat index. //! \~russian Заполняет весь двумерный массив, используя функцию-генератор `f` на основе плоского индекса. + //! \param f Function taking a size_t flat index and returning a value of type T. + //! \return Reference to this array. + //! \sa PIVector::fill(std::function) inline PIVector2D & fill(std::function f) { mat.fill(f); return *this; @@ -965,6 +1223,7 @@ public: //! \~english Assigns new size and fills with value. //! \~russian Задаёт новый размер и заполняет значением. + //! \sa PIVector::assign(size_t, const T&) inline PIVector2D & assign(size_t rows, size_t cols, const T & f = T()) { mat.assign(rows * cols, f); rows_ = rows; @@ -973,9 +1232,16 @@ public: } - // TODO: исправить - при транспонировании количество строк становится количеством столбцов и наоборот //! \~english Returns a transposed 2D array (rows become columns and vice versa). //! \~russian Возвращает транспонированный двумерный массив (строки становятся столбцами и наоборот). + //! \return A new 2D array with dimensions (cols, rows). + //! \details + //! \~english The element at (r, c) in the original becomes at (c, r) in the result. + //! \~russian Элемент (r, c) исходного массива становится элементом (c, r) в результате. + //! \code + //! PIVector2D mat(2, 3, ...); + //! auto t = mat.transposed(); // now 3x2 + //! \endcode inline PIVector2D transposed() const { if (isEmpty()) return PIVector2D(); PIVector2D result(cols_, rows_); @@ -989,6 +1255,8 @@ public: //! \~english Reverses the order of rows in place. //! \~russian Изменяет порядок строк на обратный на месте. + //! \return Reference to this array. + //! \sa reverseColumns(), PIVector::reverse() inline PIVector2D & reverseRows() { const size_t half = rows_ / 2; for (size_t i = 0; i < half; ++i) { @@ -1003,6 +1271,8 @@ public: //! \~english Reverses the order of columns in each row in place. //! \~russian Изменяет порядок столбцов в каждой строке на обратный на месте. + //! \return Reference to this array. + //! \sa reverseRows(), PIVector::reverse() inline PIVector2D & reverseColumns() { for (size_t r = 0; r < rows_; ++r) { Row currentRow = row(r); @@ -1016,6 +1286,15 @@ public: //! \~english Returns a sub-2D array (a range of rows and columns). //! \~russian Возвращает подмассив (диапазон строк и столбцов). + //! \param rowStart Starting row index. + //! \param rowCount Number of rows to take. + //! \param colStart Starting column index. + //! \param colCount Number of columns to take. + //! \return A new 2D array containing the specified range. + //! \details + //! \~english If the range exceeds the array boundaries, it is clipped. If rowCount or colCount is 0, an empty array is returned. + //! \~russian Если диапазон выходит за границы массива, он обрезается. Если rowCount или colCount равны 0, возвращается пустой массив. + //! \sa PIVector::getRange() inline PIVector2D getRange(size_t rowStart, size_t rowCount, size_t colStart, size_t colCount) const { if (rowStart >= rows_ || colStart >= cols_ || rowCount == 0 || colCount == 0) return PIVector2D(); size_t actualRowCount = piMin(rowCount, rows_ - rowStart); @@ -1032,6 +1311,13 @@ public: //! \~english Applies a function to each element and returns a new 2D array of a different type. //! \~russian Применяет функцию к каждому элементу и возвращает новый двумерный массив другого типа. + //! \tparam ST Target element type. + //! \param f Mapping function: `ST(const T&)`. + //! \return A new \a PIVector2D with the same dimensions. + //! \details + //! \~english The original array is not modified. + //! \~russian Исходный массив не изменяется. + //! \sa PIVector::map() template inline PIVector2D map(std::function f) const { return PIVector2D(rows_, cols_, mat.template map(f)); @@ -1039,6 +1325,10 @@ public: //! \~english Applies a function (with row and col indices) to each element and returns a new 2D array. //! \~russian Применяет функцию (с индексами строки и столбца) к каждому элементу и возвращает новый двумерный массив. + //! \tparam ST Target element type. + //! \param f Function: `ST(size_t row, size_t col, const T&)`. + //! \return A new \a PIVector2D. + //! \sa PIVector::mapIndexed() template inline PIVector2D mapIndexed(std::function f) const { PIVector mappedMat; @@ -1054,6 +1344,9 @@ public: // --- Итерация по строкам и столбцам --- //! \~english Applies a function to each row (modifiable). //! \~russian Применяет функцию к каждой строке (с возможностью изменения). + //! \param f Function taking a \a Row. + //! \return Reference to this array. + //! \sa forEachRow() const, PIVector::forEach() inline PIVector2D & forEachRow(std::function f) { for (size_t r = 0; r < rows_; ++r) f(row(r)); @@ -1061,12 +1354,15 @@ public: } //! \~english Applies a function to each row (read-only). //! \~russian Применяет функцию к каждой строке (только чтение). + //! \param f Function taking a \a RowConst. inline void forEachRow(std::function f) const { for (size_t r = 0; r < rows_; ++r) f(row(r)); } //! \~english Applies a function to each column (modifiable). //! \~russian Применяет функцию к каждому столбцу (с возможностью изменения). + //! \param f Function taking a \a Col. + //! \return Reference to this array. inline PIVector2D & forEachColumn(std::function f) { for (size_t c = 0; c < cols_; ++c) f(col(c)); @@ -1074,6 +1370,7 @@ public: } //! \~english Applies a function to each column (read-only). //! \~russian Применяет функцию к каждому столбцу (только чтение). + //! \param f Function taking a \a ColConst. inline void forEachColumn(std::function f) const { for (size_t c = 0; c < cols_; ++c) f(col(c)); @@ -1081,6 +1378,11 @@ public: //! \~english Accumulates a value across all elements. //! \~russian Аккумулирует значение по всем элементам. + //! \tparam ST Accumulator type. + //! \param f Reduction function: `ST(const T&, const ST&)`. + //! \param initial Initial accumulator value. Defaults to default-constructed ST. + //! \return The accumulated result. + //! \sa PIVector::reduce() template inline ST reduce(std::function f, const ST & initial = ST()) const { return mat.template reduce(f, initial); @@ -1088,6 +1390,11 @@ public: //! \~english Accumulates a value across all elements with indices. //! \~russian Аккумулирует значение по всем элементам с индексами. + //! \tparam ST Accumulator type. + //! \param f Function: `ST(size_t row, size_t col, const T&, const ST&)`. + //! \param initial Initial accumulator value. + //! \return The accumulated result. + //! \sa PIVector::reduceIndexed() template inline ST reduceIndexed(std::function f, const ST & initial = ST()) const { ST ret(initial); @@ -1101,6 +1408,14 @@ public: //! \~english Removes a row from the 2D array. //! \~russian Удаляет строку из двумерного массива. + //! \param row Index of row to remove (must be less than rows()). + //! \return Reference to this array. + //! \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. + //! \sa removeColumn(), PIVector::remove() inline PIVector2D & removeRow(size_t row) { if (row >= rows_) return *this; size_t startIdx = row * cols_; @@ -1112,6 +1427,12 @@ public: //! \~english Removes a column from the 2D array. //! \~russian Удаляет столбец из двумерного массива. + //! \param col Index of column to remove (must be less than cols()). + //! \return Reference to this array. + //! \details + //! \~english This operation is more expensive than removing a row because elements must be moved. + //! \~russian Эта операция дороже, чем удаление строки, поскольку требуется перемещение элементов. + //! \sa removeRow(), PIVector::remove() inline PIVector2D & removeColumn(size_t col) { if (col >= cols_ || rows_ == 0) return *this; PIVector2D result(rows_, cols_ - 1); @@ -1127,6 +1448,12 @@ public: //! \~english Removes all rows that satisfy a condition. //! \~russian Удаляет все строки, удовлетворяющие условию. + //! \param test Predicate taking a \a RowConst. + //! \return Reference to this array. + //! \details + //! \~english Rows are removed from the bottom to avoid index shifting issues. + //! \~russian Строки удаляются снизу вверх, чтобы избежать проблем со смещением индексов. + //! \sa removeColumnsWhere(), PIVector::removeWhere() inline PIVector2D & removeRowsWhere(std::function test) { ssize_t r = rows_ - 1; while (r >= 0) { @@ -1140,6 +1467,9 @@ public: //! \~english Removes all columns that satisfy a condition. //! \~russian Удаляет все столбцы, удовлетворяющие условию. + //! \param test Predicate taking a \a ColConst. + //! \return Reference to this array. + //! \sa removeRowsWhere() inline PIVector2D & removeColumnsWhere(std::function test) { ssize_t c = cols_ - 1; while (c >= 0) { @@ -1154,6 +1484,9 @@ public: //! \~english Returns a new 2D array containing only the rows that pass the test. //! \~russian Возвращает новый двумерный массив, содержащий только строки, прошедшие проверку. + //! \param test Predicate taking a \a RowConst. + //! \return Filtered array. + //! \sa filterColumns(), PIVector::filter() inline PIVector2D filterRows(std::function test) const { PIVector2D result; for (size_t r = 0; r < rows_; ++r) { @@ -1167,6 +1500,9 @@ public: //! \~english Returns a new 2D array containing only the columns that pass the test. //! \~russian Возвращает новый двумерный массив, содержащий только столбцы, прошедшие проверку. + //! \param test Predicate taking a \a ColConst. + //! \return Filtered array. + //! \sa filterRows() inline PIVector2D filterColumns(std::function test) const { if (isEmpty()) return PIVector2D(); PIVector goodCols; @@ -1186,6 +1522,9 @@ public: //! \~english Returns a new 2D array (as a single row) containing only the elements that pass the test. //! \~russian Возвращает новый двумерный массив (в виде одной строки), содержащий только элементы, прошедшие проверку. + //! \param test Predicate taking a const T&. + //! \return A 1xN 2D array with the filtered elements (or empty). + //! \sa PIVector::filter() inline PIVector2D filterElements(std::function test) const { PIVector filtered = mat.filter(test); if (filtered.isEmpty()) return PIVector2D();