2015-04-18 01:35:36 +00:00
|
|
|
/* Algorithms for OctaSTD.
|
|
|
|
*
|
|
|
|
* This file is part of OctaSTD. See COPYING.md for futher information.
|
|
|
|
*/
|
|
|
|
|
2015-07-13 19:08:55 +00:00
|
|
|
#ifndef OSTD_ALGORITHM_HH
|
|
|
|
#define OSTD_ALGORITHM_HH
|
2015-04-18 01:35:36 +00:00
|
|
|
|
2015-04-20 18:06:47 +00:00
|
|
|
#include <math.h>
|
2015-04-18 22:12:45 +00:00
|
|
|
|
2015-07-13 19:08:55 +00:00
|
|
|
#include "ostd/functional.hh"
|
|
|
|
#include "ostd/range.hh"
|
|
|
|
#include "ostd/utility.hh"
|
|
|
|
#include "ostd/initializer_list.hh"
|
2015-04-18 01:35:36 +00:00
|
|
|
|
2015-07-13 19:07:14 +00:00
|
|
|
namespace ostd {
|
2015-04-27 18:53:48 +00:00
|
|
|
|
2015-06-03 21:54:18 +00:00
|
|
|
/* partitioning */
|
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename R, typename U>
|
2016-04-26 21:25:46 +00:00
|
|
|
inline R partition(R range, U pred) {
|
2015-06-04 21:57:06 +00:00
|
|
|
R ret = range;
|
2015-06-03 21:54:18 +00:00
|
|
|
for (; !range.empty(); range.pop_front()) {
|
|
|
|
if (pred(range.front())) {
|
2015-07-11 17:50:13 +00:00
|
|
|
detail::swap_adl(range.front(), ret.front());
|
2015-06-03 21:54:18 +00:00
|
|
|
ret.pop_front();
|
2015-04-18 20:46:31 +00:00
|
|
|
}
|
|
|
|
}
|
2015-06-03 21:54:18 +00:00
|
|
|
return ret;
|
|
|
|
}
|
2015-04-18 20:46:31 +00:00
|
|
|
|
2016-04-30 18:21:50 +00:00
|
|
|
template<typename F>
|
|
|
|
inline auto partition(F &&func) {
|
|
|
|
return [func = forward<F>(func)](auto &&obj) mutable {
|
|
|
|
return partition(forward<decltype(obj)>(obj), forward<F>(func));
|
|
|
|
};
|
2016-04-26 21:25:46 +00:00
|
|
|
}
|
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename R, typename P>
|
2016-04-26 21:25:46 +00:00
|
|
|
inline bool is_partitioned(R range, P pred) {
|
2015-06-03 21:54:18 +00:00
|
|
|
for (; !range.empty() && pred(range.front()); range.pop_front());
|
|
|
|
for (; !range.empty(); range.pop_front())
|
|
|
|
if (pred(range.front())) return false;
|
|
|
|
return true;
|
|
|
|
}
|
2015-04-20 01:06:42 +00:00
|
|
|
|
2016-04-30 18:21:50 +00:00
|
|
|
template<typename F>
|
|
|
|
inline auto is_partitioned(F &&func) {
|
|
|
|
return [func = forward<F>(func)](auto &&obj) mutable {
|
|
|
|
return is_partitioned(forward<decltype(obj)>(obj), forward<F>(func));
|
|
|
|
};
|
2016-04-26 21:25:46 +00:00
|
|
|
}
|
|
|
|
|
2015-06-03 21:54:18 +00:00
|
|
|
/* sorting */
|
2015-04-24 17:16:35 +00:00
|
|
|
|
2015-06-03 21:54:18 +00:00
|
|
|
namespace detail {
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename R, typename C>
|
2016-04-26 21:25:46 +00:00
|
|
|
static void insort(R range, C compare) {
|
2015-07-05 22:59:36 +00:00
|
|
|
RangeSize<R> rlen = range.size();
|
|
|
|
for (RangeSize<R> i = 1; i < rlen; ++i) {
|
|
|
|
RangeSize<R> j = i;
|
|
|
|
RangeValue<R> v(move(range[i]));
|
2015-06-03 21:54:18 +00:00
|
|
|
while (j > 0 && !compare(range[j - 1], v)) {
|
|
|
|
range[j] = range[j - 1];
|
|
|
|
--j;
|
2015-06-03 21:43:07 +00:00
|
|
|
}
|
2015-07-05 22:59:36 +00:00
|
|
|
range[j] = move(v);
|
2015-04-18 22:12:45 +00:00
|
|
|
}
|
2015-06-03 21:54:18 +00:00
|
|
|
}
|
2015-04-18 22:12:45 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename R, typename C>
|
2016-04-26 21:25:46 +00:00
|
|
|
static void hs_sift_down(R range, RangeSize<R> s,
|
2015-07-05 22:59:36 +00:00
|
|
|
RangeSize<R> e, C compare) {
|
|
|
|
RangeSize<R> r = s;
|
2015-06-03 21:54:18 +00:00
|
|
|
while ((r * 2 + 1) <= e) {
|
2015-07-05 22:59:36 +00:00
|
|
|
RangeSize<R> ch = r * 2 + 1;
|
|
|
|
RangeSize<R> sw = r;
|
2015-06-03 21:54:18 +00:00
|
|
|
if (compare(range[sw], range[ch]))
|
|
|
|
sw = ch;
|
|
|
|
if (((ch + 1) <= e) && compare(range[sw], range[ch + 1]))
|
|
|
|
sw = ch + 1;
|
|
|
|
if (sw != r) {
|
2015-07-11 17:50:13 +00:00
|
|
|
detail::swap_adl(range[r], range[sw]);
|
2015-06-03 21:54:18 +00:00
|
|
|
r = sw;
|
|
|
|
} else return;
|
2015-04-18 21:33:19 +00:00
|
|
|
}
|
2015-06-03 21:54:18 +00:00
|
|
|
}
|
2015-04-24 17:16:35 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename R, typename C>
|
2016-04-26 21:25:46 +00:00
|
|
|
static void heapsort(R range, C compare) {
|
2015-07-05 22:59:36 +00:00
|
|
|
RangeSize<R> len = range.size();
|
|
|
|
RangeSize<R> st = (len - 2) / 2;
|
2015-06-03 21:54:18 +00:00
|
|
|
for (;;) {
|
2015-07-05 22:59:36 +00:00
|
|
|
detail::hs_sift_down(range, st, len - 1, compare);
|
2015-06-03 21:54:18 +00:00
|
|
|
if (st-- == 0) break;
|
|
|
|
}
|
2015-07-05 22:59:36 +00:00
|
|
|
RangeSize<R> e = len - 1;
|
2015-06-03 21:54:18 +00:00
|
|
|
while (e > 0) {
|
2015-07-11 17:50:13 +00:00
|
|
|
detail::swap_adl(range[e], range[0]);
|
2015-06-03 21:54:18 +00:00
|
|
|
--e;
|
2015-07-05 22:59:36 +00:00
|
|
|
detail::hs_sift_down(range, 0, e, compare);
|
2015-06-03 21:43:07 +00:00
|
|
|
}
|
2015-04-18 21:33:19 +00:00
|
|
|
}
|
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename R, typename C>
|
2016-04-26 21:25:46 +00:00
|
|
|
static void introloop(R range, C compare, RangeSize<R> depth) {
|
2015-06-03 21:54:18 +00:00
|
|
|
if (range.size() <= 10) {
|
2015-07-05 22:59:36 +00:00
|
|
|
detail::insort(range, compare);
|
2015-06-03 21:54:18 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (depth == 0) {
|
2015-07-05 22:59:36 +00:00
|
|
|
detail::heapsort(range, compare);
|
2015-06-03 21:54:18 +00:00
|
|
|
return;
|
|
|
|
}
|
2015-07-11 17:50:13 +00:00
|
|
|
detail::swap_adl(range[range.size() / 2], range.back());
|
2015-07-05 22:59:36 +00:00
|
|
|
RangeSize<R> pi = 0;
|
2015-06-09 21:56:40 +00:00
|
|
|
R pr = range;
|
|
|
|
pr.pop_back();
|
|
|
|
for (; !pr.empty(); pr.pop_front()) {
|
|
|
|
if (compare(pr.front(), range.back()))
|
2015-07-11 17:50:13 +00:00
|
|
|
detail::swap_adl(pr.front(), range[pi++]);
|
2015-06-09 21:56:40 +00:00
|
|
|
}
|
2015-07-11 17:50:13 +00:00
|
|
|
detail::swap_adl(range[pi], range.back());
|
2015-07-05 22:59:36 +00:00
|
|
|
detail::introloop(range.slice(0, pi), compare, depth - 1);
|
|
|
|
detail::introloop(range.slice(pi + 1, range.size()), compare,
|
2015-06-09 21:56:40 +00:00
|
|
|
depth - 1);
|
2015-04-18 19:20:40 +00:00
|
|
|
}
|
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename R, typename C>
|
2016-04-26 21:25:46 +00:00
|
|
|
inline void introsort(R range, C compare) {
|
2015-07-05 22:59:36 +00:00
|
|
|
detail::introloop(range, compare, RangeSize<R>(2
|
2015-06-03 21:54:18 +00:00
|
|
|
* (log(range.size()) / log(2))));
|
2015-04-18 19:20:40 +00:00
|
|
|
}
|
2015-06-03 21:54:18 +00:00
|
|
|
} /* namespace detail */
|
2015-04-18 23:02:38 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename R, typename C>
|
2016-04-29 16:34:46 +00:00
|
|
|
inline R sort_cmp(R range, C compare) {
|
2015-07-05 22:59:36 +00:00
|
|
|
detail::introsort(range, compare);
|
2016-04-29 16:34:46 +00:00
|
|
|
return range;
|
|
|
|
}
|
2016-04-30 18:21:50 +00:00
|
|
|
template<typename C>
|
|
|
|
inline auto sort_cmp(C &&compare) {
|
|
|
|
return [compare = forward<C>(compare)](auto &&obj) mutable {
|
|
|
|
return sort_cmp(forward<decltype(obj)>(obj), forward<C>(compare));
|
2016-04-30 17:24:17 +00:00
|
|
|
};
|
2015-06-03 21:54:18 +00:00
|
|
|
}
|
2015-04-24 17:16:35 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename R>
|
2016-04-29 16:34:46 +00:00
|
|
|
inline R sort(R range) {
|
|
|
|
return sort_cmp(range, Less<RangeValue<R>>());
|
|
|
|
}
|
|
|
|
inline auto sort() {
|
2016-04-30 18:21:50 +00:00
|
|
|
return [](auto &&obj) { return sort(forward<decltype(obj)>(obj)); };
|
2015-06-03 21:54:18 +00:00
|
|
|
}
|
2015-04-18 23:02:38 +00:00
|
|
|
|
2015-06-03 21:54:18 +00:00
|
|
|
/* min/max(_element) */
|
2015-04-18 23:02:38 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
|
|
|
inline const T &min(const T &a, const T &b) {
|
2015-06-03 21:54:18 +00:00
|
|
|
return (a < b) ? a : b;
|
|
|
|
}
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T, typename C>
|
2016-04-29 16:30:32 +00:00
|
|
|
inline const T &min_cmp(const T &a, const T &b, C compare) {
|
2015-06-03 21:54:18 +00:00
|
|
|
return compare(a, b) ? a : b;
|
|
|
|
}
|
2015-04-18 23:02:38 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
|
|
|
inline const T &max(const T &a, const T &b) {
|
2015-06-03 21:54:18 +00:00
|
|
|
return (a < b) ? b : a;
|
|
|
|
}
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T, typename C>
|
2016-04-29 16:30:32 +00:00
|
|
|
inline const T &max_cmp(const T &a, const T &b, C compare) {
|
2015-06-03 21:54:18 +00:00
|
|
|
return compare(a, b) ? b : a;
|
|
|
|
}
|
2015-04-18 23:02:38 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename R>
|
|
|
|
inline R min_element(R range) {
|
|
|
|
R r = range;
|
2015-06-03 21:54:18 +00:00
|
|
|
for (; !range.empty(); range.pop_front())
|
2015-07-13 19:07:14 +00:00
|
|
|
if (ostd::min(r.front(), range.front()) == range.front())
|
2015-06-03 21:54:18 +00:00
|
|
|
r = range;
|
|
|
|
return r;
|
|
|
|
}
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename R, typename C>
|
2016-04-29 16:30:32 +00:00
|
|
|
inline R min_element_cmp(R range, C compare) {
|
2015-06-04 21:57:06 +00:00
|
|
|
R r = range;
|
2015-06-03 21:54:18 +00:00
|
|
|
for (; !range.empty(); range.pop_front())
|
2016-04-29 16:30:32 +00:00
|
|
|
if (ostd::min_cmp(r.front(), range.front(), compare) == range.front())
|
2015-06-03 21:54:18 +00:00
|
|
|
r = range;
|
|
|
|
return r;
|
|
|
|
}
|
2016-04-29 16:30:32 +00:00
|
|
|
inline auto min_element() {
|
2016-04-30 18:21:50 +00:00
|
|
|
return [](auto &&obj) { return min_element(forward<decltype(obj)>(obj)); };
|
2016-04-29 16:30:32 +00:00
|
|
|
}
|
2016-04-30 18:21:50 +00:00
|
|
|
template<typename C>
|
|
|
|
inline auto min_element_cmp(C &&compare) {
|
|
|
|
return [compare = forward<C>(compare)](auto &&obj) mutable {
|
|
|
|
return min_element_cmp(forward<decltype(obj)>(obj), forward<C>(compare));
|
2016-04-30 17:24:17 +00:00
|
|
|
};
|
2016-04-29 16:30:32 +00:00
|
|
|
}
|
2015-04-18 23:02:38 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename R>
|
|
|
|
inline R max_element(R range) {
|
|
|
|
R r = range;
|
2015-06-03 21:54:18 +00:00
|
|
|
for (; !range.empty(); range.pop_front())
|
2015-07-13 19:07:14 +00:00
|
|
|
if (ostd::max(r.front(), range.front()) == range.front())
|
2015-06-03 21:54:18 +00:00
|
|
|
r = range;
|
|
|
|
return r;
|
|
|
|
}
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename R, typename C>
|
2016-04-29 16:30:32 +00:00
|
|
|
inline R max_element_cmp(R range, C compare) {
|
2015-06-04 21:57:06 +00:00
|
|
|
R r = range;
|
2015-06-03 21:54:18 +00:00
|
|
|
for (; !range.empty(); range.pop_front())
|
2016-04-29 16:30:32 +00:00
|
|
|
if (ostd::max_cmp(r.front(), range.front(), compare) == range.front())
|
2015-06-03 21:54:18 +00:00
|
|
|
r = range;
|
|
|
|
return r;
|
|
|
|
}
|
2016-04-29 16:30:32 +00:00
|
|
|
inline auto max_element() {
|
2016-04-30 18:21:50 +00:00
|
|
|
return [](auto &&obj) { return max_element(forward<decltype(obj)>(obj)); };
|
2016-04-29 16:30:32 +00:00
|
|
|
}
|
2016-04-30 18:21:50 +00:00
|
|
|
template<typename C>
|
|
|
|
inline auto max_element_cmp(C &&compare) {
|
|
|
|
return [compare = forward<C>(compare)](auto &&obj) mutable {
|
|
|
|
return max_element_cmp(forward<decltype(obj)>(obj), forward<C>(compare));
|
2016-04-30 17:24:17 +00:00
|
|
|
};
|
2016-04-29 16:30:32 +00:00
|
|
|
}
|
2015-04-20 01:21:27 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
|
|
|
inline T min(std::initializer_list<T> il) {
|
2015-07-13 19:07:14 +00:00
|
|
|
return ostd::min_element(ostd::iter(il)).front();
|
2015-06-03 21:54:18 +00:00
|
|
|
}
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T, typename C>
|
2016-04-29 16:30:32 +00:00
|
|
|
inline T min_cmp(std::initializer_list<T> il, C compare) {
|
|
|
|
return ostd::min_element_cmp(ostd::iter(il), compare).front();
|
2015-06-03 21:54:18 +00:00
|
|
|
}
|
2015-04-20 01:14:55 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
|
|
|
inline T max(std::initializer_list<T> il) {
|
2015-07-13 19:07:14 +00:00
|
|
|
return ostd::max_element(ostd::iter(il)).front();
|
2015-06-03 21:54:18 +00:00
|
|
|
}
|
2015-04-26 17:45:10 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T, typename C>
|
2016-04-29 16:30:32 +00:00
|
|
|
inline T max_cmp(std::initializer_list<T> il, C compare) {
|
|
|
|
return ostd::max_element_cmp(ostd::iter(il), compare).front();
|
2015-06-03 21:54:18 +00:00
|
|
|
}
|
2015-04-26 17:45:10 +00:00
|
|
|
|
2015-06-03 21:54:18 +00:00
|
|
|
/* clamp */
|
2015-04-26 17:45:10 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T, typename U>
|
|
|
|
inline T clamp(const T &v, const U &lo, const U &hi) {
|
2015-07-13 19:07:14 +00:00
|
|
|
return ostd::max(T(lo), ostd::min(v, T(hi)));
|
2015-06-03 21:54:18 +00:00
|
|
|
}
|
2015-04-24 17:16:35 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T, typename U, typename C>
|
|
|
|
inline T clamp(const T &v, const U &lo, const U &hi, C compare) {
|
2016-04-29 16:30:32 +00:00
|
|
|
return ostd::max_cmp(T(lo), ostd::min_cmp(v, T(hi), compare), compare);
|
2015-06-03 21:54:18 +00:00
|
|
|
}
|
2015-04-20 01:21:27 +00:00
|
|
|
|
2015-07-11 15:07:52 +00:00
|
|
|
/* lexicographical compare */
|
|
|
|
|
|
|
|
template<typename R1, typename R2>
|
2016-04-26 21:25:46 +00:00
|
|
|
inline bool lexicographical_compare(R1 range1, R2 range2) {
|
2015-07-11 15:07:52 +00:00
|
|
|
while (!range1.empty() && !range2.empty()) {
|
|
|
|
if (range1.front() < range2.front()) return true;
|
|
|
|
if (range2.front() < range1.front()) return false;
|
|
|
|
range1.pop_front();
|
|
|
|
range2.pop_front();
|
|
|
|
}
|
|
|
|
return (range1.empty() && !range2.empty());
|
|
|
|
}
|
2016-04-30 18:21:50 +00:00
|
|
|
template<typename R>
|
|
|
|
inline auto lexicographical_compare(R &&range) {
|
|
|
|
return [range = forward<R>(range)](auto &&obj) mutable {
|
|
|
|
return lexicographical_compare(forward<decltype(obj)>(obj), forward<R>(range));
|
2016-04-30 17:24:17 +00:00
|
|
|
};
|
2016-04-29 16:30:32 +00:00
|
|
|
}
|
2015-07-11 15:07:52 +00:00
|
|
|
|
|
|
|
template<typename R1, typename R2, typename C>
|
2016-04-29 16:30:32 +00:00
|
|
|
inline bool lexicographical_compare_cmp(R1 range1, R2 range2, C compare) {
|
2015-07-11 15:07:52 +00:00
|
|
|
while (!range1.empty() && !range2.empty()) {
|
|
|
|
if (compare(range1.front(), range2.front())) return true;
|
|
|
|
if (compare(range2.front(), range1.front())) return false;
|
|
|
|
range1.pop_front();
|
|
|
|
range2.pop_front();
|
|
|
|
}
|
|
|
|
return (range1.empty() && !range2.empty());
|
|
|
|
}
|
2016-04-29 16:30:32 +00:00
|
|
|
template<typename R, typename C>
|
2016-04-30 18:21:50 +00:00
|
|
|
inline auto lexicographical_compare_cmp(R &&range, C &&compare) {
|
|
|
|
return [range = forward<R>(range), compare = forward<C>(compare)](auto &&obj) mutable {
|
|
|
|
return lexicographical_compare_cmp(forward<decltype(obj)>(obj),
|
|
|
|
forward<R>(range), forward<C>(compare));
|
2016-04-29 16:30:32 +00:00
|
|
|
};
|
|
|
|
}
|
2015-07-11 15:07:52 +00:00
|
|
|
|
2015-06-03 21:54:18 +00:00
|
|
|
/* algos that don't change the range */
|
2015-04-20 01:21:27 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename R, typename F>
|
2016-04-26 21:25:46 +00:00
|
|
|
inline F for_each(R range, F func) {
|
2015-06-03 21:54:18 +00:00
|
|
|
for (; !range.empty(); range.pop_front())
|
|
|
|
func(range.front());
|
2015-07-05 22:59:36 +00:00
|
|
|
return move(func);
|
2015-06-03 21:54:18 +00:00
|
|
|
}
|
2015-04-20 01:21:27 +00:00
|
|
|
|
2016-04-30 18:21:50 +00:00
|
|
|
template<typename F>
|
|
|
|
inline auto for_each(F &&func) {
|
|
|
|
return [func = forward<F>(func)](auto &&obj) mutable {
|
|
|
|
return for_each(forward<decltype(obj)>(obj), forward<F>(func));
|
2016-04-26 21:25:46 +00:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename R, typename P>
|
2016-04-26 21:25:46 +00:00
|
|
|
inline bool all_of(R range, P pred) {
|
2015-06-03 21:54:18 +00:00
|
|
|
for (; !range.empty(); range.pop_front())
|
|
|
|
if (!pred(range.front())) return false;
|
|
|
|
return true;
|
|
|
|
}
|
2015-04-21 01:33:58 +00:00
|
|
|
|
2016-04-30 18:21:50 +00:00
|
|
|
template<typename F>
|
|
|
|
inline auto all_of(F &&func) {
|
|
|
|
return [func = forward<F>(func)](auto &&obj) mutable {
|
|
|
|
return all_of(forward<decltype(obj)>(obj), forward<F>(func));
|
|
|
|
};
|
2016-04-26 21:25:46 +00:00
|
|
|
}
|
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename R, typename P>
|
2016-04-26 21:25:46 +00:00
|
|
|
inline bool any_of(R range, P pred) {
|
2015-06-03 21:54:18 +00:00
|
|
|
for (; !range.empty(); range.pop_front())
|
|
|
|
if (pred(range.front())) return true;
|
|
|
|
return false;
|
|
|
|
}
|
2015-04-21 01:33:58 +00:00
|
|
|
|
2016-04-30 18:21:50 +00:00
|
|
|
template<typename F>
|
|
|
|
inline auto any_of(F &&func) {
|
|
|
|
return [func = forward<F>(func)](auto &&obj) mutable {
|
|
|
|
return any_of(forward<decltype(obj)>(obj), forward<F>(func));
|
|
|
|
};
|
2016-04-26 21:25:46 +00:00
|
|
|
}
|
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename R, typename P>
|
2016-04-26 21:25:46 +00:00
|
|
|
inline bool none_of(R range, P pred) {
|
2015-06-03 21:54:18 +00:00
|
|
|
for (; !range.empty(); range.pop_front())
|
|
|
|
if (pred(range.front())) return false;
|
|
|
|
return true;
|
|
|
|
}
|
2015-04-21 01:33:58 +00:00
|
|
|
|
2016-04-30 18:21:50 +00:00
|
|
|
template<typename F>
|
|
|
|
inline auto none_of(F &&func) {
|
|
|
|
return [func = forward<F>(func)](auto &&obj) mutable {
|
|
|
|
return none_of(forward<decltype(obj)>(obj), forward<F>(func));
|
|
|
|
};
|
2016-04-26 21:25:46 +00:00
|
|
|
}
|
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename R, typename T>
|
2016-04-26 21:25:46 +00:00
|
|
|
inline R find(R range, const T &v) {
|
2015-06-03 21:54:18 +00:00
|
|
|
for (; !range.empty(); range.pop_front())
|
|
|
|
if (range.front() == v)
|
|
|
|
break;
|
|
|
|
return range;
|
|
|
|
}
|
2015-04-21 01:33:58 +00:00
|
|
|
|
2016-04-30 18:21:50 +00:00
|
|
|
template<typename T>
|
|
|
|
inline auto find(T &&v) {
|
|
|
|
return [v = forward<T>(v)](auto &&obj) mutable {
|
|
|
|
return find(forward<decltype(obj)>(obj), forward<T>(v));
|
|
|
|
};
|
2016-04-26 21:25:46 +00:00
|
|
|
}
|
|
|
|
|
2015-08-16 18:35:06 +00:00
|
|
|
template<typename R, typename T>
|
2016-04-26 21:25:46 +00:00
|
|
|
inline R find_last(R range, const T &v) {
|
2015-08-16 18:35:06 +00:00
|
|
|
range = find(range, v);
|
|
|
|
if (!range.empty()) for (;;) {
|
|
|
|
R prev = range;
|
|
|
|
prev.pop_front();
|
|
|
|
R r = find(prev, v);
|
|
|
|
if (r.empty())
|
|
|
|
break;
|
2015-09-04 17:46:28 +00:00
|
|
|
range = r;
|
2015-08-16 18:35:06 +00:00
|
|
|
}
|
|
|
|
return range;
|
|
|
|
}
|
|
|
|
|
2016-04-30 18:21:50 +00:00
|
|
|
template<typename T>
|
|
|
|
inline auto find_last(T &&v) {
|
|
|
|
return [v = forward<T>(v)](auto &&obj) mutable {
|
|
|
|
return find_last(forward<decltype(obj)>(obj), forward<T>(v));
|
|
|
|
};
|
2016-04-26 21:25:46 +00:00
|
|
|
}
|
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename R, typename P>
|
2016-04-26 21:25:46 +00:00
|
|
|
inline R find_if(R range, P pred) {
|
2015-06-03 21:54:18 +00:00
|
|
|
for (; !range.empty(); range.pop_front())
|
|
|
|
if (pred(range.front()))
|
|
|
|
break;
|
|
|
|
return range;
|
|
|
|
}
|
2015-04-21 01:33:58 +00:00
|
|
|
|
2016-04-30 18:21:50 +00:00
|
|
|
template<typename F>
|
|
|
|
inline auto find_if(F &&func) {
|
|
|
|
return [func = forward<F>(func)](auto &&obj) mutable {
|
|
|
|
return find_if(forward<decltype(obj)>(obj), forward<F>(func));
|
|
|
|
};
|
2016-04-26 21:25:46 +00:00
|
|
|
}
|
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename R, typename P>
|
2016-04-26 21:25:46 +00:00
|
|
|
inline R find_if_not(R range, P pred) {
|
2015-06-03 21:54:18 +00:00
|
|
|
for (; !range.empty(); range.pop_front())
|
|
|
|
if (!pred(range.front()))
|
|
|
|
break;
|
|
|
|
return range;
|
|
|
|
}
|
2015-04-21 01:33:58 +00:00
|
|
|
|
2016-04-30 18:21:50 +00:00
|
|
|
template<typename F>
|
|
|
|
inline auto find_if_not(F &&func) {
|
|
|
|
return [func = forward<F>(func)](auto &&obj) mutable {
|
|
|
|
return find_if_not(forward<decltype(obj)>(obj), forward<F>(func));
|
|
|
|
};
|
2016-04-26 21:25:46 +00:00
|
|
|
}
|
|
|
|
|
2015-08-11 00:32:24 +00:00
|
|
|
template<typename R1, typename R2, typename C>
|
2016-04-29 16:30:32 +00:00
|
|
|
inline R1 find_one_of_cmp(R1 range, R2 values, C compare) {
|
2015-08-11 00:32:24 +00:00
|
|
|
for (; !range.empty(); range.pop_front())
|
|
|
|
for (R2 rv = values; !rv.empty(); rv.pop_front())
|
|
|
|
if (compare(range.front(), rv.front()))
|
|
|
|
return range;
|
|
|
|
return range;
|
|
|
|
}
|
2016-04-29 16:30:32 +00:00
|
|
|
template<typename R, typename C>
|
2016-04-30 18:21:50 +00:00
|
|
|
inline auto find_one_of_cmp(R &&values, C &&compare) {
|
|
|
|
return [values = forward<R>(values), compare = forward<C>(compare)](auto &&obj) mutable {
|
|
|
|
return find_one_of_cmp(forward<decltype(obj)>(obj),
|
|
|
|
forward<R>(values), forward<C>(compare));
|
2016-04-29 16:30:32 +00:00
|
|
|
};
|
|
|
|
}
|
2015-08-11 00:32:24 +00:00
|
|
|
|
|
|
|
template<typename R1, typename R2>
|
2016-04-26 21:25:46 +00:00
|
|
|
inline R1 find_one_of(R1 range, R2 values) {
|
2015-08-11 00:32:24 +00:00
|
|
|
for (; !range.empty(); range.pop_front())
|
|
|
|
for (R2 rv = values; !rv.empty(); rv.pop_front())
|
|
|
|
if (range.front() == rv.front())
|
|
|
|
return range;
|
|
|
|
return range;
|
|
|
|
}
|
2016-04-30 18:21:50 +00:00
|
|
|
template<typename R>
|
|
|
|
inline auto find_one_of(R &&values) {
|
|
|
|
return [values = forward<R>(values)](auto &&obj) mutable {
|
|
|
|
return find_one_of(forward<decltype(obj)>(obj), forward<R>(values));
|
2016-04-29 16:30:32 +00:00
|
|
|
};
|
|
|
|
}
|
2015-08-11 00:32:24 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename R, typename T>
|
2016-04-26 21:25:46 +00:00
|
|
|
inline RangeSize<R> count(R range, const T &v) {
|
2015-06-04 21:57:06 +00:00
|
|
|
RangeSize<R> ret = 0;
|
2015-06-03 21:54:18 +00:00
|
|
|
for (; !range.empty(); range.pop_front())
|
|
|
|
if (range.front() == v)
|
|
|
|
++ret;
|
|
|
|
return ret;
|
|
|
|
}
|
2015-04-21 01:33:58 +00:00
|
|
|
|
2016-04-30 18:21:50 +00:00
|
|
|
template<typename T>
|
|
|
|
inline auto count(T &&v) {
|
|
|
|
return [v = forward<T>(v)](auto &&obj) mutable {
|
|
|
|
return count(forward<decltype(obj)>(obj), forward<T>(v));
|
|
|
|
};
|
2016-04-26 21:25:46 +00:00
|
|
|
}
|
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename R, typename P>
|
2016-04-26 21:25:46 +00:00
|
|
|
inline RangeSize<R> count_if(R range, P pred) {
|
2015-06-04 21:57:06 +00:00
|
|
|
RangeSize<R> ret = 0;
|
2015-06-03 21:54:18 +00:00
|
|
|
for (; !range.empty(); range.pop_front())
|
|
|
|
if (pred(range.front()))
|
|
|
|
++ret;
|
|
|
|
return ret;
|
|
|
|
}
|
2015-04-21 01:33:58 +00:00
|
|
|
|
2016-04-30 18:21:50 +00:00
|
|
|
template<typename F>
|
|
|
|
inline auto count_if(F &&func) {
|
|
|
|
return [func = forward<F>(func)](auto &&obj) mutable {
|
|
|
|
return count_if(forward<decltype(obj)>(obj), forward<F>(func));
|
|
|
|
};
|
2016-04-26 21:25:46 +00:00
|
|
|
}
|
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename R, typename P>
|
2016-04-26 21:25:46 +00:00
|
|
|
inline RangeSize<R> count_if_not(R range, P pred) {
|
2015-06-04 21:57:06 +00:00
|
|
|
RangeSize<R> ret = 0;
|
2015-06-03 21:54:18 +00:00
|
|
|
for (; !range.empty(); range.pop_front())
|
|
|
|
if (!pred(range.front()))
|
|
|
|
++ret;
|
|
|
|
return ret;
|
|
|
|
}
|
2015-04-24 17:16:35 +00:00
|
|
|
|
2016-04-30 18:21:50 +00:00
|
|
|
template<typename F>
|
|
|
|
inline auto count_if_not(F &&func) {
|
|
|
|
return [func = forward<F>(func)](auto &&obj) mutable {
|
|
|
|
return count_if_not(forward<decltype(obj)>(obj), forward<F>(func));
|
|
|
|
};
|
2016-04-26 21:25:46 +00:00
|
|
|
}
|
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename R>
|
2016-04-26 21:25:46 +00:00
|
|
|
inline bool equal(R range1, R range2) {
|
2015-06-03 21:54:18 +00:00
|
|
|
for (; !range1.empty(); range1.pop_front()) {
|
|
|
|
if (range2.empty() || (range1.front() != range2.front()))
|
|
|
|
return false;
|
|
|
|
range2.pop_front();
|
2015-04-21 16:56:36 +00:00
|
|
|
}
|
2015-06-03 21:54:18 +00:00
|
|
|
return range2.empty();
|
|
|
|
}
|
2015-04-21 16:56:36 +00:00
|
|
|
|
2016-04-30 18:21:50 +00:00
|
|
|
template<typename R>
|
|
|
|
inline auto equal(R &&range) {
|
|
|
|
return [range = forward<R>(range)](auto &&obj) mutable {
|
|
|
|
return equal(forward<decltype(obj)>(obj), forward<R>(range));
|
|
|
|
};
|
2016-04-26 21:25:46 +00:00
|
|
|
}
|
|
|
|
|
2015-08-13 22:25:39 +00:00
|
|
|
template<typename R>
|
|
|
|
R slice_until(R range1, R range2) {
|
|
|
|
return range1.slice(0, range1.distance_front(range2));
|
|
|
|
}
|
|
|
|
|
2016-04-30 18:21:50 +00:00
|
|
|
template<typename R>
|
|
|
|
inline auto slice_until(R &&range) {
|
|
|
|
return [range = forward<R>(range)](auto &&obj) mutable {
|
|
|
|
return slice_until(forward<decltype(obj)>(obj), forward<R>(range));
|
|
|
|
};
|
2016-04-26 21:25:46 +00:00
|
|
|
}
|
|
|
|
|
2015-06-03 21:54:18 +00:00
|
|
|
/* algos that modify ranges or work with output ranges */
|
2015-04-21 16:56:36 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename R1, typename R2>
|
2016-04-26 21:25:46 +00:00
|
|
|
inline R2 copy(R1 irange, R2 orange) {
|
2015-06-03 21:54:18 +00:00
|
|
|
for (; !irange.empty(); irange.pop_front())
|
|
|
|
orange.put(irange.front());
|
|
|
|
return orange;
|
|
|
|
}
|
2015-04-21 16:56:36 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename R1, typename R2, typename P>
|
2016-04-26 21:25:46 +00:00
|
|
|
inline R2 copy_if(R1 irange, R2 orange, P pred) {
|
2015-06-03 21:54:18 +00:00
|
|
|
for (; !irange.empty(); irange.pop_front())
|
|
|
|
if (pred(irange.front()))
|
|
|
|
orange.put(irange.front());
|
|
|
|
return orange;
|
|
|
|
}
|
2015-04-21 16:56:36 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename R1, typename R2, typename P>
|
2016-04-26 21:25:46 +00:00
|
|
|
inline R2 copy_if_not(R1 irange, R2 orange, P pred) {
|
2015-06-03 21:54:18 +00:00
|
|
|
for (; !irange.empty(); irange.pop_front())
|
|
|
|
if (!pred(irange.front()))
|
|
|
|
orange.put(irange.front());
|
|
|
|
return orange;
|
|
|
|
}
|
2015-04-21 16:56:36 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename R1, typename R2>
|
2016-04-26 21:25:46 +00:00
|
|
|
inline R2 move(R1 irange, R2 orange) {
|
2015-06-03 21:54:18 +00:00
|
|
|
for (; !irange.empty(); irange.pop_front())
|
2015-07-05 22:59:36 +00:00
|
|
|
orange.put(move(irange.front()));
|
2015-06-03 21:54:18 +00:00
|
|
|
return orange;
|
|
|
|
}
|
2015-04-21 16:56:36 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename R>
|
2016-04-26 21:25:46 +00:00
|
|
|
inline void reverse(R range) {
|
2015-06-03 21:54:18 +00:00
|
|
|
while (!range.empty()) {
|
2015-07-11 17:50:13 +00:00
|
|
|
detail::swap_adl(range.front(), range.back());
|
2015-06-03 21:54:18 +00:00
|
|
|
range.pop_front();
|
|
|
|
range.pop_back();
|
2015-04-21 16:56:36 +00:00
|
|
|
}
|
2015-06-03 21:54:18 +00:00
|
|
|
}
|
2015-04-21 16:56:36 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename R1, typename R2>
|
2016-04-26 21:25:46 +00:00
|
|
|
inline R2 reverse_copy(R1 irange, R2 orange) {
|
2015-06-03 21:54:18 +00:00
|
|
|
for (; !irange.empty(); irange.pop_back())
|
|
|
|
orange.put(irange.back());
|
|
|
|
return orange;
|
|
|
|
}
|
2015-04-21 16:56:36 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename R, typename T>
|
2016-04-26 21:25:46 +00:00
|
|
|
inline void fill(R range, const T &v) {
|
2015-06-03 21:54:18 +00:00
|
|
|
for (; !range.empty(); range.pop_front())
|
|
|
|
range.front() = v;
|
|
|
|
}
|
2015-04-21 22:54:09 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename R, typename F>
|
2016-04-26 21:25:46 +00:00
|
|
|
inline void generate(R range, F gen) {
|
2015-06-03 21:54:18 +00:00
|
|
|
for (; !range.empty(); range.pop_front())
|
|
|
|
range.front() = gen();
|
|
|
|
}
|
2015-05-23 17:44:06 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename R1, typename R2>
|
2016-04-26 21:25:46 +00:00
|
|
|
inline Pair<R1, R2> swap_ranges(R1 range1, R2 range2) {
|
2015-06-03 21:54:18 +00:00
|
|
|
while (!range1.empty() && !range2.empty()) {
|
2015-07-11 17:50:13 +00:00
|
|
|
detail::swap_adl(range1.front(), range2.front());
|
2015-06-03 21:54:18 +00:00
|
|
|
range1.pop_front();
|
|
|
|
range2.pop_front();
|
2015-05-25 19:46:49 +00:00
|
|
|
}
|
2015-07-13 19:07:14 +00:00
|
|
|
return ostd::make_pair(range1, range2);
|
2015-06-03 21:54:18 +00:00
|
|
|
}
|
2015-05-25 19:46:49 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename R, typename T>
|
2016-04-26 21:25:46 +00:00
|
|
|
inline void iota(R range, T value) {
|
2015-06-03 21:54:18 +00:00
|
|
|
for (; !range.empty(); range.pop_front())
|
|
|
|
range.front() = value++;
|
|
|
|
}
|
2015-05-25 19:46:49 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename R, typename T>
|
2016-04-26 21:25:46 +00:00
|
|
|
inline T foldl(R range, T init) {
|
2015-06-03 21:54:18 +00:00
|
|
|
for (; !range.empty(); range.pop_front())
|
|
|
|
init = init + range.front();
|
|
|
|
return init;
|
|
|
|
}
|
2015-05-25 19:46:49 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename R, typename T, typename F>
|
2016-04-29 16:47:04 +00:00
|
|
|
inline T foldl_f(R range, T init, F func) {
|
2015-06-03 21:54:18 +00:00
|
|
|
for (; !range.empty(); range.pop_front())
|
|
|
|
init = func(init, range.front());
|
|
|
|
return init;
|
|
|
|
}
|
2015-05-25 19:46:49 +00:00
|
|
|
|
2016-04-30 18:21:50 +00:00
|
|
|
template<typename T>
|
|
|
|
inline auto foldl(T &&init) {
|
|
|
|
return [init = forward<T>(init)](auto &&obj) mutable {
|
|
|
|
return foldl(forward<decltype(obj)>(obj), forward<T>(init));
|
|
|
|
};
|
2016-04-26 21:25:46 +00:00
|
|
|
}
|
2016-04-30 18:21:50 +00:00
|
|
|
template<typename T, typename F>
|
|
|
|
inline auto foldl_f(T &&init, F &&func) {
|
|
|
|
return [init = forward<T>(init), func = forward<F>(func)](auto &&obj) mutable {
|
|
|
|
return foldl_f(forward<decltype(obj)>(obj), forward<T>(init), forward<F>(func));
|
2016-04-29 16:47:04 +00:00
|
|
|
};
|
|
|
|
}
|
2016-04-26 21:25:46 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename R, typename T>
|
2016-04-26 21:25:46 +00:00
|
|
|
inline T foldr(R range, T init) {
|
2015-06-03 21:54:18 +00:00
|
|
|
for (; !range.empty(); range.pop_back())
|
|
|
|
init = init + range.back();
|
|
|
|
return init;
|
|
|
|
}
|
2015-05-23 17:44:06 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename R, typename T, typename F>
|
2016-04-29 16:47:04 +00:00
|
|
|
inline T foldr_f(R range, T init, F func) {
|
2015-06-03 21:54:18 +00:00
|
|
|
for (; !range.empty(); range.pop_back())
|
|
|
|
init = func(init, range.back());
|
|
|
|
return init;
|
|
|
|
}
|
2015-05-23 17:55:22 +00:00
|
|
|
|
2016-04-30 18:21:50 +00:00
|
|
|
template<typename T>
|
|
|
|
inline auto foldr(T &&init) {
|
|
|
|
return [init = forward<T>(init)](auto &&obj) mutable {
|
|
|
|
return foldr(forward<decltype(obj)>(obj), forward<T>(init));
|
|
|
|
};
|
2016-04-26 21:25:46 +00:00
|
|
|
}
|
2016-04-30 18:21:50 +00:00
|
|
|
template<typename T, typename F>
|
|
|
|
inline auto foldr_f(T &&init, F &&func) {
|
|
|
|
return [init = forward<T>(init), func = forward<F>(func)](auto &&obj) mutable {
|
|
|
|
return foldr_f(forward<decltype(obj)>(obj), forward<T>(init), forward<F>(func));
|
2016-04-29 16:47:04 +00:00
|
|
|
};
|
|
|
|
}
|
2016-04-26 21:25:46 +00:00
|
|
|
|
2015-06-07 03:10:08 +00:00
|
|
|
template<typename T, typename F, typename R>
|
2015-06-03 21:54:18 +00:00
|
|
|
struct MapRange: InputRange<
|
2015-07-05 22:59:36 +00:00
|
|
|
MapRange<T, F, R>, RangeCategory<T>, R, R, RangeSize<T>
|
2015-06-03 21:54:18 +00:00
|
|
|
> {
|
|
|
|
private:
|
2015-06-04 21:57:06 +00:00
|
|
|
T p_range;
|
2016-05-08 23:07:25 +00:00
|
|
|
Decay<F> p_func;
|
2015-05-29 22:32:25 +00:00
|
|
|
|
2015-06-03 21:54:18 +00:00
|
|
|
public:
|
2015-06-29 22:33:20 +00:00
|
|
|
MapRange() = delete;
|
2016-04-30 16:58:37 +00:00
|
|
|
template<typename FF>
|
|
|
|
MapRange(const T &range, FF &&func):
|
|
|
|
p_range(range), p_func(forward<FF>(func)) {}
|
2015-06-03 21:54:18 +00:00
|
|
|
MapRange(const MapRange &it):
|
|
|
|
p_range(it.p_range), p_func(it.p_func) {}
|
|
|
|
MapRange(MapRange &&it):
|
|
|
|
p_range(move(it.p_range)), p_func(move(it.p_func)) {}
|
2015-05-29 22:32:25 +00:00
|
|
|
|
2015-06-03 21:54:18 +00:00
|
|
|
MapRange &operator=(const MapRange &v) {
|
|
|
|
p_range = v.p_range;
|
|
|
|
p_func = v.p_func;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
MapRange &operator=(MapRange &&v) {
|
|
|
|
p_range = move(v.p_range);
|
|
|
|
p_func = move(v.p_func);
|
|
|
|
return *this;
|
|
|
|
}
|
2015-05-23 17:55:22 +00:00
|
|
|
|
2015-06-03 21:54:18 +00:00
|
|
|
bool empty() const { return p_range.empty(); }
|
2015-07-05 22:59:36 +00:00
|
|
|
RangeSize<T> size() const { return p_range.size(); }
|
2015-05-29 18:52:20 +00:00
|
|
|
|
2015-06-03 21:54:18 +00:00
|
|
|
bool equals_front(const MapRange &r) const {
|
|
|
|
return p_range.equals_front(r.p_range);
|
|
|
|
}
|
|
|
|
bool equals_back(const MapRange &r) const {
|
|
|
|
return p_range.equals_front(r.p_range);
|
|
|
|
}
|
2015-05-23 17:44:06 +00:00
|
|
|
|
2015-07-05 22:59:36 +00:00
|
|
|
RangeDifference<T> distance_front(const MapRange &r) const {
|
2015-06-03 21:54:18 +00:00
|
|
|
return p_range.distance_front(r.p_range);
|
|
|
|
}
|
2015-07-05 22:59:36 +00:00
|
|
|
RangeDifference<T> distance_back(const MapRange &r) const {
|
2015-06-03 21:54:18 +00:00
|
|
|
return p_range.distance_back(r.p_range);
|
|
|
|
}
|
2015-05-29 18:52:20 +00:00
|
|
|
|
2015-06-03 21:54:18 +00:00
|
|
|
bool pop_front() { return p_range.pop_front(); }
|
|
|
|
bool pop_back() { return p_range.pop_back(); }
|
2015-05-23 17:59:14 +00:00
|
|
|
|
2015-06-03 21:54:18 +00:00
|
|
|
bool push_front() { return p_range.pop_front(); }
|
|
|
|
bool push_back() { return p_range.push_back(); }
|
2015-05-23 17:55:22 +00:00
|
|
|
|
2015-07-05 22:59:36 +00:00
|
|
|
RangeSize<T> pop_front_n(RangeSize<T> n) {
|
2015-06-03 21:54:18 +00:00
|
|
|
p_range.pop_front_n(n);
|
|
|
|
}
|
2015-07-05 22:59:36 +00:00
|
|
|
RangeSize<T> pop_back_n(RangeSize<T> n) {
|
2015-06-03 21:54:18 +00:00
|
|
|
p_range.pop_back_n(n);
|
|
|
|
}
|
2015-05-23 17:44:06 +00:00
|
|
|
|
2015-07-05 22:59:36 +00:00
|
|
|
RangeSize<T> push_front_n(RangeSize<T> n) {
|
2015-06-03 21:54:18 +00:00
|
|
|
return p_range.push_front_n(n);
|
2015-06-03 21:43:07 +00:00
|
|
|
}
|
2015-07-05 22:59:36 +00:00
|
|
|
RangeSize<T> push_back_n(RangeSize<T> n) {
|
2015-06-03 21:54:18 +00:00
|
|
|
return p_range.push_back_n(n);
|
|
|
|
}
|
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
R front() const { return p_func(p_range.front()); }
|
|
|
|
R back() const { return p_func(p_range.back()); }
|
2015-05-24 13:34:37 +00:00
|
|
|
|
2015-07-05 22:59:36 +00:00
|
|
|
R operator[](RangeSize<T> idx) const {
|
2015-06-03 21:54:18 +00:00
|
|
|
return p_func(p_range[idx]);
|
2015-05-23 17:44:06 +00:00
|
|
|
}
|
2015-05-24 01:31:54 +00:00
|
|
|
|
2015-07-05 22:59:36 +00:00
|
|
|
MapRange slice(RangeSize<T> start, RangeSize<T> end) {
|
2015-06-07 03:10:08 +00:00
|
|
|
return MapRange(p_range.slice(start, end), p_func);
|
2015-06-03 21:54:18 +00:00
|
|
|
}
|
|
|
|
};
|
2015-05-24 01:31:54 +00:00
|
|
|
|
2015-06-03 21:54:18 +00:00
|
|
|
namespace detail {
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename R, typename F> using MapReturnType
|
2015-07-05 22:59:36 +00:00
|
|
|
= decltype(declval<F>()(declval<RangeReference<R>>()));
|
2015-06-03 21:54:18 +00:00
|
|
|
}
|
2015-05-24 01:31:54 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename R, typename F>
|
2016-04-26 21:25:46 +00:00
|
|
|
inline MapRange<R, F, detail::MapReturnType<R, F>> map(R range, F func) {
|
2016-04-30 16:58:37 +00:00
|
|
|
return MapRange<R, F, detail::MapReturnType<R, F>>(range, move(func));
|
2015-06-03 21:54:18 +00:00
|
|
|
}
|
2015-05-24 01:31:54 +00:00
|
|
|
|
2016-04-30 18:21:50 +00:00
|
|
|
template<typename F>
|
|
|
|
inline auto map(F &&func) {
|
|
|
|
return [func = forward<F>(func)](auto &&obj) mutable {
|
|
|
|
return map(forward<decltype(obj)>(obj), forward<F>(func));
|
|
|
|
};
|
2016-04-26 19:13:32 +00:00
|
|
|
}
|
|
|
|
|
2015-06-07 15:11:01 +00:00
|
|
|
template<typename T, typename F>
|
2015-06-03 21:54:18 +00:00
|
|
|
struct FilterRange: InputRange<
|
2015-07-05 22:59:36 +00:00
|
|
|
FilterRange<T, F>, CommonType<RangeCategory<T>, ForwardRangeTag>,
|
|
|
|
RangeValue<T>, RangeReference<T>, RangeSize<T>
|
2015-06-03 21:54:18 +00:00
|
|
|
> {
|
|
|
|
private:
|
2015-06-04 21:57:06 +00:00
|
|
|
T p_range;
|
2016-05-08 23:07:25 +00:00
|
|
|
Decay<F> p_pred;
|
2015-05-24 01:31:54 +00:00
|
|
|
|
2015-06-03 21:54:18 +00:00
|
|
|
void advance_valid() {
|
|
|
|
while (!p_range.empty() && !p_pred(front())) p_range.pop_front();
|
|
|
|
}
|
2015-05-24 01:31:54 +00:00
|
|
|
|
2015-06-03 21:54:18 +00:00
|
|
|
public:
|
2015-06-29 22:33:20 +00:00
|
|
|
FilterRange() = delete;
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename P>
|
2016-04-30 16:58:37 +00:00
|
|
|
FilterRange(const T &range, P &&pred): p_range(range),
|
|
|
|
p_pred(forward<P>(pred)) {
|
2015-06-03 21:54:18 +00:00
|
|
|
advance_valid();
|
|
|
|
}
|
|
|
|
FilterRange(const FilterRange &it): p_range(it.p_range),
|
|
|
|
p_pred(it.p_pred) {
|
|
|
|
advance_valid();
|
|
|
|
}
|
|
|
|
FilterRange(FilterRange &&it): p_range(move(it.p_range)),
|
|
|
|
p_pred(move(it.p_pred)) {
|
|
|
|
advance_valid();
|
|
|
|
}
|
2015-05-24 01:31:54 +00:00
|
|
|
|
2015-06-03 21:54:18 +00:00
|
|
|
FilterRange &operator=(const FilterRange &v) {
|
|
|
|
p_range = v.p_range;
|
|
|
|
p_pred = v.p_pred;
|
|
|
|
advance_valid();
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
FilterRange &operator=(FilterRange &&v) {
|
|
|
|
p_range = move(v.p_range);
|
|
|
|
p_pred = move(v.p_pred);
|
|
|
|
advance_valid();
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool empty() const { return p_range.empty(); }
|
2015-05-24 01:31:54 +00:00
|
|
|
|
2015-06-03 21:54:18 +00:00
|
|
|
bool equals_front(const FilterRange &r) const {
|
|
|
|
return p_range.equals_front(r.p_range);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool pop_front() {
|
|
|
|
bool ret = p_range.pop_front();
|
|
|
|
advance_valid();
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2015-07-05 22:59:36 +00:00
|
|
|
RangeReference<T> front() const { return p_range.front(); }
|
2015-06-03 21:54:18 +00:00
|
|
|
};
|
|
|
|
|
2015-06-07 15:11:01 +00:00
|
|
|
namespace detail {
|
|
|
|
template<typename R, typename P> using FilterPred
|
2015-07-05 22:59:36 +00:00
|
|
|
= EnableIf<IsSame<
|
|
|
|
decltype(declval<P>()(declval<RangeReference<R>>())), bool
|
2016-01-12 22:24:40 +00:00
|
|
|
>, P>;
|
2015-06-07 15:11:01 +00:00
|
|
|
}
|
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename R, typename P>
|
2016-04-26 21:25:46 +00:00
|
|
|
inline FilterRange<R, detail::FilterPred<R, P>> filter(R range, P pred) {
|
2016-05-08 23:07:25 +00:00
|
|
|
return FilterRange<R, P>(range, move(pred));
|
2015-04-18 01:35:36 +00:00
|
|
|
}
|
|
|
|
|
2016-04-30 18:21:50 +00:00
|
|
|
template<typename F>
|
|
|
|
inline auto filter(F &&func) {
|
|
|
|
return [func = forward<F>(func)](auto &&obj) mutable {
|
|
|
|
return filter(forward<decltype(obj)>(obj), forward<F>(func));
|
|
|
|
};
|
2016-04-26 19:13:32 +00:00
|
|
|
}
|
|
|
|
|
2015-07-13 19:07:14 +00:00
|
|
|
} /* namespace ostd */
|
2015-06-03 21:54:18 +00:00
|
|
|
|
2016-02-07 21:17:15 +00:00
|
|
|
#endif
|