i and ai refactor pivector2d

This commit is contained in:
2026-02-27 00:07:00 +03:00
parent 6557933a2e
commit 42a1507536
6 changed files with 202 additions and 378 deletions

View File

@@ -19,13 +19,13 @@ PIP is a C++ cross-platform library providing platform-independent abstractions
### Basic Build
```bash
cmake -B build
cmake --build build
cmake --build build -j8
```
### Build with Tests
```bash
cmake -B build -DTESTS=ON
cmake --build build
cmake --build build -j8
```
### Run Tests

70
dependencies.md Normal file
View File

@@ -0,0 +1,70 @@
# PIP Dependencies
## Встроенные (included in 3rd/)
| Библиотека | Назначение | Модуль PIP |
|------------|------------|------------|
| **PCRE2** | Регулярные выражения | main (internal) |
| **BLAKE2** | Хеширование | main (internal) |
| **SipHash** | Хеширование | main (internal) |
| **Lua** | Lua scripting | lua |
| **LuaBridge** | Lua bindings | lua |
## Внешние (системные)
| Библиотека | Опция | Модуль PIP |
|------------|-------|------------|
| **ICU** | `-DICU=ON` | main (string conversion) |
| **zlib** | `PIP_BUILD_COMPRESS` | compress |
| **libsodium** | `PIP_BUILD_CRYPT` | crypt, io_utils, cloud |
| **libusb** | `PIP_BUILD_USB` | usb |
| **FFTW3** (+ threads) | `PIP_BUILD_FFTW` | fftw |
| **OpenCL** | `PIP_BUILD_OPENCL` | opencl |
| **libmicrohttpd** | `PIP_BUILD_HTTP_SERVER` | http_server |
| **libcurl** | `PIP_BUILD_HTTP_CLIENT` | http_client |
| **gnutls** | (optional, для http_server) | http_server |
| **pthread** | (system) | main |
| **libdl** | (system) | main |
| **librt** | (system, не Apple/Android) | main |
| **libutil** | (system) | main |
| **libsocket** | (QNX) | main |
| **ws2_32, iphlpapi, psapi, cfgmgr32, setupapi, hid** | (Windows) | main |
## Опциональные (тесты/документация)
| Инструмент | Назначение |
|------------|------------|
| **Google Test** | Тестирование (fetched automatically) |
| **Doxygen** | Генерация документации |
## Стандартные системные библиотеки
- libm (math)
- libc (C standard)
## Схема зависимостей модулей
```
main (core)
├── PCRE2 (встроен)
├── BLAKE2 (встроен)
├── SipHash (встроен)
├── pthread (система)
├── libdl (система)
├── librt (система)
├── libutil (система)
└── ICU (опционально)
console → main
compress → zlib
crypt → libsodium
usb → libusb
fftw → FFTW3
opencl → OpenCL
io_utils → [crypt, если доступен]
client_server → io_utils
cloud → io_utils, crypt
lua → Lua (встроен), LuaBridge (встроен)
http_server → libmicrohttpd, [gnutls]
http_client → libcurl
```

View File

@@ -52,6 +52,14 @@
template<typename T>
class PIVector2D {
public:
//! \brief
//! \~english Index structure for 2D array elements (row, column).
//! \~russian Структура индекса для элементов двумерного массива (строка, столбец).
struct Index {
ssize_t row;
ssize_t col;
};
//! \~english Constructs an empty 2D array. No memory is allocated.
//! \~russian Создаёт пустой двумерный массив. Память не выделяется.
//! \details
@@ -198,18 +206,12 @@ public:
friend class PIVector2D<T>;
protected:
inline RowConst(const PIVector2D<T> * p, size_t row): p_(&(p->mat)) {
st_ = p->cols_ * row;
sz_ = p->cols_;
}
inline RowConst(const PIVector2D<T> * p, size_t row): p_(&(p->mat)), st_(p->cols_ * row), sz_(p->cols_) {}
const PIVector<T> * p_;
size_t st_, sz_;
const size_t st_, sz_;
public:
inline RowConst(const PIVector2D<T>::Row & r): p_(r.p_) {
st_ = r.st_;
sz_ = r.sz_;
}
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 Размер строки (количество столбцов).
@@ -351,20 +353,12 @@ public:
friend class PIVector2D<T>;
protected:
inline ColConst(const PIVector2D<T> * p, size_t col): p_(&(p->mat)) {
step_ = p->cols_;
col_ = col;
sz_ = p->rows_;
}
inline ColConst(const PIVector2D<T> * p, size_t col): p_(&(p->mat)), step_(p->cols_), col_(col), sz_(p->rows_) {}
const PIVector<T> * p_;
size_t step_, col_, sz_;
const 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_;
}
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 Размер столбца (количество строк).
@@ -509,23 +503,17 @@ public:
//! \~russian Объекты этого класса возвращаются неконстантными операторами \a operator[] или методом \a row().
//! Они предоставляют доступ к элементам конкретной строки, подобный массиву, и позволяют выполнять такие операции, как присваивание из
//! другой строки или \a PIVector, поиск, заполнение и итерацию. \sa Col, RowConst
class Row {
class Row: public RowConst {
friend class PIVector2D<T>;
private:
inline Row(PIVector2D<T> * p, size_t row): p_(&(p->mat)) {
st_ = p->cols_ * row;
sz_ = p->cols_;
}
inline Row(PIVector2D<T> * p, size_t row): RowConst(p, row), p_(&(p->mat)) {}
PIVector<T> * p_;
size_t st_, sz_;
public:
//! \~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_; }
using RowConst::operator[];
using RowConst::data;
using RowConst::size;
//! \~english Accesses the element at the given column index within the row.
//! \~russian Доступ к элементу по заданному индексу столбца в строке.
@@ -533,12 +521,7 @@ public:
//! \~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]; }
inline T & operator[](size_t index) { return (*p_)[this->st_ + index]; }
//! \~english Returns a pointer to the row data starting at an optional offset.
//! \~russian Возвращает указатель на данные строки, начиная с опционального смещения.
@@ -547,12 +530,7 @@ public:
//! 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); }
inline T * data(size_t index = 0) { return p_->data(this->st_ + index); }
//! \~english Assigns the contents of another Row to this row.
//! \~russian Присваивает этой строке содержимое другой строки.
@@ -561,9 +539,9 @@ public:
//! \~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_);
p_->_copyRaw(p_->data(st_), other.data(), sz);
if (p_ == other.p_ && this->st_ == other.st_) return *this;
const size_t sz = piMin<size_t>(this->sz_, other.sz_);
p_->_copyRaw(p_->data(this->st_), other.data(), sz);
return *this;
}
@@ -574,64 +552,11 @@ public:
//! \~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);
const size_t sz = piMin<size_t>(this->sz_, other.size());
p_->_copyRaw(p_->data(this->st_), other.data(), sz);
return *this;
}
//! \~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) {
if ((*p_)[st_ + i] == e) return (ssize_t)i;
}
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) {
if ((*p_)[st_ + i] == e) return i;
}
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) {
if (test((*p_)[st_ + i])) return (ssize_t)i;
}
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) {
if (test((*p_)[st_ + i])) return i;
}
return -1;
}
//! \~english Applies a function to each element of the row (modifiable).
//! \~russian Применяет функцию к каждому элементу строки (с возможностью изменения).
//! \param func Function that takes a reference to T.
@@ -640,20 +565,8 @@ public:
//! \~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]);
for (size_t i = 0; i < this->sz_; ++i) {
func((*p_)[this->st_ + i]);
}
}
@@ -661,59 +574,10 @@ public:
//! \~russian Заполняет строку копиями `value`.
//! \sa PIVector::fill()
inline void fill(const T & value) {
for (size_t i = 0; i < sz_; ++i) {
(*p_)[st_ + i] = value;
for (size_t i = 0; i < this->sz_; ++i) {
(*p_)[this->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;
}
};
@@ -726,31 +590,18 @@ public:
//! Row.
//! \~russian Объекты этого класса возвращаются неконстантным методом \a col(). Они предоставляют доступ к столбцам и операции,
//! аналогичные \a Row. \sa Row, ColConst
class Col {
class Col: public ColConst {
friend class PIVector2D<T>;
private:
inline Col(PIVector2D<T> * p, size_t col): p_(&(p->mat)) {
step_ = p->cols_;
col_ = col;
sz_ = p->rows_;
}
inline Col(PIVector2D<T> * p, size_t col): ColConst(p, col), p_(&(p->mat)) {}
PIVector<T> * p_;
size_t step_, col_, sz_;
public:
//! \~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 Доступ к элементу по заданному индексу строки в столбце.
//! \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.
//! \~russian Константный доступ к элементу по заданному индексу строки в столбце.
inline const T & operator[](size_t index) const { return (*p_)[index * step_ + col_]; }
inline T & operator[](size_t index) { return (*p_)[index * this->step_ + this->col_]; }
//! \~english Returns a pointer to the column data starting at an optional row offset.
//! \~russian Возвращает указатель на данные столбца, начиная с опционального смещения по строкам.
@@ -759,89 +610,27 @@ public:
//! 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.
//! \~russian Возвращает константный указатель на данные столбца, начиная с опционального смещения по строкам.
inline const T * data(size_t index = 0) const { return p_->data(index * step_ + col_); }
inline T * data(size_t index = 0) { return p_->data(index * this->step_ + this->col_); }
//! \~english Assigns the contents of another Col to this column.
//! \~russian Присваивает этому столбцу содержимое другого столбца.
inline Col & operator=(const Col & other) {
if (p_ == other.p_ && col_ == other.col_) return *this;
const size_t sz = piMin<size_t>(sz_, other.sz_);
if (p_ == other.p_ && this->col_ == other.col_) return *this;
const size_t sz = piMin<size_t>(this->sz_, other.sz_);
for (size_t i = 0; i < sz; ++i)
(*p_)[i * step_ + col_] = other[i];
(*p_)[i * this->step_ + this->col_] = other.ColConst::operator[](i);
return *this;
}
//! \~english Assigns the contents of a \a PIVector to this column.
//! \~russian Присваивает этому столбцу содержимое \a PIVector.
inline Col & operator=(const PIVector<T> & other) {
const size_t sz = piMin<size_t>(sz_, other.size());
const size_t sz = piMin<size_t>(this->sz_, other.size());
for (size_t i = 0; i < sz; ++i)
(*p_)[i * step_ + col_] = other[i];
(*p_)[i * this->step_ + this->col_] = other[i];
return *this;
}
//! \~english Converts the column to a \a PIVector.
//! \~russian Преобразует столбец в \a PIVector.
inline PIVector<T> toVector() const {
PIVector<T> ret;
ret.reserve(sz_);
for (size_t i = 0; i < sz_; i++)
ret << (*p_)[i * step_ + col_];
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) {
if ((*p_)[i * step_ + col_] == e) return (ssize_t)i;
}
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) {
if ((*p_)[i * step_ + col_] == e) return i;
}
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) {
if (test((*p_)[i * step_ + col_])) return (ssize_t)i;
}
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) {
if (test((*p_)[i * step_ + col_])) return i;
}
return -1;
}
//! \~english Applies a function to each element of the column (modifiable).
//! \~russian Применяет функцию к каждому элементу столбца (с возможностью изменения).
//! \details
@@ -849,20 +638,8 @@ public:
//! \~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_]);
for (size_t i = 0; i < this->sz_; ++i) {
func((*p_)[i * this->step_ + this->col_]);
}
}
@@ -870,59 +647,10 @@ public:
//! \~russian Заполняет столбец копиями `value`.
//! \sa PIVector::fill()
inline void fill(const T & value) {
for (size_t i = 0; i < sz_; ++i) {
(*p_)[i * step_ + col_] = value;
for (size_t i = 0; i < this->sz_; ++i) {
(*p_)[i * this->step_ + this->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;
}
};
@@ -1211,37 +939,37 @@ public:
//! \~english Returns the first index (row, col) of `e` in the 2D array.
//! \~russian Возвращает первый индекс (строка, столбец) элемента `e` в двумерном массиве.
//! \sa PIVector::indexOf()
inline PIPair<ssize_t, ssize_t> indexOf(const T & e) const {
inline Index 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_);
if (flat < 0 || cols_ == 0) return Index{-1, -1};
return Index{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 {
inline Index 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);
return PIPair<ssize_t, ssize_t>(flat / cols_, flat % cols_);
if (flat < 0 || cols_ == 0) return Index{-1, -1};
return Index{flat / cols_, flat % cols_};
}
//! \~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 {
inline Index 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);
return PIPair<ssize_t, ssize_t>(flat / cols_, flat % cols_);
if (flat < 0 || cols_ == 0) return Index{-1, -1};
return Index{flat / cols_, flat % cols_};
}
//! \~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 {
inline Index 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);
return PIPair<ssize_t, ssize_t>(flat / cols_, flat % cols_);
if (flat < 0 || cols_ == 0) return Index{-1, -1};
return Index{flat / cols_, flat % cols_};
}

59
options.md Normal file
View File

@@ -0,0 +1,59 @@
# PIP Build Options
## Основные опции сборки
### Стандартные опции (option())
| Опция | Описание | По умолчанию |
|-------|----------|--------------|
| `ICU` | ICU support для конвертации кодовых страниц | ON (кроме Win/Android/Apple) |
| `STD_IOSTREAM` | Поддержка std::iostream операторов | OFF |
| `INTROSPECTION` | Сборка с интроспекцией | OFF |
| `TESTS` | Сборка тестов | OFF |
| `COVERAGE` | Сборка с информацией о покрытии | OFF |
| `PIP_FFTW_F` | Поддержка FFTW для float | ON |
| `PIP_FFTW_L` | Поддержка FFTW для long double | ON |
| `PIP_FFTW_Q` | Поддержка FFTW для quad double | OFF |
### Опции модулей (PIP_BUILD_*)
| Опция | Модуль |
|-------|--------|
| `PIP_BUILD_CONSOLE` | console |
| `PIP_BUILD_CRYPT` | crypt (требует libsodium) |
| `PIP_BUILD_COMPRESS` | compress (требует zlib) |
| `PIP_BUILD_USB` | usb |
| `PIP_BUILD_FFTW` | fftw |
| `PIP_BUILD_OPENCL` | opencl |
| `PIP_BUILD_IO_UTILS` | io_utils |
| `PIP_BUILD_CLIENT_SERVER` | client_server |
| `PIP_BUILD_CLOUD` | cloud |
| `PIP_BUILD_LUA` | lua |
| `PIP_BUILD_HTTP_CLIENT` | http_client (требует libcurl) |
| `PIP_BUILD_HTTP_SERVER` | http_server (требует libmicrohttpd) |
### Дополнительные переменные
| Переменная | Описание |
|------------|----------|
| `PIP_BUILD_DEBUG` | Сборка debug версии |
| `PIP_FREERTOS` | Поддержка FreeRTOS |
| `CROSSTOOLS` | Режим кросс-компиляции |
| `LOCAL` | Локальная установка (bin/lib/include) |
| `PIP_CONTAINERS_MIN_ALLOC` | Переопределить минимальный размер аллокации контейнеров |
| `PIP_CONTAINERS_MAX_POT_ALLOC` | Переопределить максимальный размер (поддерживает X_KiB, X_MiB) |
### Примеры использования
```bash
# Базовая сборка с тестами
cmake -B build -DTESTS=ON
# Сборка с покрытием и ICU
cmake -B build -DTESTS=ON -DCOVERAGE=ON -DICU=ON
# Отключение отдельных модулей
cmake -B build -DPIP_BUILD_CRYPT=OFF -DPIP_BUILD_OPENCL=OFF
# Переопределение параметров контейнеров
cmake -B build -DPIP_CONTAINERS_MIN_ALLOC=64
# Локальная установка
cmake -B build -DLOCAL=ON
```

View File

@@ -1,48 +1,15 @@
# План рефакторинга PIVector2D
## Этап 1: Выполнить наследование Row от RowConst, Col от ColConst
## Этап 1: Сборка
### 1.1 Найти классы Col, Row, ColConst и RowConst
- они находятся в файле `libs/main/containers/pivector2d.h`
### 1.2 Изменить класс Row
- Наследовать от RowConst: `class Row : public RowConst`
- Убрать дублирующиеся методы (они унаследованы от RowConst):
- size()
- toVector()
- operator[] (const версия)
- data() (const версия)
- indexOf()
- lastIndexOf()
- indexWhere()
- lastIndexWhere()
- forEach() (const версия)
- contains()
- entries()
- any()
- every()
- Сохранить неконстантные методы:
- operator[] (неконстантный)
- data() (неконстантный)
- operator=()
- forEach() (неконстантный)
- fill()
### 1.3 Изменить класс Col
- Наследовать от ColConst: `class Col : public ColConst`
- Аналогично убрать дублирующиеся методы
### 1.4 Собрать проект
### 1.1 Собрать проект
- собери проект, при необходимости поправь ошибки
- тесты не трогай
## Этап 2: Проверить и поправить тесты
### 2.1 Запустить тесты
- Запустить: `./build/tests/pip_math_test --gtest_filter="*Vector2D*"`
### 2.2 Поправить код или тесты
- внести правки в pivector2d.h
- В случае ошибок внести правки в pivector2d.h
---
@@ -50,7 +17,7 @@
### 3.1 Создать структуру PIVector2DIndex
```cpp
struct PIVector2DIndex {
struct Index {
ssize_t row;
ssize_t col;
};

View File

@@ -952,38 +952,38 @@ TEST_F(Vector2DTest, forEach_modifying_changes_elements) {
TEST_F(Vector2DTest, indexOf_returns_correct_pair) {
auto p = vec.indexOf(vec.element(10, 15));
EXPECT_EQ(p.first, 10);
EXPECT_EQ(p.second, 15);
EXPECT_EQ(p.row, 10);
EXPECT_EQ(p.col, 15);
p = vec.indexOf(-999);
EXPECT_EQ(p.first, -1);
EXPECT_EQ(p.second, -1);
EXPECT_EQ(p.row, -1);
EXPECT_EQ(p.col, -1);
}
TEST_F(Vector2DTest, indexWhere_returns_correct_pair) {
vec.element(5, 5) = -42;
auto isTarget = [](const int & e) { return e == -42; };
auto p = vec.indexWhere(isTarget);
EXPECT_EQ(p.first, 5);
EXPECT_EQ(p.second, 5);
EXPECT_EQ(p.row, 5);
EXPECT_EQ(p.col, 5);
}
TEST_F(Vector2DTest, lastIndexOf_works) {
int val = vec.element(10, 10);
vec.element(20, 20) = val; // duplicate
auto p = vec.lastIndexOf(val);
EXPECT_EQ(p.first, 20);
EXPECT_EQ(p.second, 20);
EXPECT_EQ(p.row, 20);
EXPECT_EQ(p.col, 20);
}
TEST_F(Vector2DTest, lastIndexWhere_works) {
auto isLarge = [](const int & e) { return e > 500; };
auto p = vec.lastIndexWhere(isLarge);
EXPECT_GE(p.first, 0);
EXPECT_GE(p.second, 0);
EXPECT_GE(p.row, 0);
EXPECT_GE(p.col, 0);
// The last element with value >500 should be the largest index
size_t lastFlat = p.first * vec.cols() + p.second;
size_t lastFlat = p.row * vec.cols() + p.col;
size_t expectedLastFlat = vec.size() - 1;
EXPECT_EQ(lastFlat, expectedLastFlat);
EXPECT_EQ(lastFlat, expectedLastFlat);
}
TEST_F(Vector2DTest, reduce_accumulates_correctly) {