From d22af96bea3277a19d237ebec9f43bdf866364fe Mon Sep 17 00:00:00 2001 From: Andrey Date: Thu, 14 Apr 2022 18:00:33 +0300 Subject: [PATCH] PIDeque optimization --- libs/main/containers/pideque.h | 51 +++++++++++++++++---------------- libs/main/containers/pivector.h | 16 +++++++++++ 2 files changed, 43 insertions(+), 24 deletions(-) diff --git a/libs/main/containers/pideque.h b/libs/main/containers/pideque.h index 00db86f9..9220fdaf 100644 --- a/libs/main/containers/pideque.h +++ b/libs/main/containers/pideque.h @@ -38,17 +38,17 @@ public: } inline PIDeque(const PIDeque & other): pid_data(0), pid_size(0), pid_rsize(0), pid_start(0) { PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T)) - alloc(other.pid_size, true); + alloc_forward(other.pid_size); newT(pid_data + pid_start, other.pid_data + other.pid_start, pid_size); } inline PIDeque(std::initializer_list init_list): pid_data(0), pid_size(0), pid_rsize(0), pid_start(0) { PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T)) - alloc(init_list.size(), true); + alloc_forward(init_list.size()); newT(pid_data, init_list.begin(), init_list.size()); } inline PIDeque(const T * data, size_t size): pid_data(0), pid_size(0), pid_rsize(0), pid_start(0) { PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T)) - alloc(size, true); + alloc_forward(size); newT(pid_data + pid_start, data, pid_size); } inline PIDeque(size_t pid_size, const T & f = T()): pid_data(0), pid_size(0), pid_rsize(0), pid_start(0) { @@ -74,7 +74,7 @@ public: inline PIDeque & operator =(const PIDeque & other) { if (this == &other) return *this; deleteT(pid_data + pid_start, pid_size); - alloc(other.pid_size, true); + alloc_forward(other.pid_size); newT(pid_data + pid_start, other.pid_data + other.pid_start, pid_size); return *this; } @@ -458,7 +458,7 @@ public: } if (new_size > pid_size) { size_t os = pid_size; - alloc(new_size, true); + alloc_forward(new_size); PIINTROSPECTION_CONTAINER_USED(T, (new_size-os)) for (size_t i = os + pid_start; i < new_size + pid_start; ++i) { elementNew(pid_data + i, f); @@ -476,7 +476,7 @@ public: } if (new_size > pid_size) { size_t os = pid_size; - alloc(new_size, true); + alloc_forward(new_size); PIINTROSPECTION_CONTAINER_USED(T, (new_size-os)) for (size_t i = os + pid_start; i < new_size + pid_start; ++i) { elementNew(pid_data + i, f(i)); @@ -495,14 +495,14 @@ public: if (new_size < pid_size) { PIINTROSPECTION_CONTAINER_UNUSED(T, (pid_size-new_size)); } - alloc(new_size, true); + alloc_forward(new_size); return *this; } inline PIDeque & reserve(size_t new_size) { if (new_size <= pid_rsize) return *this; size_t os = pid_size; - alloc(new_size, true); + alloc_forward(new_size); pid_size = os; return *this; } @@ -512,13 +512,13 @@ public: PIINTROSPECTION_CONTAINER_USED(T, 1) bool dir = pid_rsize <= 2 ? true : (index >= pid_rsize / 2 ? true : false); if (dir) { - alloc(pid_size + 1, true); + alloc_forward(pid_size + 1); if (index < pid_size - 1) { size_t os = pid_size - index - 1; memmove((void*)(&(pid_data[index + pid_start + 1])), (const void*)(&(pid_data[index + pid_start])), os * sizeof(T)); } } else { - alloc(pid_size + 1, false, -1); + alloc_backward(pid_size + 1, -1); if (index > 0) { memmove((void*)(&(pid_data[pid_start])), (const void*)(&(pid_data[pid_start + 1])), index * sizeof(T)); } @@ -531,13 +531,13 @@ public: PIINTROSPECTION_CONTAINER_USED(T, 1) bool dir = pid_rsize <= 2 ? true : (index >= pid_rsize / 2 ? true : false); if (dir) { - alloc(pid_size + 1, true); + alloc_forward(pid_size + 1); if (index < pid_size - 1) { size_t os = pid_size - index - 1; memmove((void*)(&(pid_data[index + pid_start + 1])), (const void*)(&(pid_data[index + pid_start])), os * sizeof(T)); } } else { - alloc(pid_size + 1, false, -1); + alloc_backward(pid_size + 1, -1); if (index > 0) { memmove((void*)(&(pid_data[pid_start])), (const void*)(&(pid_data[pid_start + 1])), index * sizeof(T)); } @@ -556,12 +556,12 @@ public: bool dir = pid_rsize <= 2 ? true : (index >= pid_rsize / 2 ? true : false); if (dir) { ssize_t os = pid_size - index; - alloc(pid_size + other.pid_size, true); + alloc_forward(pid_size + other.pid_size); if (os > 0) { memmove((void*)(&(pid_data[index + pid_start + other.pid_size])), (const void*)(&(pid_data[index + pid_start])), os * sizeof(T)); } } else { - alloc(pid_size + other.pid_size, false, -other.pid_size); + alloc_backward(pid_size + other.pid_size, -other.pid_size); if (index > 0) { memmove((void*)(&(pid_data[pid_start])), (const void*)(&(pid_data[pid_start + other.pid_size])), index * sizeof(T)); } @@ -634,6 +634,8 @@ public: //! bool comp(const T &a, const T &b); //! \endcode //! While the signature does not need to have const &, the function must not modify the objects passed to it. + //! The function must return `false` for identical elements, + //! otherwise, it will lead to undefined program behavior and memory errors. //! Sorting provided by [std::sort](https://en.cppreference.com/w/cpp/algorithm/sort). //! Complexity `O(N·log(N))`. //! \~russian Сохранность порядка элементов, имеющих одинаковое значение, не гарантируется. @@ -644,6 +646,8 @@ public: //! bool comp(const T &a, const T &b); //! \endcode //! Сигнатура не обязана содержать const &, однако, функция не может изменять переданные объекты. + //! Функция обязана возвращать `false` для одинаковых элементов, + //! иначе это приведёт к неопределённому поведению программы и ошибкам памяти. //! Для сортировки используется функция [std::sort](https://ru.cppreference.com/w/cpp/algorithm/sort). //! Сложность сортировки `O(N·log(N))`. //! \~\code @@ -693,13 +697,13 @@ public: } inline PIDeque & push_back(const T & e) { - alloc(pid_size + 1, true); + alloc_forward(pid_size + 1); PIINTROSPECTION_CONTAINER_USED(T, 1); elementNew(pid_data + pid_start + pid_size - 1, e); return *this; } inline PIDeque & push_back(T && e) { - alloc(pid_size + 1, true); + alloc_forward(pid_size + 1); PIINTROSPECTION_CONTAINER_USED(T, 1); elementNew(pid_data + pid_start + pid_size - 1, std::move(e)); return *this; @@ -714,7 +718,7 @@ public: #endif assert(&v != this); size_t ps = pid_size; - alloc(pid_size + v.pid_size, true); + alloc_forward(pid_size + v.pid_size); newT(pid_data + ps + pid_start, v.pid_data + v.pid_start, v.pid_size); return *this; } @@ -904,7 +908,7 @@ private: if ((uchar*)pid_data != 0) free((uchar*)pid_data); pid_data = 0; } - inline void checkMove(bool direction) { + inline void checkMove() { if (pid_size >= 4) { if (pid_size < pid_rsize / 6) { if (pid_start < ssize_t(pid_size + pid_size) || pid_start > (ssize_t(pid_rsize) - ssize_t(pid_size) - ssize_t(pid_size))) { @@ -923,11 +927,10 @@ private: } } } - inline void alloc(size_t new_size, bool direction, ssize_t start_offset = 0) { // direction == true -> alloc forward - if (direction) { + inline void alloc_forward(size_t new_size) { // direction == true -> alloc forward if (pid_start + new_size <= pid_rsize) { pid_size = new_size; - checkMove(direction); + checkMove(); return; } pid_size = new_size; @@ -944,7 +947,8 @@ private: pid_data = p_d; pid_rsize = as; } - } else { + } + inline void alloc_backward(size_t new_size, ssize_t start_offset = 0) { //alloc backward size_t as; if (pid_start + start_offset < 0) { as = asize(pid_rsize - start_offset); @@ -965,8 +969,7 @@ private: } pid_start += start_offset; pid_size = new_size; - checkMove(direction); - } + checkMove(); } T * pid_data; diff --git a/libs/main/containers/pivector.h b/libs/main/containers/pivector.h index de3c3430..12b055b9 100644 --- a/libs/main/containers/pivector.h +++ b/libs/main/containers/pivector.h @@ -1287,6 +1287,8 @@ public: //! bool comp(const T &a, const T &b); //! \endcode //! While the signature does not need to have const &, the function must not modify the objects passed to it. + //! The function must return `false` for identical elements, + //! otherwise, it will lead to undefined program behavior and memory errors. //! Sorting provided by [std::sort](https://en.cppreference.com/w/cpp/algorithm/sort). //! Complexity `O(N·log(N))`. //! \~russian Сохранность порядка элементов, имеющих одинаковое значение, не гарантируется. @@ -1297,6 +1299,8 @@ public: //! bool comp(const T &a, const T &b); //! \endcode //! Сигнатура не обязана содержать const &, однако, функция не может изменять переданные объекты. + //! Функция обязана возвращать `false` для одинаковых элементов, + //! иначе это приведёт к неопределённому поведению программы и ошибкам памяти. //! Для сортировки используется функция [std::sort](https://ru.cppreference.com/w/cpp/algorithm/sort). //! Сложность сортировки `O(N·log(N))`. //! \~\code @@ -1795,6 +1799,18 @@ public: return ret; } + //! \brief + //! \~english Returns a new array with all elements + //! that pass the test implemented by the provided function `test`. + //! \~russian Возвращает новый массив со всеми элементами, + //! прошедшими проверку, задаваемую в передаваемой функции `test`. + //! \~\details + //! \~\code + //! PIVector v{3, 2, 5, 2, 7}; + //! PIVector v2 = v.filter([](const int & i){return i > 2;}); + //! piCout << v2; // {3, 5, 7} + //! \endcode + //! \~\sa \a take_front(), \a pop_back(), \a pop_front() inline PIVector filter(std::function test) const { PIVector ret; for (size_t i = 0; i < piv_size; ++i) {