diff --git a/libs/main/containers/pideque.h b/libs/main/containers/pideque.h index 17bd087d..83a031b3 100644 --- a/libs/main/containers/pideque.h +++ b/libs/main/containers/pideque.h @@ -127,13 +127,13 @@ public: //! \~english Constructs an empty array. //! \~russian Создает пустой массив. - inline PIDeque(): pid_data(0), pid_size(0), pid_rsize(0), pid_start(0) { + inline PIDeque() { PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T)) } //! \~english Copy constructor. //! \~russian Копирующий конструктор. - inline PIDeque(const PIDeque & other): pid_data(0), pid_size(0), pid_rsize(0), pid_start(0) { + inline PIDeque(const PIDeque & other) { PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T)) alloc_forward(other.pid_size); newT(pid_data + pid_start, other.pid_data + other.pid_start, pid_size); @@ -148,7 +148,7 @@ public: //! PIDeque v{1,2,3}; //! piCout << v; // {1, 2, 3} //! \endcode - inline PIDeque(std::initializer_list init_list): pid_data(0), pid_size(0), pid_rsize(0), pid_start(0) { + inline PIDeque(std::initializer_list init_list) { PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T)) alloc_forward(init_list.size()); newT(pid_data, init_list.begin(), init_list.size()); @@ -158,7 +158,7 @@ public: //! This constructor reserve `size` and copy from `data` pointer. //! \~russian Создает массив из указателя на данные `data` и размер `size`. //! То есть выделяет память для `size` элементов и копирует данные из указателя `data`. - inline PIDeque(const T * data, size_t size): pid_data(0), pid_size(0), pid_rsize(0), pid_start(0) { + inline PIDeque(const T * data, size_t size) { PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T)) alloc_forward(size); newT(pid_data + pid_start, data, pid_size); @@ -166,9 +166,9 @@ public: //! \~english Contructs array with size `size` filled elements `e`. //! \~russian Создает массив из `size` элементов заполненных `e`. - inline PIDeque(size_t pid_size, const T & e = T()): pid_data(0), pid_size(0), pid_rsize(0), pid_start(0) { + inline PIDeque(size_t pid_size, const T & e = T()) { PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T)) - resize(pid_size, e); + expand(pid_size, e); } //! \~english Contructs array with size `size` and elements created by function `f(size_t i)`. @@ -184,15 +184,19 @@ public: //! PIDeque v(5, [](size_t i){return i*2;}); //! piCout << v; // {0, 2, 4, 6, 8} //! \endcode - inline PIDeque(size_t piv_size, std::function f): pid_data(0), pid_size(0), pid_rsize(0), pid_start(0) { + inline PIDeque(size_t piv_size, std::function f) { PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T)) - resize(piv_size, f); + expand(piv_size, f); } //! \~english Move constructor. //! \~russian Перемещающий конструктор. - inline PIDeque(PIDeque && other): pid_data(other.pid_data), pid_size(other.pid_size), pid_rsize(other.pid_rsize), pid_start(other.pid_start) { + inline PIDeque(PIDeque && other) { PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T)) + pid_data = other.pid_data; + pid_size = other.pid_size; + pid_rsize = other.pid_rsize; + pid_start = other.pid_start; other._reset(); } @@ -1185,7 +1189,9 @@ public: !std::is_trivially_copyable::value , int>::type = 0> inline PIDeque & clear() { - resize(0); + deleteT(&(pid_data[pid_start]), pid_size); + pid_size = 0; + pid_start = (pid_rsize - pid_size) / 2; return *this; } template & resize(size_t new_size, const T & e = T()) { + if (new_size == 0) return clear(); if (new_size < pid_size) { deleteT(&(pid_data[new_size + pid_start]), pid_size - new_size); pid_size = new_size; - if (new_size == 0) { - pid_start = (pid_rsize - pid_size) / 2; - } - } - if (new_size > pid_size) { - size_t os = pid_size; - 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, e); - } + }else if (new_size > pid_size) { + expand(new_size, e); } return *this; } @@ -1299,20 +1297,12 @@ public: //! лишние элементы удаляются с конца массива. //! \~\sa \a size(), \a clear() inline PIDeque & resize(size_t new_size, std::function f) { + if (new_size == 0) return clear(); if (new_size < pid_size) { deleteT(&(pid_data[new_size + pid_start]), pid_size - new_size); pid_size = new_size; - if (new_size == 0) { - pid_start = (pid_rsize - pid_size) / 2; - } - } - if (new_size > pid_size) { - size_t os = pid_size; - 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)); - } + } else if (new_size > pid_size) { + expand(new_size, f); } return *this; } @@ -1485,7 +1475,10 @@ public: inline PIDeque & remove(size_t index, size_t count = 1) { if (count == 0) return *this; if (index + count >= pid_size) { - resize(index); + if (index < pid_size) { + deleteT(&(pid_data[index + pid_start]), pid_size - index); + pid_size = index; + } return *this; } size_t os = pid_size - index - count; @@ -1887,6 +1880,7 @@ public: //! \endcode //! \~\sa \a push_back(), \a append(), \a prepend(), \a insert() inline PIDeque & push_front(const T & e) { + if (isEmpty()) push_back(e); insert(0, e); return *this; } @@ -1898,6 +1892,7 @@ public: //! \~russian Перегруженая функция. //! \~\sa \a push_front() inline PIDeque & push_front(T && e) { + if (isEmpty()) push_back(std::move(e)); insert(0, std::move(e)); return *this; } @@ -1914,6 +1909,7 @@ public: //! \endcode //! \~\sa \a push_front() inline PIDeque & push_front(const PIDeque & v) { + if (isEmpty()) push_back(v); insert(0, v); return *this; } @@ -1929,6 +1925,7 @@ public: //! [списка инициализации C++11](https://ru.cppreference.com/w/cpp/utility/initializer_list). //! \~\sa \a append() inline PIDeque & push_front(std::initializer_list init_list) { + if (isEmpty()) push_back(init_list); insert(0, init_list); return *this; } @@ -2007,7 +2004,8 @@ public: //! \~\sa \a pop_front(), \a take_back(), \a take_front() inline PIDeque & pop_back() { if (pid_size == 0) return *this; - resize(pid_size - 1); + elementDelete(pid_data[pid_size + pid_start - 1]); + pid_size = pid_size - 1; return *this; } @@ -2028,7 +2026,9 @@ public: //! \~\sa \a pop_back(), \a take_back(), \a take_front() inline PIDeque & pop_front() { if (pid_size == 0) return *this; - remove(0); + elementDelete(pid_data[pid_start]); + pid_start += 1; + pid_size -= 1; return *this; } @@ -2420,7 +2420,7 @@ public: } #endif assert(rows*cols == pid_size); - ret.resize(rows); + ret.expand(rows); if (order == ReshapeByRow) { for (size_t r = 0; r < rows; r++) { ret[r] = PIDeque(&(pid_data[r*cols]), cols); @@ -2428,7 +2428,7 @@ public: } if (order == ReshapeByColumn) { for (size_t r = 0; r < rows; r++) { - ret[r].resize(cols); + ret[r].expand(cols); for (size_t c = 0; c < cols; c++) { ret[r][c] = pid_data[c*rows + r]; } @@ -2503,7 +2503,13 @@ public: } private: - inline void _reset() {pid_size = pid_rsize = pid_start = 0; pid_data = 0;} + inline void _reset() { + pid_size = 0; + pid_rsize = 0; + pid_start = 0; + pid_data = nullptr; + } + inline size_t asize(ssize_t s) { if (s <= 0) return 0; if (pid_rsize + pid_rsize >= size_t(s) && pid_rsize < size_t(s)) { @@ -2511,18 +2517,20 @@ private: } size_t t = _PIContainerConstants::minCountPoT(); size_t s_ = s - 1; - while (s_ >> t) - ++t; + while (s_ >> t) ++t; return (1 << t); } + template::value , int>::type = 0> inline void newT(T * dst, const T * src, size_t s) { PIINTROSPECTION_CONTAINER_USED(T, s) - for (size_t i = 0; i < s; ++i) + for (size_t i = 0; i < s; ++i) { elementNew(dst + i, src[i]); + } } + template::value , int>::type = 0> @@ -2530,51 +2538,73 @@ private: PIINTROSPECTION_CONTAINER_USED(T, s) memcpy((void*)(dst), (const void*)(src), s * sizeof(T)); } + template::value , int>::type = 0> inline void deleteT(T * d, size_t sz) { PIINTROSPECTION_CONTAINER_UNUSED(T, sz) - if ((uchar*)d != 0) { + if (d != nullptr) { for (size_t i = 0; i < sz; ++i) { elementDelete(d[i]); } } } + template::value , int>::type = 0> inline void deleteT(T * d, size_t sz) { PIINTROSPECTION_CONTAINER_UNUSED(T, sz) } + template::value , int>::type = 0> - inline void elementNew(T * to, const T & from) {new(to)T(from);} + inline void elementNew(T * to, const T & from) { + new(to)T(from); + } + template::value , int>::type = 0> - inline void elementNew(T * to, T && from) {new(to)T(std::move(from));} + inline void elementNew(T * to, T && from) { + new(to)T(std::move(from)); + } + template::value , int>::type = 0> - inline void elementNew(T1 * to, const T & from) {(*to) = from;} + inline void elementNew(T1 * to, const T & from) { + (*to) = from; + } + template::value , int>::type = 0> - inline void elementNew(T * to, T && from) {(*to) = std::move(from);} + inline void elementNew(T * to, T && from) { + (*to) = std::move(from); + } + template::value , int>::type = 0> - inline void elementDelete(T & from) {from.~T();} + inline void elementDelete(T & from) { + from.~T(); + } + template::value , int>::type = 0> inline void elementDelete(T & from) {} + inline void dealloc() { - if ((uchar*)pid_data != 0) free((uchar*)pid_data); - pid_data = 0; + if (pid_data != nullptr) { + free((uchar*)pid_data); + pid_data = nullptr; + } } + inline void checkMove() { if (pid_size >= 4) { if (pid_size < pid_rsize / 6) { @@ -2594,55 +2624,75 @@ private: } } } - inline void alloc_forward(size_t new_size) { // direction == true -> alloc forward - if (pid_start + new_size <= pid_rsize) { - pid_size = new_size; - checkMove(); - return; - } - pid_size = new_size; - size_t as = asize(pid_start + new_size); - if (as != pid_rsize) { - PIINTROSPECTION_CONTAINER_ALLOC(T, (as-pid_rsize)) - T * p_d = (T*)(realloc((void*)(pid_data), as*sizeof(T))); -#ifndef NDEBUG - if (!p_d) { - printf("error with PIDeque<%s>::alloc\n", __PIP_TYPENAME__(T)); - } -#endif - assert(p_d); - pid_data = p_d; - pid_rsize = as; - } - } - inline void alloc_backward(size_t new_size, ssize_t start_offset = 0) { //alloc backward - size_t as; - if (ssize_t(pid_start) + start_offset < 0) { - as = asize(pid_rsize - start_offset); - } else { - as = pid_rsize; - } - if (as > pid_rsize) { - T * td = (T*)(malloc(as * sizeof(T))); - size_t ns = pid_start + as - pid_rsize; - PIINTROSPECTION_CONTAINER_ALLOC(T, (as-pid_rsize)) - if (pid_rsize > 0 && pid_data != 0) { - memcpy((void*)(td + ns), (const void*)(pid_data + pid_start), pid_size * sizeof(T)); - dealloc(); - } - pid_data = td; - pid_rsize = as; - pid_start = ns; - } - pid_start += start_offset; + + inline void alloc_forward(size_t new_size) { + if (pid_start + new_size <= pid_rsize) { pid_size = new_size; checkMove(); + return; + } + pid_size = new_size; + size_t as = asize(pid_start + new_size); + if (as != pid_rsize) { + PIINTROSPECTION_CONTAINER_ALLOC(T, (as-pid_rsize)) + T * p_d = (T*)(realloc((void*)(pid_data), as*sizeof(T))); +#ifndef NDEBUG + if (!p_d) { + printf("error with PIDeque<%s>::alloc\n", __PIP_TYPENAME__(T)); + } +#endif + assert(p_d); + pid_data = p_d; + pid_rsize = as; + } } - T * pid_data; - size_t pid_size; - size_t pid_rsize; - size_t pid_start; + inline void alloc_backward(size_t new_size, ssize_t start_offset = 0) { + size_t as; + if (ssize_t(pid_start) + start_offset < 0) { + as = asize(pid_rsize - start_offset); + } else { + as = pid_rsize; + } + if (as > pid_rsize) { + T * td = (T*)(malloc(as * sizeof(T))); + size_t ns = pid_start + as - pid_rsize; + PIINTROSPECTION_CONTAINER_ALLOC(T, (as-pid_rsize)) + if (pid_rsize > 0 && pid_data != 0) { + memcpy((void*)(td + ns), (const void*)(pid_data + pid_start), pid_size * sizeof(T)); + dealloc(); + } + pid_data = td; + pid_rsize = as; + pid_start = ns; + } + pid_start += start_offset; + pid_size = new_size; + checkMove(); + } + + inline void expand(size_t new_size, const T & e = T()) { + size_t os = pid_size; + 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, e); + } + } + + inline void expand(size_t new_size, std::function f) { + size_t os = pid_size; + 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)); + } + } + + T * pid_data = nullptr; + size_t pid_size = 0; + size_t pid_rsize = 0; + size_t pid_start = 0; }; diff --git a/libs/main/containers/piqueue.h b/libs/main/containers/piqueue.h index ba5103d1..15eac7b1 100644 --- a/libs/main/containers/piqueue.h +++ b/libs/main/containers/piqueue.h @@ -39,7 +39,7 @@ public: T & head() {return PIDeque::back();} const T & head() const {return PIDeque::back();} PIVector toVector() {return PIVector(PIDeque::data(), PIDeque::size());} - PIVector toDeque() {return PIDeque(*this);} + PIDeque toDeque() {return PIDeque(*this);} }; #endif // PIQUEUE_H diff --git a/libs/main/containers/pistack.h b/libs/main/containers/pistack.h index 84a6811c..f04a4c53 100644 --- a/libs/main/containers/pistack.h +++ b/libs/main/containers/pistack.h @@ -38,7 +38,7 @@ public: T & top() {return PIVector::back();} const T & top() const {return PIVector::back();} PIVector toVector() {return PIVector(*this);} - PIVector toDeque() {return PIDeque(PIVector::data(), PIVector::size());} + PIDeque toDeque() {return PIDeque(PIVector::data(), PIVector::size());} }; #endif // PISTACK_H