From 42a1507536682986e721e2249e74a0b35f1150c9 Mon Sep 17 00:00:00 2001 From: "andrey.bychkov" Date: Fri, 27 Feb 2026 00:07:00 +0300 Subject: [PATCH] i and ai refactor pivector2d --- AGENTS.md | 4 +- dependencies.md | 70 ++++++ libs/main/containers/pivector2d.h | 382 +++++------------------------- options.md | 59 +++++ plans/pivector2d.md | 41 +--- tests/math/testpivector2d.cpp | 24 +- 6 files changed, 202 insertions(+), 378 deletions(-) create mode 100644 dependencies.md create mode 100644 options.md diff --git a/AGENTS.md b/AGENTS.md index 8a65e260..270ffd38 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -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 diff --git a/dependencies.md b/dependencies.md new file mode 100644 index 00000000..d0bfcadc --- /dev/null +++ b/dependencies.md @@ -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 +``` diff --git a/libs/main/containers/pivector2d.h b/libs/main/containers/pivector2d.h index 72199c03..e1006d46 100644 --- a/libs/main/containers/pivector2d.h +++ b/libs/main/containers/pivector2d.h @@ -52,6 +52,14 @@ template 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; protected: - inline RowConst(const PIVector2D * p, size_t row): p_(&(p->mat)) { - st_ = p->cols_ * row; - sz_ = p->cols_; - } + inline RowConst(const PIVector2D * p, size_t row): p_(&(p->mat)), st_(p->cols_ * row), sz_(p->cols_) {} const PIVector * p_; - size_t st_, sz_; + const size_t st_, sz_; public: - inline RowConst(const PIVector2D::Row & r): p_(r.p_) { - st_ = r.st_; - sz_ = r.sz_; - } + inline RowConst(const PIVector2D::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; protected: - inline ColConst(const PIVector2D * p, size_t col): p_(&(p->mat)) { - step_ = p->cols_; - col_ = col; - sz_ = p->rows_; - } + inline ColConst(const PIVector2D * p, size_t col): p_(&(p->mat)), step_(p->cols_), col_(col), sz_(p->rows_) {} const PIVector * p_; - size_t step_, col_, sz_; + const size_t step_, col_, sz_; public: - inline ColConst(const PIVector2D::Col & c): p_(c.p_) { - step_ = c.step_; - col_ = c.col_; - sz_ = c.sz_; - } + inline ColConst(const PIVector2D::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; private: - inline Row(PIVector2D * p, size_t row): p_(&(p->mat)) { - st_ = p->cols_ * row; - sz_ = p->cols_; - } + inline Row(PIVector2D * p, size_t row): RowConst(p, row), p_(&(p->mat)) {} PIVector * 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(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(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 & other) { - const size_t sz = piMin(sz_, other.size()); - p_->_copyRaw(p_->data(st_), other.data(), sz); + const size_t sz = piMin(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 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`. - //! \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 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 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 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 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 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 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 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; private: - inline Col(PIVector2D * p, size_t col): p_(&(p->mat)) { - step_ = p->cols_; - col_ = col; - sz_ = p->rows_; - } + inline Col(PIVector2D * p, size_t col): ColConst(p, col), p_(&(p->mat)) {} PIVector * 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(sz_, other.sz_); + if (p_ == other.p_ && this->col_ == other.col_) return *this; + const size_t sz = piMin(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 & other) { - const size_t sz = piMin(sz_, other.size()); + const size_t sz = piMin(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 toVector() const { - PIVector 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 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 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 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 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 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 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 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 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(-1, -1); - return PIPair(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 indexWhere(std::function test, ssize_t start = 0) const { + inline Index 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); - return PIPair(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 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(-1, -1); - return PIPair(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 lastIndexWhere(std::function test, ssize_t start = -1) const { + inline Index 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); - return PIPair(flat / cols_, flat % cols_); + if (flat < 0 || cols_ == 0) return Index{-1, -1}; + return Index{flat / cols_, flat % cols_}; } diff --git a/options.md b/options.md new file mode 100644 index 00000000..ecc938d1 --- /dev/null +++ b/options.md @@ -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 +``` diff --git a/plans/pivector2d.md b/plans/pivector2d.md index 8d869c4c..c59c0cf5 100644 --- a/plans/pivector2d.md +++ b/plans/pivector2d.md @@ -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; }; diff --git a/tests/math/testpivector2d.cpp b/tests/math/testpivector2d.cpp index 3aaf7ae4..e0f626ae 100644 --- a/tests/math/testpivector2d.cpp +++ b/tests/math/testpivector2d.cpp @@ -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) {