diff --git a/CMakeLists.txt b/CMakeLists.txt index 01c31722..ea8dfebe 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,9 +2,9 @@ cmake_minimum_required(VERSION 3.0) cmake_policy(SET CMP0017 NEW) # need include() with .cmake project(PIP) set(PIP_MAJOR 3) -set(PIP_MINOR 0) +set(PIP_MINOR 1) set(PIP_REVISION 0) -set(PIP_SUFFIX rc) +set(PIP_SUFFIX dev) set(PIP_COMPANY SHS) set(PIP_DOMAIN org.SHS) diff --git a/libs/main/containers/pideque.h b/libs/main/containers/pideque.h index e926e392..ee3741a9 100644 --- a/libs/main/containers/pideque.h +++ b/libs/main/containers/pideque.h @@ -751,6 +751,30 @@ public: //! Иначе это приведёт к неопределённому поведению программы и ошибкам памяти. inline const T & at(size_t index) const {return pid_data[pid_start + index];} + //! \~english Returns the first element of the array that + //! passes the test implemented by the provided function `test` + //! or `def` if there is no such element. + //! \~russian Возвращает первый элемент массива, проходящего по условию, + //! заданному в передаваемой функции `test`, или `def` если такого элемента нет. + //! \~\sa \a indexWhere() + inline const T & atWhere(std::function test, ssize_t start = 0, const T & def = T()) const { + ssize_t i = indexWhere(test, start); + if (i < 0) return def; + else return at(i); + } + + //! \~english Returns the last element of the array that + //! passes the test implemented by the provided function `test` + //! or `def` if there is no such element. + //! \~russian Возвращает последний элемент массива, проходящего по условию, + //! заданному в передаваемой функции `test`, или `def` если такого элемента нет. + //! \~\sa \a lastIndexWhere() + inline const T & lastAtWhere(std::function test, ssize_t start = -1, const T & def = T()) const { + ssize_t i = lastIndexWhere(test, start); + if (i < 0) return def; + else return at(i); + } + //! \~english Last element. //! \~russian Последний элемент массива. //! \~\details @@ -805,7 +829,7 @@ public: //! возвращается **false**, что означает, что массив даже не просматривается. //! Если индекс является отрицательным числом, он трактуется как смещение с конца массива. //! Если рассчитанный индекс все равно оказывается меньше 0, просматривается весь массив. - //! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу. + //! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу (слева на право). //! Значение по умолчанию равно 0, что означает, что просматривается весь массив. //! \~\code //! PIDeque v{1, 2, 3, 4}; @@ -832,6 +856,33 @@ public: return false; } + //! \~english Tests if all elements of `v` exists in the array. + //! \~russian Проверяет наличие всех элементов `v` в массиве. + //! \~\details + //! \~\code + //! PIDeque v{1, 2, 3, 4}; + //! piCout << v.contains({1,4}); // true + //! piCout << v.contains({1,5}); // false + //! \endcode + //! \~\sa \a every(), \a any(), \a entries(), \a forEach() + inline bool contains(const PIDeque & v, ssize_t start = 0) const { + if (start < 0) { + start = pid_size + start; + if (start < 0) start = 0; + } + for (const T & e : v) { + bool c = false; + for (size_t i = pid_start + size_t(start); i < pid_start + pid_size; ++i) { + if (e == pid_data[i]) { + c = true; + break; + } + } + if (!c) return false; + } + return true; + } + //! \~english Count elements equal `e` in the array. //! \~russian Подсчитывает количество элементов, совпадающих с элементом `e` в массиве. //! \~\details @@ -848,7 +899,7 @@ public: //! возвращается 0, что означает, что массив даже не просматривается. //! Если индекс является отрицательным числом, он трактуется как смещение с конца массива. //! Если рассчитанный индекс все равно оказывается меньше 0, просматривается весь массив. - //! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу. + //! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу (слева на право). //! Значение по умолчанию равно 0, что означает, что просматривается весь массив. //! \~\code //! PIDeque v{2, 2, 4, 2, 6}; @@ -888,7 +939,7 @@ public: //! возвращается 0, что означает, что массив даже не просматривается. //! Если индекс является отрицательным числом, он трактуется как смещение с конца массива. //! Если рассчитанный индекс все равно оказывается меньше 0, просматривается весь массив. - //! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу. + //! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу (слева на право). //! Значение по умолчанию равно 0, что означает, что просматривается весь массив. //! \~\sa \a every(), \a any(), \a contains(), \a forEach(), \a indexWhere() inline int entries(std::function test, ssize_t start = 0) const { @@ -921,7 +972,7 @@ public: //! возвращается `-1`, что означает, что массив даже не просматривается. //! Если индекс является отрицательным числом, он трактуется как смещение с конца массива. //! Если рассчитанный индекс все равно оказывается меньше 0, просматривается весь массив. - //! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу. + //! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу (слева на право). //! Значение по умолчанию равно 0, что означает, что просматривается весь массив. //! \~\code //! PIDeque v{2, 5, 9}; @@ -964,7 +1015,7 @@ public: //! возвращается `-1`, что означает, что массив даже не просматривается. //! Если индекс является отрицательным числом, он трактуется как смещение с конца массива. //! Если рассчитанный индекс все равно оказывается меньше 0, просматривается весь массив. - //! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу. + //! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу (слева на право). //! Значение по умолчанию равно 0, что означает, что просматривается весь массив. //! \~\code //! PIDeque v{"do", "re", "mi", "re"}; @@ -1006,7 +1057,7 @@ public: //! c которого начинать поиск в обратном направлении. //! Если индекс больше или равен длине массива, просматривается весь массив. //! Если индекс является отрицательным числом, он трактуется как смещение с конца массива. - //! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от конца к началу. + //! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от конца к началу (справа на лево). //! Если рассчитанный индекс оказывается меньше 0, массив даже не просматривается. //! Значение по умолчанию равно `-1`, что равно индексу последнего элемента //! и означает, что просматривается весь массив. @@ -1023,9 +1074,9 @@ public: inline ssize_t lastIndexOf(const T & e, ssize_t start = -1) const { if (start >= size_s()) start = pid_size - 1; if (start < 0) start = pid_size + start; - for (size_t i = pid_start + size_t(start); i >= pid_start; --i) { + for (ssize_t i = ssize_t(pid_start) + start; i >= ssize_t(pid_start); --i) { if (e == pid_data[i]) { - return ssize_t(i) - pid_start; + return i - ssize_t(pid_start); } } return -1; @@ -1051,7 +1102,7 @@ public: //! c которого начинать поиск в обратном направлении. //! Если индекс больше или равен длине массива, просматривается весь массив. //! Если индекс является отрицательным числом, он трактуется как смещение с конца массива. - //! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от конца к началу. + //! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от конца к началу (справа на лево). //! Если рассчитанный индекс оказывается меньше 0, массив даже не просматривается. //! Значение по умолчанию равно `-1`, что равно индексу последнего элемента //! и означает, что просматривается весь массив. @@ -1059,9 +1110,9 @@ public: inline ssize_t lastIndexWhere(std::function test, ssize_t start = -1) const { if (start >= size_s()) start = pid_size - 1; if (start < 0) start = pid_size + start; - for (size_t i = pid_start + size_t(start); i >= pid_start; --i) { + for (ssize_t i = ssize_t(pid_start) + start; i >= ssize_t(pid_start); --i) { if (test(pid_data[i])) { - return ssize_t(i) - pid_start; + return i - ssize_t(pid_start); } } return -1; @@ -2048,6 +2099,39 @@ public: return ret; } + //! \~english Same as \a filter() but with `index` parameter in `test`. + //! \~russian Аналогично \a filter() но с параметром индекса `index` в функции `test`. + //! \~\sa \a filter() + inline PIDeque filterIndexed(std::function test) const { + PIDeque ret; + for (size_t i = pid_start; i < pid_start + pid_size; ++i) { + if (test(i - pid_start, pid_data[i])) ret << pid_data[i]; + } + return ret; + } + + //! \~english Same as \a filter() but from end to begin (from right to left). + //! \~russian Аналогично \a filter() но от конца до начала (справа на лево). + //! \~\sa \a filter() + inline PIDeque filterReverse(std::function test) const { + PIDeque ret; + for (ssize_t i = ssize_t(pid_start+pid_size) - 1; i >= ssize_t(pid_start); --i) { + if (test(pid_data[i])) ret << pid_data[i]; + } + return ret; + } + + //! \~english Same as \a filterReverse() but with `index` parameter in `test`. + //! \~russian Аналогично \a filterReverse() но с параметром индекса `index` в функции `test`. + //! \~\sa \a filterReverse() + inline PIDeque filterReverseIndexed(std::function test) const { + PIDeque ret; + for (ssize_t i = ssize_t(pid_start+pid_size) - 1; i >= ssize_t(pid_start); --i) { + if (test(i - pid_start, pid_data[i])) ret << pid_data[i]; + } + return ret; + } + //! \~english Execute function `void f(const T & e)` for every element in array. //! \~russian Выполняет функцию `void f(const T & e)` для каждого элемента массива. //! \~\details @@ -2088,6 +2172,63 @@ public: return *this; } + //! \~english Same as \a forEach() but with `index` parameter in `f`. + //! \~russian Аналогично \a forEach() но с параметром индекса `index` в функции `f`. + //! \~\sa \a forEach() + inline void forEachIndexed(std::function f) const { + for (size_t i = pid_start; i < pid_start + pid_size; ++i) { + f(i - pid_start, pid_data[i]); + } + } + + //! \~english Same as \a forEachIndexed(), but allows you to change the elements of the array. + //! \~russian Аналогично \a forEachIndexed(), но позволяет изменять элементы массива. + //! \~\sa \a forEach(), \a forEachIndexed() + inline PIDeque & forEachIndexed(std::function f) { + for (size_t i = pid_start; i < pid_start + pid_size; ++i) { + f(i - pid_start, pid_data[i]); + } + return *this; + } + + //! \~english Same as \a forEach() but from end to begin (from right to left). + //! \~russian Аналогично \a forEach() но от конца до начала (справа на лево). + //! \~\sa \a forEach() + inline void forEachReverse(std::function f) const { + for (ssize_t i = ssize_t(pid_start+pid_size) - 1; i >= ssize_t(pid_start); --i) { + f(pid_data[i]); + } + } + + //! \~english Same as \a forEachReverse(), but allows you to change the elements of the array. + //! \~russian Аналогично \a forEachReverse(), но позволяет изменять элементы массива. + //! \~\sa \a forEach(), \a forEachReverse() + inline PIDeque & forEachReverse(std::function f) { + for (ssize_t i = ssize_t(pid_start+pid_size) - 1; i >= ssize_t(pid_start); --i) { + f(pid_data[i]); + } + return *this; + } + + //! \~english Same as \a forEachIndexed() but from end to begin (from right to left). + //! \~russian Аналогично \a forEachIndexed() но от конца до начала (справа на лево). + //! \~\sa \a forEachIndexed(), \a forEachReverse(), \a forEach() + inline void forEachReverseIndexed(std::function f) const { + for (ssize_t i = ssize_t(pid_start+pid_size) - 1; i >= ssize_t(pid_start); --i) { + f(i - pid_start, pid_data[i]); + } + } + + //! \~english Same as \a forEachReverseIndexed(), but allows you to change the elements of the array. + //! \~russian Аналогично \a forEachReverseIndexed(), но позволяет изменять элементы массива. + //! \~\sa \a forEachReverseIndexed(), \a forEachIndexed(), \a forEachReverse(), \a forEach() + inline PIDeque & forEachReverseIndexed(std::function f) { + for (ssize_t i = ssize_t(pid_start+pid_size) - 1; i >= ssize_t(pid_start); --i) { + f(i - pid_start, pid_data[i]); + } + return *this; + } + //! \~english Сreates a new array populated with the results //! of calling a provided function `ST f(const T & e)` on every element in the calling array. //! \~russian Создаёт новый массив с результатом вызова указанной функции @@ -2097,12 +2238,12 @@ public: //! once for each element in an array, in order, //! and constructs a new array from the results. //! \~russian Метод `map` вызывает переданную функцию `ST f(const T & e)` - //! один раз для каждого элемента в порядке их появления + //! один раз для каждого элемента в порядке их появления от начала к концу (слева на право) //! и конструирует новый массив из результатов её вызова. //! \~\code //! PIDeque v{1, 2, 3}; //! PIStringList sl = v.map([](const int & i){return PIString::fromNumber(i);}); - //! piCout << sl; {"1", "2", "3"} + //! piCout << sl; // {"1", "2", "3"} //! \endcode //! \~\sa \a forEach(), \a reduce() template @@ -2114,6 +2255,57 @@ public: return ret; } + //! \~english Same as \a map() but with `index` parameter in `f`. + //! \~russian Аналогично \a map() но с параметром индекса `index` в функции `f`. + //! \~\code + //! PIDeque v{1, 2, 3}; + //! PIStringList sl = v.mapIndexed([](size_t index, const int & i){return PIString::fromNumber(index);}); + //! piCout << sl; // {"0", "1", "2"} + //! \endcode + //! \~\sa \a map() + template + inline PIDeque mapIndexed(std::function f) const { + PIDeque ret; ret.reserve(pid_size); + for (size_t i = pid_start; i < pid_start + pid_size; ++i) { + ret << f(i - pid_start, pid_data[i]); + } + return ret; + } + + //! \~english Same as \a map() but from end to begin (from right to left). + //! \~russian Аналогично \a map() но от конца до начала (справа на лево). + //! \~\code + //! PIDeque v{1, 2, 3}; + //! PIStringList sl = v.mapReverse([](const int & i){return PIString::fromNumber(i);}); + //! piCout << sl; // {"3", "2", "1"} + //! \endcode + //! \~\sa \a map() + template + inline PIDeque mapReverse(std::function f) const { + PIDeque ret; ret.reserve(pid_size); + for (ssize_t i = ssize_t(pid_start+pid_size) - 1; i >= ssize_t(pid_start); --i) { + ret << f(pid_data[i]); + } + return ret; + } + + //! \~english Same as \a mapReverse() but with `index` parameter in `f`. + //! \~russian Аналогично \a mapReverse() но с параметром индекса `index` в функции `f`. + //! \~\code + //! PIDeque v{1, 2, 3}; + //! PIStringList sl = v.mapReverseIndexed([](size_t index, const int & i){return PIString::fromNumber(index);}); + //! piCout << sl; // {"2", "1", "0"} + //! \endcode + //! \~\sa \a mapReverse() + template + inline PIDeque mapReverseIndexed(std::function f) const { + PIDeque ret; ret.reserve(pid_size); + for (ssize_t i = ssize_t(pid_start+pid_size) - 1; i >= ssize_t(pid_start); --i) { + ret << f(size_t(i) - pid_start, pid_data[i]); + } + return ret; + } + //! \~english Applies the function `ST f(const T & e, const ST & acc)` //! to each element of the array (from left to right), returns one value. //! \~russian Применяет функцию `ST f(const T & e, const ST & acc)` @@ -2134,7 +2326,7 @@ public: //! \param initial _optional_ Object used as the second argument //! when the `f` function is first called. //! \~russian Метод reduce() выполняет функцию `f` - //! один раз для каждого элемента, присутствующего в массиве. + //! один раз для каждого элемента, присутствующего в массиве от начала к концу (слева на право). //! Если при вызове reduce() передан аргумент `initial`, //! то при первом вызове функции `f` значение `acc` //! будет равным значению `initial`. @@ -2154,7 +2346,7 @@ public: //! int s = v.reduce([](const int & e, const int & acc){return e + acc;}); //! piCout << s; // 15 //! \endcode - //! \~\sa \a forEach(), \a map() + //! \~\sa \a reduceIndexed(), \a reduceReverse(), \a reduceReverseIndexed(), \a forEach(), \a map() template inline ST reduce(std::function f, const ST & initial = ST()) const { ST ret(initial); @@ -2164,6 +2356,42 @@ public: return ret; } + //! \~english Same as \a reduce() but with `index` parameter in `f`. + //! \~russian Аналогично \a reduce() но с параметром индекса `index` в функции `f`. + //! \~\sa \a reduce() + template + inline ST reduceIndexed(std::function f, const ST & initial = ST()) const { + ST ret(initial); + for (size_t i = pid_start; i < pid_start + pid_size; ++i) { + ret = f(i - pid_start, pid_data[i], ret); + } + return ret; + } + + //! \~english Same as \a reduce() but from end to begin (from right to left). + //! \~russian Аналогично \a reduce() но от конца до начала (справа на лево). + //! \~\sa \a reduce() + template + inline ST reduceReverse(std::function f, const ST & initial = ST()) const { + ST ret(initial); + for (ssize_t i = ssize_t(pid_start+pid_size) - 1; i >= ssize_t(pid_start); --i) { + ret = f(pid_data[i], ret); + } + return ret; + } + + //! \~english Same as \a reduceReverse() but with `index` parameter in `f`. + //! \~russian Аналогично \a reduceReverse() но с параметром индекса `index` в функции `f`. + //! \~\sa \a reduceReverse() + template + inline ST reduceReverseIndexed(std::function f, const ST & initial = ST()) const { + ST ret(initial); + for (ssize_t i = ssize_t(pid_start+pid_size) - 1; i >= ssize_t(pid_start); --i) { + ret = f(size_t(i) - pid_start, pid_data[i], ret); + } + return ret; + } + //! \~english Changes the dimension of the array, creates a two-dimensional array from a one-dimensional array. //! \~russian Изменяет размерность массива, из одномерного массива создает двухмерный. //! \~\details @@ -2326,7 +2554,7 @@ private: 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(from);} template::value , int>::type = 0> diff --git a/libs/main/containers/piqueue.h b/libs/main/containers/piqueue.h index 8c58e360..ba5103d1 100644 --- a/libs/main/containers/piqueue.h +++ b/libs/main/containers/piqueue.h @@ -38,13 +38,8 @@ public: T dequeue() {return PIDeque::take_back();} T & head() {return PIDeque::back();} const T & head() const {return PIDeque::back();} - PIVector toVector() { - PIVector v; - v.reserve(PIDeque::size()); - for (uint i = 0; i < PIDeque::size(); ++i) - v.push_back(PIDeque::at(i)); - return v; - } + PIVector toVector() {return PIVector(PIDeque::data(), PIDeque::size());} + PIVector toDeque() {return PIDeque(*this);} }; #endif // PIQUEUE_H diff --git a/libs/main/containers/pistack.h b/libs/main/containers/pistack.h index fdc0f903..84a6811c 100644 --- a/libs/main/containers/pistack.h +++ b/libs/main/containers/pistack.h @@ -26,6 +26,7 @@ #define PISTACK_H #include "pivector.h" +#include "pideque.h" template class PIStack: public PIVector { @@ -37,6 +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());} }; #endif // PISTACK_H diff --git a/libs/main/containers/pivector.h b/libs/main/containers/pivector.h index 14624ed2..08c87c87 100644 --- a/libs/main/containers/pivector.h +++ b/libs/main/containers/pivector.h @@ -748,6 +748,31 @@ public: //! Иначе это приведёт к неопределённому поведению программы и ошибкам памяти. inline const T & at(size_t index) const {return piv_data[index];} + + //! \~english Returns the first element of the array that + //! passes the test implemented by the provided function `test` + //! or `def` if there is no such element. + //! \~russian Возвращает первый элемент массива, проходящего по условию, + //! заданному в передаваемой функции `test`, или `def` если такого элемента нет. + //! \~\sa \a indexWhere() + inline const T & atWhere(std::function test, ssize_t start = 0, const T & def = T()) const { + ssize_t i = indexWhere(test, start); + if (i < 0) return def; + else return at(i); + } + + //! \~english Returns the last element of the array that + //! passes the test implemented by the provided function `test` + //! or `def` if there is no such element. + //! \~russian Возвращает последний элемент массива, проходящего по условию, + //! заданному в передаваемой функции `test`, или `def` если такого элемента нет. + //! \~\sa \a lastIndexWhere() + inline const T & lastAtWhere(std::function test, ssize_t start = -1, const T & def = T()) const { + ssize_t i = lastIndexWhere(test, start); + if (i < 0) return def; + else return at(i); + } + //! \~english Last element. //! \~russian Последний элемент массива. //! \~\details @@ -802,7 +827,7 @@ public: //! возвращается **false**, что означает, что массив даже не просматривается. //! Если индекс является отрицательным числом, он трактуется как смещение с конца массива. //! Если рассчитанный индекс все равно оказывается меньше 0, просматривается весь массив. - //! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу. + //! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу (слева на право). //! Значение по умолчанию равно 0, что означает, что просматривается весь массив. //! \~\code //! PIVector v{1, 2, 3, 4}; @@ -829,6 +854,33 @@ public: return false; } + //! \~english Tests if all elements of `v` exists in the array. + //! \~russian Проверяет наличие всех элементов `v` в массиве. + //! \~\details + //! \~\code + //! PIVector v{1, 2, 3, 4}; + //! piCout << v.contains({1,4}); // true + //! piCout << v.contains({1,5}); // false + //! \endcode + //! \~\sa \a every(), \a any(), \a entries(), \a forEach() + inline bool contains(const PIVector & v, ssize_t start = 0) const { + if (start < 0) { + start = piv_size + start; + if (start < 0) start = 0; + } + for (const T & e : v) { + bool c = false; + for (size_t i = start; i < piv_size; ++i) { + if (e == piv_data[i]) { + c = true; + break; + } + } + if (!c) return false; + } + return true; + } + //! \~english Count elements equal `e` in the array. //! \~russian Подсчитывает количество элементов, совпадающих с элементом `e` в массиве. //! \~\details @@ -845,7 +897,7 @@ public: //! возвращается 0, что означает, что массив даже не просматривается. //! Если индекс является отрицательным числом, он трактуется как смещение с конца массива. //! Если рассчитанный индекс все равно оказывается меньше 0, просматривается весь массив. - //! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу. + //! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу (слева на право). //! Значение по умолчанию равно 0, что означает, что просматривается весь массив. //! \~\code //! PIVector v{2, 2, 4, 2, 6}; @@ -885,7 +937,7 @@ public: //! возвращается 0, что означает, что массив даже не просматривается. //! Если индекс является отрицательным числом, он трактуется как смещение с конца массива. //! Если рассчитанный индекс все равно оказывается меньше 0, просматривается весь массив. - //! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу. + //! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу (слева на право). //! Значение по умолчанию равно 0, что означает, что просматривается весь массив. //! \~\sa \a every(), \a any(), \a contains(), \a forEach(), \a indexWhere() inline int entries(std::function test, ssize_t start = 0) const { @@ -918,7 +970,7 @@ public: //! возвращается `-1`, что означает, что массив даже не просматривается. //! Если индекс является отрицательным числом, он трактуется как смещение с конца массива. //! Если рассчитанный индекс все равно оказывается меньше 0, просматривается весь массив. - //! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу. + //! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу (слева на право). //! Значение по умолчанию равно 0, что означает, что просматривается весь массив. //! \~\code //! PIVector v{2, 5, 9}; @@ -959,7 +1011,7 @@ public: //! возвращается `-1`, что означает, что массив даже не просматривается. //! Если индекс является отрицательным числом, он трактуется как смещение с конца массива. //! Если рассчитанный индекс все равно оказывается меньше 0, просматривается весь массив. - //! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу. + //! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу (слева на право). //! Значение по умолчанию равно 0, что означает, что просматривается весь массив. //! \~\code //! PIVector v{"do", "re", "mi", "re"}; @@ -999,7 +1051,7 @@ public: //! c которого начинать поиск в обратном направлении. //! Если индекс больше или равен длине массива, просматривается весь массив. //! Если индекс является отрицательным числом, он трактуется как смещение с конца массива. - //! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от конца к началу. + //! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от конца к началу (справа на лево). //! Если рассчитанный индекс оказывается меньше 0, массив даже не просматривается. //! Значение по умолчанию равно `-1`, что равно индексу последнего элемента //! и означает, что просматривается весь массив. @@ -1042,7 +1094,7 @@ public: //! c которого начинать поиск в обратном направлении. //! Если индекс больше или равен длине массива, просматривается весь массив. //! Если индекс является отрицательным числом, он трактуется как смещение с конца массива. - //! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от конца к началу. + //! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от конца к началу (справа на лево). //! Если рассчитанный индекс оказывается меньше 0, массив даже не просматривается. //! Значение по умолчанию равно `-1`, что равно индексу последнего элемента //! и означает, что просматривается весь массив. @@ -1972,6 +2024,39 @@ public: return ret; } + //! \~english Same as \a filter() but with `index` parameter in `test`. + //! \~russian Аналогично \a filter() но с параметром индекса `index` в функции `test`. + //! \~\sa \a filter() + inline PIVector filterIndexed(std::function test) const { + PIVector ret; + for (size_t i = 0; i < piv_size; ++i) { + if (test(i, piv_data[i])) ret << piv_data[i]; + } + return ret; + } + + //! \~english Same as \a filter() but from end to begin (from right to left). + //! \~russian Аналогично \a filter() но от конца до начала (справа на лево). + //! \~\sa \a filter() + inline PIVector filterReverse(std::function test) const { + PIVector ret; + for (ssize_t i = piv_size; i >= 0; --i) { + if (test(piv_data[i])) ret << piv_data[i]; + } + return ret; + } + + //! \~english Same as \a filterReverse() but with `index` parameter in `test`. + //! \~russian Аналогично \a filterReverse() но с параметром индекса `index` в функции `test`. + //! \~\sa \a filterReverse() + inline PIVector filterReverseIndexed(std::function test) const { + PIVector ret; + for (ssize_t i = piv_size; i >= 0; --i) { + if (test(i, piv_data[i])) ret << piv_data[i]; + } + return ret; + } + //! \~english Execute function `void f(const T & e)` for every element in array. //! \~russian Выполняет функцию `void f(const T & e)` для каждого элемента массива. //! \~\details @@ -2012,6 +2097,63 @@ public: return *this; } + //! \~english Same as \a forEach() but with `index` parameter in `f`. + //! \~russian Аналогично \a forEach() но с параметром индекса `index` в функции `f`. + //! \~\sa \a forEach() + inline void forEachIndexed(std::function f) const { + for (size_t i = 0; i < piv_size; ++i) { + f(i, piv_data[i]); + } + } + + //! \~english Same as \a forEachIndexed(), but allows you to change the elements of the array. + //! \~russian Аналогично \a forEachIndexed(), но позволяет изменять элементы массива. + //! \~\sa \a forEach(), \a forEachIndexed() + inline PIVector & forEachIndexed(std::function f) { + for (size_t i = 0; i < piv_size; ++i) { + f(i, piv_data[i]); + } + return *this; + } + + //! \~english Same as \a forEach() but from end to begin (from right to left). + //! \~russian Аналогично \a forEach() но от конца до начала (справа на лево). + //! \~\sa \a forEach() + inline void forEachReverse(std::function f) const { + for (ssize_t i = piv_size; i >= 0; --i) { + f(piv_data[i]); + } + } + + //! \~english Same as \a forEachReverse(), but allows you to change the elements of the array. + //! \~russian Аналогично \a forEachReverse(), но позволяет изменять элементы массива. + //! \~\sa \a forEach(), \a forEachReverse() + inline PIVector & forEachReverse(std::function f) { + for (ssize_t i = piv_size; i >= 0; --i) { + f(piv_data[i]); + } + return *this; + } + + //! \~english Same as \a forEachIndexed() but from end to begin (from right to left). + //! \~russian Аналогично \a forEachIndexed() но от конца до начала (справа на лево). + //! \~\sa \a forEachIndexed(), \a forEachReverse(), \a forEach() + inline void forEachReverseIndexed(std::function f) const { + for (ssize_t i = piv_size; i >= 0; --i) { + f(i, piv_data[i]); + } + } + + //! \~english Same as \a forEachReverseIndexed(), but allows you to change the elements of the array. + //! \~russian Аналогично \a forEachReverseIndexed(), но позволяет изменять элементы массива. + //! \~\sa \a forEachReverseIndexed(), \a forEachIndexed(), \a forEachReverse(), \a forEach() + inline PIVector & forEachReverseIndexed(std::function f) { + for (ssize_t i = piv_size; i >= 0; --i) { + f(i, piv_data[i]); + } + return *this; + } + //! \~english Сreates a new array populated with the results //! of calling a provided function `ST f(const T & e)` on every element in the calling array. //! \~russian Создаёт новый массив с результатом вызова указанной функции @@ -2026,7 +2168,7 @@ public: //! \~\code //! PIVector v{1, 2, 3}; //! PIVector sl = v.map([](const int & i){return PIString::fromNumber(i);}); - //! piCout << sl; {"1", "2", "3"} + //! piCout << sl; // {"1", "2", "3"} //! \endcode //! \~\sa \a forEach(), \a reduce() template @@ -2038,6 +2180,57 @@ public: return ret; } + //! \~english Same as \a map() but with `index` parameter in `f`. + //! \~russian Аналогично \a map() но с параметром индекса `index` в функции `f`. + //! \~\code + //! PIVector v{1, 2, 3}; + //! PIVector sl = v.mapIndexed([](size_t index, const int & i){return PIString::fromNumber(index);}); + //! piCout << sl; // {"0", "1", "2"} + //! \endcode + //! \~\sa \a map() + template + inline PIVector mapIndexed(std::function f) const { + PIVector ret; ret.reserve(piv_size); + for (size_t i = 0; i < piv_size; ++i) { + ret << f(i, piv_data[i]); + } + return ret; + } + + //! \~english Same as \a map() but from end to begin (from right to left). + //! \~russian Аналогично \a map() но от конца до начала (справа на лево). + //! \~\code + //! PIVector v{1, 2, 3}; + //! PIVector sl = v.mapReverse([](const int & i){return PIString::fromNumber(i);}); + //! piCout << sl; // {"3", "2", "1"} + //! \endcode + //! \~\sa \a map() + template + inline PIVector mapReverse(std::function f) const { + PIVector ret; ret.reserve(piv_size); + for (ssize_t i = piv_size; i >= 0; --i) { + ret << f(piv_data[i]); + } + return ret; + } + + //! \~english Same as \a mapReverse() but with `index` parameter in `f`. + //! \~russian Аналогично \a mapReverse() но с параметром индекса `index` в функции `f`. + //! \~\code + //! PIVector v{1, 2, 3}; + //! PIVector sl = v.mapReverseIndexed([](size_t index, const int & i){return PIString::fromNumber(index);}); + //! piCout << sl; // {"2", "1", "0"} + //! \endcode + //! \~\sa \a mapReverse() + template + inline PIVector mapReverseIndexed(std::function f) const { + PIVector ret; ret.reserve(piv_size); + for (ssize_t i = piv_size; i >= 0; --i) { + ret << f(i, piv_data[i]); + } + return ret; + } + //! \~english Applies the function `ST f(const T & e, const ST & acc)` //! to each element of the array (from left to right), returns one value. //! \~russian Применяет функцию `ST f(const T & e, const ST & acc)` @@ -2088,6 +2281,42 @@ public: return ret; } + //! \~english Same as \a reduce() but with `index` parameter in `f`. + //! \~russian Аналогично \a reduce() но с параметром индекса `index` в функции `f`. + //! \~\sa \a reduce() + template + inline ST reduceIndexed(std::function f, const ST & initial = ST()) const { + ST ret(initial); + for (size_t i = 0; i < piv_size; ++i) { + ret = f(i, piv_data[i], ret); + } + return ret; + } + + //! \~english Same as \a reduce() but from end to begin (from right to left). + //! \~russian Аналогично \a reduce() но от конца до начала (справа на лево). + //! \~\sa \a reduce() + template + inline ST reduceReverse(std::function f, const ST & initial = ST()) const { + ST ret(initial); + for (ssize_t i = piv_size; i >= 0; --i) { + ret = f(piv_data[i], ret); + } + return ret; + } + + //! \~english Same as \a reduceReverse() but with `index` parameter in `f`. + //! \~russian Аналогично \a reduceReverse() но с параметром индекса `index` в функции `f`. + //! \~\sa \a reduceReverse() + template + inline ST reduceReverseIndexed(std::function f, const ST & initial = ST()) const { + ST ret(initial); + for (ssize_t i = piv_size; i >= 0; --i) { + ret = f(i, piv_data[i], ret); + } + return ret; + } + //! \~english Changes the dimension of the array, creates a two-dimensional array from a one-dimensional array. //! \~russian Изменяет размерность массива, из одномерного массива создает двухмерный. //! \~\details @@ -2249,7 +2478,7 @@ private: 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(from);} template::value , int>::type = 0> diff --git a/main.cpp b/main.cpp index c116ae08..5400a29b 100644 --- a/main.cpp +++ b/main.cpp @@ -1,13 +1,76 @@ #include "pip.h" #include "piiostream.h" #include "pibytearray.h" +#include using namespace PICoutManipulators; + +class A { +public: + A(int id) : id_(id) { + piCout << "A()" << id_ << this; + } + + A(const A & a) { + id_ = a.id_; + piCout << "A(A)" << id_ << this; + } + + A(A && a) { + std::swap(id_, a.id_); + piCout << "move A(A)" << id_ << this; + } + + ~A() { + piCout << "~A()" << id_ << this; + //id_ = 0; + } + + inline A & operator =(const A & a) { + id_ = a.id_; + piCout << "A =" << id_ << this; + return *this; + } + + inline A & operator =(A && a) { + std::swap(id_, a.id_); + piCout << "move A=" << id_ << this; + return *this; + } +private: + int id_; +}; + + +//class B { +//public: +// B() {a_ = nullptr;} +// ~B() {if (a_) delete a_;} + +// void setA(A && a) { +// a_ = (A *)malloc(sizeof(a)); +// memcpy(a_, &a, sizeof(a)); +// operator delete(&a); +// } +// void setA(const A & a) {a_ = new A(a);} +//private: +// A * a_; +//}; + int main(int argc, char * argv[]) { - //PIMap v{{1, "xdsa"},{2, "blya"},{3, "\n"}}; - PIVector x{1,2}; - piCout << 1 << 2; - piCout << 1 << 2; + piCout << "pip 3.1"; + { + PIDeque v; + v.push_back(A(1)); +// v.push_back(A(2)); + } + + piCout << "std"; + { + std::vector v; + v.push_back(A(1)); +// v.push_back(A(2)); + } return 0; }