@@ -43,7 +43,7 @@
//! (use \a resize(), \a addRow(), \a removeRow(), \a removeColumn() instead), but you can modify the values of existing elements.
//! \~russian
//! Этот класс используется для хранения двумерного массива элементов любого типа в виде единого непрерывного блока памяти (обычного
//! PIVector). Доступ к элементам осуществляется с помощью операторов `[][]`, где первый индекс — это строка, а второй — столбец. С о
//! \a PIVector). Доступ к элементам осуществляется с помощью операторов `[][]`, где первый индекс — это строка, а второй — столбец. С о
//! строками можно работать как с объектами \a PIVector, что позволяет изменять отдельные элементы или присваивать целые строки. Нельзя
//! напрямую добавлять или удалять элементы, чтобы изменить размеры массива после создания (используйте \a resize(), \a addRow(), \a
//! removeRow(), \a removeColumn() для этого), но можно изменять значения существующих элементов.
@@ -52,21 +52,22 @@
template < typename T >
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`.
//! \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 Значение для заполнения массива.
//! \~russian Создаё т двумерный массив заданного размера, заполненный копиями `f`.
//! \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,22 +75,35 @@ public:
}
//! \~english Constructs a 2D array from an existing 1D vector, reshaping it.
//! \~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` .
//! \~russian Создаё т двумерный массив из существующего одномерного вектора, изменяя е г о форму.
//! \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, other values filled whith default cunstructor T()
//! \~russian Конструктор копирует данные из `v` во внутренний плоский вектор.
//! Если `v` больше, чем `rows * cols`, лишние элементы игнорируются (вектор обрезается).
//! Если `v` меньше, остальные значения будут заполнены из конструктора по умолчанию T()
//! \sa PIVector::PIVector(const PIVector&), reshape()
inline PIVector2D ( size_t rows , size_t cols , const PIVector < T > & v ) : rows_ ( rows ) , cols_ ( cols ) , mat ( v ) { mat . resize ( rows * cols ) ; }
//! \~english Move constructs a 2D array from an existing 1D vector, reshaping it.
//! \~russian Конструктор перемещения из существующего одномерного вектора, изменяя е г о форму.
//! \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 < T > & & 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 Создаё т двумерный массив из вектора векторов (рваного массива). Предполагается, что все внутренние векторы имеют
//! одинаковый размер.
//! \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 < PIVector < T > > & v ) {
rows_ = v . size ( ) ;
if ( rows_ ) {
@@ -103,36 +117,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 N umber of columns.
//! \~russian К оличество столбцов.
//! \~english Returns the n umber 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 T otal number of elements (`rows * cols`).
//! \~russian О бщее количество элементов (`строки * столбцы`).
//! \~english Returns the t otal 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 T otal number of elements as signed value.
//! \~russian О бщее количество элементов в виде знакового числа.
//! \~english Returns the t otal 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 T otal number of elements.
//! \~russian О бщее количество элементов.
//! \~english Returns the t otal 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 N umber of elements that the underlying container has currently allocated space for.
//! \~russian К оличество элементов, для которого сейчас выделена память во внутреннем контейнере.
//! \~english Returns the n umber 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 +185,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 < T > ;
@@ -152,28 +204,45 @@ 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 Доступ к элементу по заданному индексу столбца в строке.
//! \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 Константный доступ к элементу по заданному индексу столбца в строке.
//! \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 Возвращает указатель на данные строки, начиная с опционального смещения.
//! \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 Возвращает константный указатель на данные строки, начиная с опционального смещения.
//! \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 Присваивает этой строке содержимое другой строки.
//! \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 < size_t > ( sz_ , other . sz_ ) ;
@@ -183,6 +252,10 @@ public:
//! \~english Assigns the contents of a \a PIVector to this row.
//! \~russian Присваивает этой строке содержимое \a PIVector.
//! \details
//! \~english Only the minimum of the row size and vector size is copied.
//! \~russian Копируется только минимум из размера строки и размера вектора.
//! \sa PIVector::operator=
inline Row & operator = ( const PIVector < T > & other ) {
const size_t sz = piMin < size_t > ( sz_ , other . size ( ) ) ;
p_ - > _copyRaw ( p_ - > data ( st_ ) , other . data ( ) , sz ) ;
@@ -191,9 +264,15 @@ public:
//! \~english Converts the row to a \a PIVector.
//! \~russian Преобразует строку в \a PIVector.
//! \sa PIVector::PIVector(const T*, size_t)
inline PIVector < T > toVector ( ) const { return PIVector < T > ( p_ - > data ( st_ ) , sz_ ) ; }
// --- Поиск в строке ---
//! \~english Returns the first index of element `e` in the row, starting from `start`.
//! \~russian Возвращает первый индекс элемента `e` в строке, начиная с позиции `start`.
//! \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 +280,10 @@ public:
}
return - 1 ;
}
//! \~english Returns the last index of element `e` in the row, searching backwards from `start`.
//! \~russian Возвращает последний индекс элемента `e` в строке, выполняя поиск в обратном направлении от `start`.
//! \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 ) {
@@ -208,6 +291,10 @@ public:
}
return - 1 ;
}
//! \~english Returns the first index where the predicate `test` returns true, starting from `start`.
//! \~russian Возвращает первый индекс, для которого предикат `test` возвращает true, начиная с `start`.
//! \sa PIVector::indexWhere()
inline ssize_t indexWhere ( std : : function < bool ( const T & e ) > test , ssize_t start = 0 ) const {
if ( start < 0 ) start = 0 ;
for ( size_t i = ( size_t ) start ; i < sz_ ; + + i ) {
@@ -215,6 +302,11 @@ public:
}
return - 1 ;
}
//! \~english Returns the last index where the predicate `test` returns true, searching backwards from `start`.
//! \~russian Возвращает последний индекс, для которого предикат `test` возвращает true,
//! выполняя поиск в обратном направлении от `start`.
//! \sa PIVector::lastIndexWhere()
inline ssize_t lastIndexWhere ( std : : function < bool ( const T & e ) > 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 ) {
@@ -222,12 +314,100 @@ public:
}
return - 1 ;
}
//! \~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 < void ( T & ) > func ) {
for ( size_t i = 0 ; i < sz_ ; + + i ) {
func ( ( * p_ ) [ st_ + i ] ) ;
}
}
//! \~english Applies a function to each element of the row (read-only).
//! \~russian Применяет функцию к каждому элементу строки (только чтение).
//! \details
//! \~english The function can't modify the elements.
//! \~russian Функция не может изменять элементы.
//! \sa forEach (modifiable)
inline void forEach ( std : : function < void ( const T & ) > func ) const {
for ( size_t i = 0 ; i < sz_ ; + + i ) {
func ( ( * p_ ) [ st_ + i ] ) ;
}
}
//! \~english Fills the row with copies of `value`.
//! \~russian Заполняет строку копиями `value`.
//! \sa PIVector::fill()
inline void fill ( const T & value ) {
for ( size_t i = 0 ; i < sz_ ; + + i ) {
( * p_ ) [ st_ + i ] = value ;
}
}
//! \~english Checks if the row contains the element `e`.
//! \~russian Проверяет, содержит ли строка элемент `e`.
//! \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` в строке.
//! \sa PIVector::entries()
inline int entries ( const T & e , ssize_t start = 0 ) const {
if ( start < 0 ) start = 0 ;
int count = 0 ;
for ( size_t i = ( size_t ) start ; i < sz_ ; + + i ) {
if ( ( * p_ ) [ st_ + i ] = = e ) + + count ;
}
return count ;
}
//! \~english Counts elements in the row that pass the `test`.
//! \~russian Подсчитывает элементы в строке, проходящие `test`.
//! \sa PIVector::entries(std::function)
inline int entries ( std : : function < bool ( const T & e ) > test , ssize_t start = 0 ) const {
if ( start < 0 ) start = 0 ;
int count = 0 ;
for ( size_t i = ( size_t ) start ; i < sz_ ; + + i ) {
if ( test ( ( * p_ ) [ st_ + i ] ) ) + + count ;
}
return count ;
}
//! \~english Tests if any element in the row passes the `test`.
//! \~russian Проверяет, проходит ли какой-либо элемент в строке `test`.
//! \sa PIVector::any()
inline bool any ( std : : function < bool ( const T & e ) > test ) const {
for ( size_t i = 0 ; i < sz_ ; + + i ) {
if ( test ( ( * p_ ) [ st_ + i ] ) ) return true ;
}
return false ;
}
//! \~english Tests if all elements in the row pass the `test`.
//! \~russian Проверяет, проходят ли все элементы в строке `test`.
//! \sa PIVector::every()
inline bool every ( std : : function < bool ( const T & e ) > test ) const {
for ( size_t i = 0 ; i < sz_ ; + + i ) {
if ( ! test ( ( * p_ ) [ st_ + i ] ) ) return false ;
}
return true ;
}
} ;
//! \class Col
//! \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 < T > ;
@@ -241,12 +421,13 @@ public:
size_t step_ , col_ , sz_ ;
public :
//! \~english S ize of the column (number of rows).
//! \~russian Р азмер столбца (количество строк).
//! \~english Returns the s ize 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 Доступ к элементу по заданному индексу строки в столбце.
//! \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.
@@ -255,6 +436,11 @@ public:
//! \~english Returns a pointer to the column data starting at an optional row offset.
//! \~russian Возвращает указатель на данные столбца, начиная с опционального смещения по строкам.
//! \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.
@@ -290,7 +476,12 @@ public:
return ret ;
}
// --- Поиск в столбце ---
//! \~english Returns the first index of element `e` in the row, starting from `start`.
//! \~russian Возвращает первый индекс элемента `e` в строке, начиная с позиции `start`.
//! \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 ) {
@@ -298,6 +489,10 @@ public:
}
return - 1 ;
}
//! \~english Returns the last index of element `e` in the row, searching backwards from `start`.
//! \~russian Возвращает последний индекс элемента `e` в строке, выполняя поиск в обратном направлении от `start`.
//! \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 ) {
@@ -305,6 +500,10 @@ public:
}
return - 1 ;
}
//! \~english Returns the first index where the predicate `test` returns true, starting from `start`.
//! \~russian Возвращает первый индекс, для которого предикат `test` возвращает true, начиная с `start`.
//! \sa PIVector::indexWhere()
inline ssize_t indexWhere ( std : : function < bool ( const T & e ) > test , ssize_t start = 0 ) const {
if ( start < 0 ) start = 0 ;
for ( size_t i = ( size_t ) start ; i < sz_ ; + + i ) {
@@ -312,6 +511,11 @@ public:
}
return - 1 ;
}
//! \~english Returns the last index where the predicate `test` returns true, searching backwards from `start`.
//! \~russian Возвращает последний индекс, для которого предикат `test` возвращает true,
//! выполняя поиск в обратном направлении от `start`.
//! \sa PIVector::lastIndexWhere()
inline ssize_t lastIndexWhere ( std : : function < bool ( const T & e ) > 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 ) {
@@ -319,12 +523,98 @@ public:
}
return - 1 ;
}
//! \~english Applies a function to each element of the column (modifiable).
//! \~russian Применяет функцию к каждому элементу столбца (с возможностью изменения).
//! \details
//! \~english The function can modify the elements.
//! \~russian Функция может изменять элементы.
//! \sa PIVector::forEach()
inline void forEach ( std : : function < void ( T & ) > func ) {
for ( size_t i = 0 ; i < sz_ ; + + i ) {
func ( ( * p_ ) [ i * step_ + col_ ] ) ;
}
}
//! \~english Applies a function to each element of the column (read-only).
//! \~russian Применяет функцию к каждому элементу столбца (только чтение).
//! \details
//! \~english The function can't modify the elements.
//! \~russian Функция не может изменять элементы.
//! \sa forEach (modifiable)
inline void forEach ( std : : function < void ( const T & ) > func ) const {
for ( size_t i = 0 ; i < sz_ ; + + i ) {
func ( ( * p_ ) [ i * step_ + col_ ] ) ;
}
}
//! \~english Fills the column with copies of `value`.
//! \~russian Заполняет столбец копиями `value`.
//! \sa PIVector::fill()
inline void fill ( const T & value ) {
for ( size_t i = 0 ; i < sz_ ; + + i ) {
( * p_ ) [ i * step_ + col_ ] = value ;
}
}
//! \~english Checks if the column contains the element `e`.
//! \~russian Проверяет, содержит ли столбец элемент `e`.
//! \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 column.
//! \~russian Подсчитывает количество вхождений `e` в столбце.
//! \sa PIVector::entries()
inline int entries ( const T & e , ssize_t start = 0 ) const {
if ( start < 0 ) start = 0 ;
int count = 0 ;
for ( size_t i = ( size_t ) start ; i < sz_ ; + + i ) {
if ( ( * p_ ) [ i * step_ + col_ ] = = e ) + + count ;
}
return count ;
}
//! \~english Counts elements in the column that pass the `test`.
//! \~russian Подсчитывает элементы в столбце, проходящие `test`.
//! \sa PIVector::entries(std::function)
inline int entries ( std : : function < bool ( const T & e ) > test , ssize_t start = 0 ) const {
if ( start < 0 ) start = 0 ;
int count = 0 ;
for ( size_t i = ( size_t ) start ; i < sz_ ; + + i ) {
if ( test ( ( * p_ ) [ i * step_ + col_ ] ) ) + + count ;
}
return count ;
}
//! \~english Tests if any element in the column passes the `test`.
//! \~russian Проверяет, проходит ли какой-либо элемент в столбце `test`.
//! \sa PIVector::any()
inline bool any ( std : : function < bool ( const T & e ) > test ) const {
for ( size_t i = 0 ; i < sz_ ; + + i ) {
if ( test ( ( * p_ ) [ i * step_ + col_ ] ) ) return true ;
}
return false ;
}
//! \~english Tests if all elements in the column pass the `test`.
//! \~russian Проверяет, проходят ли все элементы в столбце `test`.
//! \sa PIVector::every()
inline bool every ( std : : function < bool ( const T & e ) > test ) const {
for ( size_t i = 0 ; i < sz_ ; + + i ) {
if ( ! test ( ( * p_ ) [ i * step_ + col_ ] ) ) return false ;
}
return true ;
}
} ;
//! \class RowConst
//! \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 < T > ;
@@ -337,6 +627,11 @@ public:
size_t st_ , sz_ ;
public :
inline RowConst ( const PIVector2D < T > : : Row & r ) : p_ ( r . p_ ) {
st_ = r . st_ ;
sz_ = r . sz_ ;
}
//! \~english Size of the row (number of columns).
//! \~russian Размер строки (количество столбцов).
inline size_t size ( ) const { return sz_ ; }
@@ -353,7 +648,12 @@ public:
//! \~russian Преобразует строку в \a PIVector.
inline PIVector < T > toVector ( ) const { return PIVector < T > ( p_ - > data ( st_ ) , sz_ ) ; }
// --- Поиск в строке (только чтение) ---
//! \~english Returns the first index of element `e` in the row, starting from `start`.
//! \~russian Возвращает первый индекс элемента `e` в строке, начиная с позиции `start`.
//! \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 ) {
@@ -361,6 +661,11 @@ public:
}
return - 1 ;
}
//! \~english Returns the last index of element `e` in the row, searching backwards from `start`.
//! \~russian Возвращает последний индекс элемента `e` в строке, выполняя поиск в обратном направлении от `start`.
//! \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 ) {
@@ -368,6 +673,10 @@ public:
}
return - 1 ;
}
//! \~english Returns the first index where the predicate `test` returns true, starting from `start`.
//! \~russian Возвращает первый индекс, для которого предикат `test` возвращает true, начиная с `start`.
//! \sa PIVector::indexWhere()
inline ssize_t indexWhere ( std : : function < bool ( const T & e ) > test , ssize_t start = 0 ) const {
if ( start < 0 ) start = 0 ;
for ( size_t i = ( size_t ) start ; i < sz_ ; + + i ) {
@@ -375,6 +684,11 @@ public:
}
return - 1 ;
}
//! \~english Returns the last index where the predicate `test` returns true, searching backwards from `start`.
//! \~russian Возвращает последний индекс, для которого предикат `test` возвращает true,
//! выполняя поиск в обратном направлении от `start`.
//! \sa PIVector::lastIndexWhere()
inline ssize_t lastIndexWhere ( std : : function < bool ( const T & e ) > 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 ) {
@@ -382,12 +696,77 @@ public:
}
return - 1 ;
}
//! \~english Applies a function to each element of the row (read-only).
//! \~russian Применяет функцию к каждому элементу строки (только чтение).
//! \details
//! \~english The function can't modify the elements.
//! \~russian Функция не может изменять элементы.
//! \sa forEach (modifiable)
inline void forEach ( std : : function < void ( const T & ) > func ) const {
for ( size_t i = 0 ; i < sz_ ; + + i ) {
func ( ( * p_ ) [ st_ + i ] ) ;
}
}
//! \~english Checks if the row contains the element `e`.
//! \~russian Проверяет, содержит ли строка элемент `e`.
//! \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` в строке.
//! \sa PIVector::entries()
inline int entries ( const T & e , ssize_t start = 0 ) const {
if ( start < 0 ) start = 0 ;
int count = 0 ;
for ( size_t i = ( size_t ) start ; i < sz_ ; + + i ) {
if ( ( * p_ ) [ st_ + i ] = = e ) + + count ;
}
return count ;
}
//! \~english Counts elements in the row that pass the `test`.
//! \~russian Подсчитывает элементы в строке, проходящие `test`.
//! \sa PIVector::entries(std::function)
inline int entries ( std : : function < bool ( const T & e ) > test , ssize_t start = 0 ) const {
if ( start < 0 ) start = 0 ;
int count = 0 ;
for ( size_t i = ( size_t ) start ; i < sz_ ; + + i ) {
if ( test ( ( * p_ ) [ st_ + i ] ) ) + + count ;
}
return count ;
}
//! \~english Tests if any element in the row passes the `test`.
//! \~russian Проверяет, проходит ли какой-либо элемент в строке `test`.
//! \sa PIVector::any()
inline bool any ( std : : function < bool ( const T & e ) > test ) const {
for ( size_t i = 0 ; i < sz_ ; + + i ) {
if ( test ( ( * p_ ) [ st_ + i ] ) ) return true ;
}
return false ;
}
//! \~english Tests if all elements in the row pass the `test`.
//! \~russian Проверяет, проходят ли все элементы в строке `test`.
//! \sa PIVector::every()
inline bool every ( std : : function < bool ( const T & e ) > test ) const {
for ( size_t i = 0 ; i < sz_ ; + + i ) {
if ( ! test ( ( * p_ ) [ st_ + i ] ) ) return false ;
}
return true ;
}
} ;
//! \class ColConst
//! \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 < T > ;
@@ -401,6 +780,12 @@ public:
size_t step_ , col_ , sz_ ;
public :
inline ColConst ( const PIVector2D < T > : : Col & c ) : p_ ( c . p_ ) {
step_ = c . step_ ;
col_ = c . col_ ;
sz_ = c . sz_ ;
}
//! \~english Size of the column (number of rows).
//! \~russian Размер столбца (количество строк).
inline size_t size ( ) const { return sz_ ; }
@@ -423,7 +808,12 @@ public:
return ret ;
}
// --- Поиск в столбце (только чтение) ---
//! \~english Returns the first index of element `e` in the row, starting from `start`.
//! \~russian Возвращает первый индекс элемента `e` в строке, начиная с позиции `start`.
//! \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 ) {
@@ -431,6 +821,10 @@ public:
}
return - 1 ;
}
//! \~english Returns the last index of element `e` in the row, searching backwards from `start`.
//! \~russian Возвращает последний индекс элемента `e` в строке, выполняя поиск в обратном направлении от `start`.
//! \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 ) {
@@ -438,6 +832,10 @@ public:
}
return - 1 ;
}
//! \~english Returns the first index where the predicate `test` returns true, starting from `start`.
//! \~russian Возвращает первый индекс, для которого предикат `test` возвращает true, начиная с `start`.
//! \sa PIVector::indexWhere()
inline ssize_t indexWhere ( std : : function < bool ( const T & e ) > test , ssize_t start = 0 ) const {
if ( start < 0 ) start = 0 ;
for ( size_t i = ( size_t ) start ; i < sz_ ; + + i ) {
@@ -445,6 +843,11 @@ public:
}
return - 1 ;
}
//! \~english Returns the last index where the predicate `test` returns true, searching backwards from `start`.
//! \~russian Возвращает последний индекс, для которого предикат `test` возвращает true,
//! выполняя поиск в обратном направлении от `start`.
//! \sa PIVector::lastIndexWhere()
inline ssize_t lastIndexWhere ( std : : function < bool ( const T & e ) > 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 ) {
@@ -452,10 +855,75 @@ public:
}
return - 1 ;
}
//! \~english Applies a function to each element of the column (read-only).
//! \~russian Применяет функцию к каждому элементу столбца (только чтение).
//! \details
//! \~english The function can't modify the elements.
//! \~russian Функция не может изменять элементы.
//! \sa forEach (modifiable)
inline void forEach ( std : : function < void ( const T & ) > func ) const {
for ( size_t i = 0 ; i < sz_ ; + + i ) {
func ( ( * p_ ) [ i * step_ + col_ ] ) ;
}
}
//! \~english Checks if the column contains the element `e`.
//! \~russian Проверяет, содержит ли столбец элемент `e`.
//! \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 column.
//! \~russian Подсчитывает количество вхождений `e` в столбце.
//! \sa PIVector::entries()
inline int entries ( const T & e , ssize_t start = 0 ) const {
if ( start < 0 ) start = 0 ;
int count = 0 ;
for ( size_t i = ( size_t ) start ; i < sz_ ; + + i ) {
if ( ( * p_ ) [ i * step_ + col_ ] = = e ) + + count ;
}
return count ;
}
//! \~english Counts elements in the column that pass the `test`.
//! \~russian Подсчитывает элементы в столбце, проходящие `test`.
//! \sa PIVector::entries(std::function)
inline int entries ( std : : function < bool ( const T & e ) > test , ssize_t start = 0 ) const {
if ( start < 0 ) start = 0 ;
int count = 0 ;
for ( size_t i = ( size_t ) start ; i < sz_ ; + + i ) {
if ( test ( ( * p_ ) [ i * step_ + col_ ] ) ) + + count ;
}
return count ;
}
//! \~english Tests if any element in the column passes the `test`.
//! \~russian Проверяет, проходит ли какой-либо элемент в столбце `test`.
//! \sa PIVector::any()
inline bool any ( std : : function < bool ( const T & e ) > test ) const {
for ( size_t i = 0 ; i < sz_ ; + + i ) {
if ( test ( ( * p_ ) [ i * step_ + col_ ] ) ) return true ;
}
return false ;
}
//! \~english Tests if all elements in the column pass the `test`.
//! \~russian Проверяет, проходят ли все элементы в столбце `test`.
//! \sa PIVector::every()
inline bool every ( std : : function < bool ( const T & e ) > test ) const {
for ( size_t i = 0 ; i < sz_ ; + + i ) {
if ( ! test ( ( * p_ ) [ i * step_ + col_ ] ) ) return false ;
}
return true ;
}
} ;
//! \~english Returns a reference to the element at the given row and column.
//! \~russian Возвращает ссылку на элемент по заданной строке и столбцу.
//! \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.
@@ -468,6 +936,7 @@ public:
//! \~english Returns a proxy object for the row at the given index for modification.
//! \~russian Возвращает прокси-объект для строки по заданному индексу для модификации.
//! \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.
@@ -476,6 +945,7 @@ public:
//! \~english Returns a pointer to the underlying flat data starting at an optional offset.
//! \~russian Возвращает указатель на внутренние плоские данные, начиная с опционального смещения.
//! \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.
@@ -485,6 +955,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.
@@ -493,21 +964,13 @@ public:
//! \~english Returns a proxy object for the column at the given index for modification.
//! \~russian Возвращает прокси-объект для столбца по заданному индексу для модификации.
//! \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.
//! \~russian Возвращает прокси-объект для столбца по заданному индексу только для чтения.
inline ColConst col ( size_t index ) const { return ColConst ( this , index ) ; }
//! \~english Replaces a row with the contents of another Row object.
//! \~russian Заменяет строку содержимым другого объекта Row.
inline PIVector2D < T > & setRow ( size_t row , const Row & other ) {
const size_t sz = piMin < size_t > ( cols_ , other . sz_ ) ;
mat . _copyRaw ( mat . data ( cols_ * row ) , other . data ( ) , sz ) ;
return * this ;
}
//! \~english Replaces a row with the contents of a read-only RowConst object.
//! \~russian Заменяет строку содержимым объекта RowConst только для чтения.
inline PIVector2D < T > & setRow ( size_t row , const RowConst & other ) {
@@ -526,18 +989,12 @@ public:
//! \~english Appends a new row to the bottom of the array from another Row object.
//! \~russian Добавляет новую строку в конец массива из другого объекта Row.
inline PIVector2D < T > & addRow ( const Row & other ) {
if ( cols_ = = 0 ) cols_ = other . sz_ ;
const size_t sz = piMin < size_t > ( cols_ , other . sz_ ) ;
const size_t ps = mat . size ( ) ;
mat . resize ( mat . size ( ) + cols_ ) ;
mat . _copyRaw ( mat . data ( ps ) , other . data ( ) , sz ) ;
rows_ + + ;
return * this ;
}
//! \~english Appends a new row to the bottom of the array from a read-only RowConst object.
//! \~russian Добавляет новую строку в конец массива из объекта RowConst только для чтения.
//! \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 < T > & addRow ( const RowConst & other ) {
if ( cols_ = = 0 ) cols_ = other . sz_ ;
const size_t sz = piMin < size_t > ( cols_ , other . sz_ ) ;
@@ -560,13 +1017,88 @@ public:
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 ) {
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 ] ;
}
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 ) ;
} else {
const T tmp = T ( ) ;
mat . _copyRaw ( & ( dst [ oldCols ] ) , & tmp , 1 ) ;
}
}
mat . _copyRaw ( mat . data ( oldCols ) , & ( other [ 0 ] ) , 1 ) ;
cols_ = newCols ;
return * this ;
}
//! \~english Appends a new column to the right of the array from a \a PIVector.
//! \~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 ] ;
}
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 ) ;
} else {
const T tmp = T ( ) ;
mat . _copyRaw ( & ( dst [ oldCols ] ) , & tmp , 1 ) ;
}
}
mat . _copyRaw ( mat . data ( oldCols ) , & ( other [ 0 ] ) , 1 ) ;
cols_ = newCols ;
return * this ;
}
//! \~english Resizes the 2D array to new dimensions.
//! \~russian Изменяет размер двумерного массива.
//! \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<int> 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 < T > & resize ( size_t rows , size_t cols , const T & f = T ( ) ) {
if ( rows = = rows_ & & cols = = cols_ ) return * this ;
PIVector2D < T > tmp ( rows , cols , f ) ;
@@ -583,6 +1115,7 @@ public:
//! \~english Equality operator.
//! \~russian Оператор равенства.
//! \sa PIVector::operator==
inline bool operator = = ( const PIVector2D < T > & t ) const {
if ( cols_ ! = t . cols_ | | rows_ ! = t . rows_ ) return false ;
return mat = = t . mat ;
@@ -594,6 +1127,10 @@ public:
//! \~english Converts the 2D array to a vector of vectors (PIVector<PIVector<T>>).
//! \~russian Преобразует двумерный массив в вектор векторов (PIVector<PIVector<T>>).
//! \details
//! \~english Each row vector is a copy of the corresponding row.
//! \~russian Каждый вектор-строка является копией соответствующей строки.
//! \sa fromVectors(), PIVector::PIVector(const T*, size_t)
inline PIVector < PIVector < T > > toVectors ( ) const {
PIVector < PIVector < T > > ret ;
ret . reserve ( rows_ ) ;
@@ -616,6 +1153,10 @@ public:
//! \~english Swaps this 2D array with another.
//! \~russian Меняет местами этот двумерный массив с другим.
//! \details
//! \~english Swaps the flat vectors and the dimension members. Very fast, no memory allocation.
//! \~russian Обменивает внутренние плоские векторы и члены, хранящие размеры. Очень быстро, без выделения памяти.
//! \sa PIVector::swap()
inline void swap ( PIVector2D < T > & other ) {
mat . swap ( other . mat ) ;
piSwap < size_t > ( rows_ , other . rows_ ) ;
@@ -633,6 +1174,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 ( ) ;
@@ -641,31 +1186,32 @@ public:
//! \~english Checks if the underlying flat vector contains the element `e`.
//! \~russian Проверяет, содержит ли внутренний плоский вектор элемент `e`.
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`.
inline bool contains ( const PIVector < T > & v , ssize_t start = 0 ) const { return mat . contains ( v , start ) ; }
//! \sa PIVector::contains()
inline bool contains ( const T & e ) const { return mat . contains ( e ) ; }
//! \~english Counts occurrences of `e` in the underlying flat vector.
//! \~russian Подсчитывает количество вхождений `e` во внутреннем плоском векторе.
inline int entries ( const T & e , ssize_t start = 0 ) const { return mat . entries ( e , start ) ; }
//! \sa PIVector::entries()
inline int entries ( const T & e ) const { return mat . entries ( e ) ; }
//! \~english Counts elements in the flat vector that pass the `test`.
//! \~russian Подсчитывает элементы в плоском векторе, проходящие `test`.
inline int entries ( std : : function < bool ( const T & e ) > test , ssize_t start = 0 ) const { return mat . entries ( test , start ) ; }
//! \sa PIVector::entries(std::function)
inline int entries ( std : : function < bool ( const T & e ) > test ) const { return mat . entries ( test ) ; }
//! \~english Returns the first index (row, col) of `e` in the 2D array.
//! \~russian Возвращает первый индекс (строка, столбец) элемента `e` в двумерном массиве.
inline PIPair < ssize_t , ssize_t > indexOf ( const T & e , ssize_t start = 0 ) const {
ssize_t flat = mat . indexOf ( e , start ) ;
//! \sa PIVector::indexOf()
inline PIPair < ssize_t , ssize_t > indexOf ( const T & e ) const {
ssize_t flat = mat . indexOf ( e ) ;
if ( flat < 0 | | cols_ = = 0 ) return PIPair < ssize_t , ssize_t > ( - 1 , - 1 ) ;
return PIPair < ssize_t , ssize_t > ( flat / cols_ , flat % cols_ ) ;
}
//! \~english Returns the first index (row, col) in the 2D array that passes the `test`.
//! \~russian Возвращает первый индекс (строка, столбец) в двумерном массиве, проходящий `test`.
//! \sa PIVector::indexWhere()
inline PIPair < ssize_t , ssize_t > indexWhere ( std : : function < bool ( const T & e ) > test , ssize_t start = 0 ) const {
ssize_t flat = mat . indexWhere ( test , start ) ;
if ( flat < 0 | | cols_ = = 0 ) return PIPair < ssize_t , ssize_t > ( - 1 , - 1 ) ;
@@ -674,6 +1220,7 @@ public:
//! \~english Returns the last index (row, col) of `e` in the 2D array.
//! \~russian Возвращает последний индекс (строка, столбец) элемента `e` в двумерном массиве.
//! \sa PIVector::lastIndexOf()
inline PIPair < ssize_t , ssize_t > lastIndexOf ( const T & e , ssize_t start = - 1 ) const {
ssize_t flat = mat . lastIndexOf ( e , start ) ;
if ( flat < 0 | | cols_ = = 0 ) return PIPair < ssize_t , ssize_t > ( - 1 , - 1 ) ;
@@ -682,6 +1229,7 @@ public:
//! \~english Returns the last index (row, col) in the 2D array that passes the `test`.
//! \~russian Возвращает последний индекс (строка, столбец) в двумерном массиве, проходящий `test`.
//! \sa PIVector::lastIndexWhere()
inline PIPair < ssize_t , ssize_t > lastIndexWhere ( std : : function < bool ( const T & e ) > test , ssize_t start = - 1 ) const {
ssize_t flat = mat . lastIndexWhere ( test , start ) ;
if ( flat < 0 | | cols_ = = 0 ) return PIPair < ssize_t , ssize_t > ( - 1 , - 1 ) ;
@@ -691,14 +1239,17 @@ public:
//! \~english Tests if any element in the flat vector passes the `test`.
//! \~russian Проверяет, проходит ли какой-либо элемент в плоском векторе `test`.
//! \sa PIVector::any()
inline bool any ( std : : function < bool ( const T & e ) > 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 < bool ( const T & e ) > test ) const { return mat . every ( test ) ; }
//! \~english Fills the entire 2D array with copies of `e`.
//! \~russian Заполняет весь двумерный массив копиями `e`.
//! \sa PIVector::fill()
inline PIVector2D < T > & fill ( const T & e = T ( ) ) {
mat . fill ( e ) ;
return * this ;
@@ -706,6 +1257,7 @@ public:
//! \~english Fills the entire 2D array using a generator function `f` based on flat index.
//! \~russian Заполняет весь двумерный массив, используя функцию-генератор `f` на основе плоского индекса.
//! \sa PIVector::fill(std::function)
inline PIVector2D < T > & fill ( std : : function < T ( size_t i ) > f ) {
mat . fill ( f ) ;
return * this ;
@@ -717,6 +1269,7 @@ public:
//! \~english Assigns new size and fills with value.
//! \~russian Задаёт новый размер и заполняет значением.
//! \sa PIVector::assign(size_t, const T&)
inline PIVector2D < T > & assign ( size_t rows , size_t cols , const T & f = T ( ) ) {
mat . assign ( rows * cols , f ) ;
rows_ = rows ;
@@ -725,9 +1278,15 @@ public:
}
// TODO: исправить - при транспонировании количество строк становится количеством столбцов и наоборот
//! \~english Returns a transposed 2D array (rows become columns and vice versa).
//! \~russian Возвращает транспонированный двумерный массив (строки становятся столбцами и наоборот).
//! \details
//! \~english The element at (r, c) in the original becomes at (c, r) in the result.
//! \~russian Элемент (r, c) исходного массива становится элементом (c, r) в результате.
//! \code
//! PIVector2D<int> mat(2, 3, ...);
//! auto t = mat.transposed(); // now 3x2
//! \endcode
inline PIVector2D < T > transposed ( ) const {
if ( isEmpty ( ) ) return PIVector2D < T > ( ) ;
PIVector2D < T > result ( cols_ , rows_ ) ;
@@ -741,6 +1300,7 @@ public:
//! \~english Reverses the order of rows in place.
//! \~russian Изменяет порядок строк на обратный на месте.
//! \sa reverseColumns(), PIVector::reverse()
inline PIVector2D < T > & reverseRows ( ) {
const size_t half = rows_ / 2 ;
for ( size_t i = 0 ; i < half ; + + i ) {
@@ -755,6 +1315,7 @@ public:
//! \~english Reverses the order of columns in each row in place.
//! \~russian Изменяет порядок столбцов в каждой строке на обратный на месте.
//! \sa reverseRows(), PIVector::reverse()
inline PIVector2D < T > & reverseColumns ( ) {
for ( size_t r = 0 ; r < rows_ ; + + r ) {
Row currentRow = row ( r ) ;
@@ -768,10 +1329,14 @@ public:
//! \~english Returns a sub-2D array (a range of rows and columns).
//! \~russian Возвращает подмассив (диапазон строк и столбцов).
//! \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 < T > 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 < T > ( ) ;
size_t actualRowCount = piMin( rowCount , rows_ - rowStart ) ;
size_t actualColCount = piMin( colCount , cols_ - colStart ) ;
size_t actualRowCount = piMin< size_t > ( rowCount , rows_ - rowStart ) ;
size_t actualColCount = piMin< size_t > ( colCount , cols_ - colStart ) ;
PIVector2D < T > result ( actualRowCount , actualColCount ) ;
for ( size_t r = 0 ; r < actualRowCount ; + + r ) {
@@ -784,6 +1349,10 @@ public:
//! \~english Applies a function to each element and returns a new 2D array of a different type.
//! \~russian Применяет функцию к каждому элементу и возвращает новый двумерный массив другого типа.
//! \details
//! \~english The original array is not modified.
//! \~russian Исходный массив не изменяется.
//! \sa PIVector::map()
template < typename ST >
inline PIVector2D < ST > map ( std : : function < ST ( const T & e ) > f ) const {
return PIVector2D < ST > ( rows_ , cols_ , mat . template map < ST > ( f ) ) ;
@@ -791,6 +1360,7 @@ public:
//! \~english Applies a function (with row and col indices) to each element and returns a new 2D array.
//! \~russian Применяет функцию (с индексами строки и столбца) к каждому элементу и возвращает новый двумерный массив.
//! \sa PIVector::mapIndexed()
template < typename ST >
inline PIVector2D < ST > mapIndexed ( std : : function < ST ( size_t row , size_t col , const T & e ) > f ) const {
PIVector < ST > mappedMat ;
@@ -803,20 +1373,22 @@ public:
return PIVector2D < ST > ( rows_ , cols_ , std : : move ( mappedMat ) ) ;
}
// --- Итерация по строкам и столбцам ---
//! \~english Applies a function to each row (modifiable).
//! \~russian Применяет функцию к каждой строке (с возможностью изменения).
//! \sa forEachRow() const, PIVector::forEach()
inline PIVector2D < T > & forEachRow ( std : : function < void ( Row ) > f ) {
for ( size_t r = 0 ; r < rows_ ; + + r )
f ( row ( r ) ) ;
return * this ;
}
//! \~english Applies a function to each row (read-only).
//! \~russian Применяет функцию к каждой строке (только чтение).
inline void forEachRow ( std : : function < void ( RowConst ) > f ) const {
for ( size_t r = 0 ; r < rows_ ; + + r )
f ( row ( r ) ) ;
}
//! \~english Applies a function to each column (modifiable).
//! \~russian Применяет функцию к каждому столбцу (с возможностью изменения).
inline PIVector2D < T > & forEachColumn ( std : : function < void ( Col ) > f ) {
@@ -824,8 +1396,10 @@ public:
f ( col ( c ) ) ;
return * this ;
}
//! \~english Applies a function to each column (read-only).
//! \~russian Применяет функцию к каждому столбцу (только чтение).
//! \param f Function taking a \a ColConst.
inline void forEachColumn ( std : : function < void ( ColConst ) > f ) const {
for ( size_t c = 0 ; c < cols_ ; + + c )
f ( col ( c ) ) ;
@@ -833,6 +1407,7 @@ public:
//! \~english Accumulates a value across all elements.
//! \~russian Аккумулирует значение по всем элементам.
//! \sa PIVector::reduce()
template < typename ST >
inline ST reduce ( std : : function < ST ( const T & e , const ST & acc ) > f , const ST & initial = ST ( ) ) const {
return mat . template reduce < ST > ( f , initial ) ;
@@ -840,6 +1415,7 @@ public:
//! \~english Accumulates a value across all elements with indices.
//! \~russian Аккумулирует значение по всем элементам с индексами.
//! \sa PIVector::reduceIndexed()
template < typename ST >
inline ST reduceIndexed ( std : : function < ST ( size_t row , size_t col , const T & e , const ST & acc ) > f , const ST & initial = ST ( ) ) const {
ST ret ( initial ) ;
@@ -853,10 +1429,15 @@ 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.
//! \sa removeColumn(), PIVector::remove()
inline PIVector2D < T > & removeRow ( size_t row ) {
if ( row > = rows_ ) return * this ;
size_t startIdx = row * cols_ ;
mat . remove ( startIdx , cols_ ) ;
mat . remove ( row * cols_ , cols_ ) ;
rows_ - - ;
if ( rows_ = = 0 ) cols_ = 0 ;
return * this ;
@@ -864,6 +1445,10 @@ public:
//! \~english Removes a column from the 2D array.
//! \~russian Удаляет столбец из двумерного массива.
//! \details
//! \~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 ) {
if ( col > = cols_ | | rows_ = = 0 ) return * this ;
PIVector2D < T > result ( rows_ , cols_ - 1 ) ;
@@ -879,26 +1464,29 @@ public:
//! \~english Removes all rows that satisfy a condition.
//! \~russian Удаляет все строки, удовлетворяющие условию.
//! \details
//! \~english Rows are removed from the bottom to avoid index shifting issues.
//! \~russian Строки удаляются снизу вверх, чтобы избежать проблем с о смещением индексов.
//! \sa removeColumnsWhere(), PIVector::removeWhere()
inline PIVector2D < T > & removeRowsWhere ( std : : function < bool ( const RowConst & ) > test ) {
ssize_t r = rows_ - 1 ;
while ( r > = 0 ) {
ssize_t r = rows_ ;
while ( - - r > = 0 ) {
if ( test ( RowConst ( this , r ) ) ) {
removeRow ( r ) ;
}
- - r ;
}
return * this ;
}
//! \~english Removes all columns that satisfy a condition.
//! \~russian Удаляет все столбцы, удовлетворяющие условию.
//! \sa removeRowsWhere()
inline PIVector2D < T > & removeColumnsWhere ( std : : function < bool ( const ColConst & ) > test ) {
ssize_t c = cols_ - 1 ;
while ( c > = 0 ) {
ssize_t c = cols_ ;
while ( - - c > = 0 ) {
if ( test ( ColConst ( this , c ) ) ) {
removeColumn ( c ) ;
}
- - c ;
}
return * this ;
}
@@ -906,6 +1494,7 @@ public:
//! \~english Returns a new 2D array containing only the rows that pass the test.
//! \~russian Возвращает новый двумерный массив, содержащий только строки, прошедшие проверку.
//! \sa filterColumns(), PIVector::filter()
inline PIVector2D < T > filterRows ( std : : function < bool ( const RowConst & ) > test ) const {
PIVector2D < T > result ;
for ( size_t r = 0 ; r < rows_ ; + + r ) {
@@ -919,6 +1508,7 @@ public:
//! \~english Returns a new 2D array containing only the columns that pass the test.
//! \~russian Возвращает новый двумерный массив, содержащий только столбцы, прошедшие проверку.
//! \sa filterRows()
inline PIVector2D < T > filterColumns ( std : : function < bool ( const ColConst & ) > test ) const {
if ( isEmpty ( ) ) return PIVector2D < T > ( ) ;
PIVector < size_t > goodCols ;
@@ -936,14 +1526,6 @@ public:
return result ;
}
//! \~english Returns a new 2D array (as a single row) containing only the elements that pass the test.
//! \~russian Возвращает новый двумерный массив (в виде одной строки), содержащий только элементы, прошедшие проверку.
inline PIVector2D < T > filterElements ( std : : function < bool ( const T & ) > test ) const {
PIVector < T > filtered = mat . filter ( test ) ;
if ( filtered . isEmpty ( ) ) return PIVector2D < T > ( ) ;
return PIVector2D < T > ( 1 , filtered . size ( ) , filtered ) ;
}
protected :
size_t rows_ , cols_ ;
PIVector < T > mat ;