piping for nearly all algorithms

master
Daniel Kolesa 2016-04-26 22:25:46 +01:00
parent 5604df9625
commit e7dd08d884
2 changed files with 116 additions and 43 deletions

View File

@ -18,7 +18,7 @@ namespace ostd {
/* partitioning */
template<typename R, typename U>
R partition(R range, U pred) {
inline R partition(R range, U pred) {
R ret = range;
for (; !range.empty(); range.pop_front()) {
if (pred(range.front())) {
@ -29,19 +29,27 @@ R partition(R range, U pred) {
return ret;
}
template<typename F> inline auto partition(F func) {
return [f = move(func)](auto obj) { return partition(obj, f); };
}
template<typename R, typename P>
bool is_partitioned(R range, P pred) {
inline bool is_partitioned(R range, P pred) {
for (; !range.empty() && pred(range.front()); range.pop_front());
for (; !range.empty(); range.pop_front())
if (pred(range.front())) return false;
return true;
}
template<typename F> inline bool is_partitioned(F func) {
return [f = move(func)](auto obj) { return is_partitioned(obj, f); };
}
/* sorting */
namespace detail {
template<typename R, typename C>
void insort(R range, C compare) {
static void insort(R range, C compare) {
RangeSize<R> rlen = range.size();
for (RangeSize<R> i = 1; i < rlen; ++i) {
RangeSize<R> j = i;
@ -55,7 +63,7 @@ namespace detail {
}
template<typename R, typename C>
void hs_sift_down(R range, RangeSize<R> s,
static void hs_sift_down(R range, RangeSize<R> s,
RangeSize<R> e, C compare) {
RangeSize<R> r = s;
while ((r * 2 + 1) <= e) {
@ -73,7 +81,7 @@ namespace detail {
}
template<typename R, typename C>
void heapsort(R range, C compare) {
static void heapsort(R range, C compare) {
RangeSize<R> len = range.size();
RangeSize<R> st = (len - 2) / 2;
for (;;) {
@ -89,7 +97,7 @@ namespace detail {
}
template<typename R, typename C>
void introloop(R range, C compare, RangeSize<R> depth) {
static void introloop(R range, C compare, RangeSize<R> depth) {
if (range.size() <= 10) {
detail::insort(range, compare);
return;
@ -113,19 +121,19 @@ namespace detail {
}
template<typename R, typename C>
void introsort(R range, C compare) {
inline void introsort(R range, C compare) {
detail::introloop(range, compare, RangeSize<R>(2
* (log(range.size()) / log(2))));
}
} /* namespace detail */
template<typename R, typename C>
void sort(R range, C compare) {
inline void sort(R range, C compare) {
detail::introsort(range, compare);
}
template<typename R>
void sort(R range) {
inline void sort(R range) {
sort(range, Less<RangeValue<R>>());
}
@ -217,7 +225,7 @@ inline T clamp(const T &v, const U &lo, const U &hi, C compare) {
/* lexicographical compare */
template<typename R1, typename R2>
bool lexicographical_compare(R1 range1, R2 range2) {
inline bool lexicographical_compare(R1 range1, R2 range2) {
while (!range1.empty() && !range2.empty()) {
if (range1.front() < range2.front()) return true;
if (range2.front() < range1.front()) return false;
@ -228,7 +236,7 @@ bool lexicographical_compare(R1 range1, R2 range2) {
}
template<typename R1, typename R2, typename C>
bool lexicographical_compare(R1 range1, R2 range2, C compare) {
inline bool lexicographical_compare(R1 range1, R2 range2, C compare) {
while (!range1.empty() && !range2.empty()) {
if (compare(range1.front(), range2.front())) return true;
if (compare(range2.front(), range1.front())) return false;
@ -241,43 +249,67 @@ bool lexicographical_compare(R1 range1, R2 range2, C compare) {
/* algos that don't change the range */
template<typename R, typename F>
F for_each(R range, F func) {
inline F for_each(R range, F func) {
for (; !range.empty(); range.pop_front())
func(range.front());
return move(func);
}
template<typename F> inline auto for_each(F func) {
return [f = move(func)](auto obj) {
for (; !obj.empty(); obj.pop_front())
f(obj.front());
return move(f);
};
}
template<typename R, typename P>
bool all_of(R range, P pred) {
inline bool all_of(R range, P pred) {
for (; !range.empty(); range.pop_front())
if (!pred(range.front())) return false;
return true;
}
template<typename F> inline auto all_of(F func) {
return [f = move(func)](auto obj) { return all_of(obj, f); };
}
template<typename R, typename P>
bool any_of(R range, P pred) {
inline bool any_of(R range, P pred) {
for (; !range.empty(); range.pop_front())
if (pred(range.front())) return true;
return false;
}
template<typename F> inline auto any_of(F func) {
return [f = move(func)](auto obj) { return any_of(obj, f); };
}
template<typename R, typename P>
bool none_of(R range, P pred) {
inline bool none_of(R range, P pred) {
for (; !range.empty(); range.pop_front())
if (pred(range.front())) return false;
return true;
}
template<typename F> inline auto none_of(F func) {
return [f = move(func)](auto obj) { return none_of(obj, f); };
}
template<typename R, typename T>
R find(R range, const T &v) {
inline R find(R range, const T &v) {
for (; !range.empty(); range.pop_front())
if (range.front() == v)
break;
return range;
}
template<typename T> inline auto find(const T &v) {
return [v](auto obj) { return find(obj, v); };
}
template<typename R, typename T>
R find_last(R range, const T &v) {
inline R find_last(R range, const T &v) {
range = find(range, v);
if (!range.empty()) for (;;) {
R prev = range;
@ -290,24 +322,36 @@ R find_last(R range, const T &v) {
return range;
}
template<typename T> inline auto find_last(const T &v) {
return [v](auto obj) { return find_last(obj, v); };
}
template<typename R, typename P>
R find_if(R range, P pred) {
inline R find_if(R range, P pred) {
for (; !range.empty(); range.pop_front())
if (pred(range.front()))
break;
return range;
}
template<typename F> inline auto find_if(F func) {
return [f = move(func)](auto obj) { return find_if(obj, f); };
}
template<typename R, typename P>
R find_if_not(R range, P pred) {
inline R find_if_not(R range, P pred) {
for (; !range.empty(); range.pop_front())
if (!pred(range.front()))
break;
return range;
}
template<typename F> inline auto find_if_not(F func) {
return [f = move(func)](auto obj) { return find_if_not(obj, f); };
}
template<typename R1, typename R2, typename C>
R1 find_one_of(R1 range, R2 values, C compare) {
inline R1 find_one_of(R1 range, R2 values, C compare) {
for (; !range.empty(); range.pop_front())
for (R2 rv = values; !rv.empty(); rv.pop_front())
if (compare(range.front(), rv.front()))
@ -316,7 +360,7 @@ R1 find_one_of(R1 range, R2 values, C compare) {
}
template<typename R1, typename R2>
R1 find_one_of(R1 range, R2 values) {
inline R1 find_one_of(R1 range, R2 values) {
for (; !range.empty(); range.pop_front())
for (R2 rv = values; !rv.empty(); rv.pop_front())
if (range.front() == rv.front())
@ -325,7 +369,7 @@ R1 find_one_of(R1 range, R2 values) {
}
template<typename R, typename T>
RangeSize<R> count(R range, const T &v) {
inline RangeSize<R> count(R range, const T &v) {
RangeSize<R> ret = 0;
for (; !range.empty(); range.pop_front())
if (range.front() == v)
@ -333,8 +377,12 @@ RangeSize<R> count(R range, const T &v) {
return ret;
}
template<typename T> inline auto count(const T &v) {
return [v](auto obj) { return count(obj, v); };
}
template<typename R, typename P>
RangeSize<R> count_if(R range, P pred) {
inline RangeSize<R> count_if(R range, P pred) {
RangeSize<R> ret = 0;
for (; !range.empty(); range.pop_front())
if (pred(range.front()))
@ -342,8 +390,12 @@ RangeSize<R> count_if(R range, P pred) {
return ret;
}
template<typename F> inline auto count_if(F func) {
return [f = move(func)](auto obj) { return count_if(obj, f); };
}
template<typename R, typename P>
RangeSize<R> count_if_not(R range, P pred) {
inline RangeSize<R> count_if_not(R range, P pred) {
RangeSize<R> ret = 0;
for (; !range.empty(); range.pop_front())
if (!pred(range.front()))
@ -351,8 +403,12 @@ RangeSize<R> count_if_not(R range, P pred) {
return ret;
}
template<typename F> inline auto count_if_not(F func) {
return [f = move(func)](auto obj) { return count_if_not(obj, f); };
}
template<typename R>
bool equal(R range1, R range2) {
inline bool equal(R range1, R range2) {
for (; !range1.empty(); range1.pop_front()) {
if (range2.empty() || (range1.front() != range2.front()))
return false;
@ -361,22 +417,30 @@ bool equal(R range1, R range2) {
return range2.empty();
}
template<typename R> inline bool equal(R range) {
return [r = move(range)](auto obj) { return equal(obj, r); };
}
template<typename R>
R slice_until(R range1, R range2) {
return range1.slice(0, range1.distance_front(range2));
}
template<typename R> inline auto slice_until(R range) {
return [r = move(range)](auto obj) { return slice_until(obj, r); };
}
/* algos that modify ranges or work with output ranges */
template<typename R1, typename R2>
R2 copy(R1 irange, R2 orange) {
inline R2 copy(R1 irange, R2 orange) {
for (; !irange.empty(); irange.pop_front())
orange.put(irange.front());
return orange;
}
template<typename R1, typename R2, typename P>
R2 copy_if(R1 irange, R2 orange, P pred) {
inline R2 copy_if(R1 irange, R2 orange, P pred) {
for (; !irange.empty(); irange.pop_front())
if (pred(irange.front()))
orange.put(irange.front());
@ -384,7 +448,7 @@ R2 copy_if(R1 irange, R2 orange, P pred) {
}
template<typename R1, typename R2, typename P>
R2 copy_if_not(R1 irange, R2 orange, P pred) {
inline R2 copy_if_not(R1 irange, R2 orange, P pred) {
for (; !irange.empty(); irange.pop_front())
if (!pred(irange.front()))
orange.put(irange.front());
@ -392,14 +456,14 @@ R2 copy_if_not(R1 irange, R2 orange, P pred) {
}
template<typename R1, typename R2>
R2 move(R1 irange, R2 orange) {
inline R2 move(R1 irange, R2 orange) {
for (; !irange.empty(); irange.pop_front())
orange.put(move(irange.front()));
return orange;
}
template<typename R>
void reverse(R range) {
inline void reverse(R range) {
while (!range.empty()) {
detail::swap_adl(range.front(), range.back());
range.pop_front();
@ -408,26 +472,26 @@ void reverse(R range) {
}
template<typename R1, typename R2>
R2 reverse_copy(R1 irange, R2 orange) {
inline R2 reverse_copy(R1 irange, R2 orange) {
for (; !irange.empty(); irange.pop_back())
orange.put(irange.back());
return orange;
}
template<typename R, typename T>
void fill(R range, const T &v) {
inline void fill(R range, const T &v) {
for (; !range.empty(); range.pop_front())
range.front() = v;
}
template<typename R, typename F>
void generate(R range, F gen) {
inline void generate(R range, F gen) {
for (; !range.empty(); range.pop_front())
range.front() = gen();
}
template<typename R1, typename R2>
Pair<R1, R2> swap_ranges(R1 range1, R2 range2) {
inline Pair<R1, R2> swap_ranges(R1 range1, R2 range2) {
while (!range1.empty() && !range2.empty()) {
detail::swap_adl(range1.front(), range2.front());
range1.pop_front();
@ -437,39 +501,47 @@ Pair<R1, R2> swap_ranges(R1 range1, R2 range2) {
}
template<typename R, typename T>
void iota(R range, T value) {
inline void iota(R range, T value) {
for (; !range.empty(); range.pop_front())
range.front() = value++;
}
template<typename R, typename T>
T foldl(R range, T init) {
inline T foldl(R range, T init) {
for (; !range.empty(); range.pop_front())
init = init + range.front();
return init;
}
template<typename R, typename T, typename F>
T foldl(R range, T init, F func) {
inline T foldl(R range, T init, F func) {
for (; !range.empty(); range.pop_front())
init = func(init, range.front());
return init;
}
template<typename T> inline auto foldl(T init) {
return [v = move(init)](auto obj) { return foldl(obj, v); };
}
template<typename R, typename T>
T foldr(R range, T init) {
inline T foldr(R range, T init) {
for (; !range.empty(); range.pop_back())
init = init + range.back();
return init;
}
template<typename R, typename T, typename F>
T foldr(R range, T init, F func) {
inline T foldr(R range, T init, F func) {
for (; !range.empty(); range.pop_back())
init = func(init, range.back());
return init;
}
template<typename T> inline auto foldr(T init) {
return [v = move(init)](auto obj) { return foldr(obj, v); };
}
template<typename T, typename F, typename R>
struct MapRange: InputRange<
MapRange<T, F, R>, RangeCategory<T>, R, R, RangeSize<T>
@ -553,12 +625,12 @@ namespace detail {
}
template<typename R, typename F>
MapRange<R, F, detail::MapReturnType<R, F>> map(R range, F func) {
inline MapRange<R, F, detail::MapReturnType<R, F>> map(R range, F func) {
return MapRange<R, F, detail::MapReturnType<R, F>>(range,
func);
}
template<typename F> auto map(F func) {
template<typename F> inline auto map(F func) {
return [f = move(func)](auto obj) { return map(obj, f); };
}
@ -627,11 +699,11 @@ namespace detail {
}
template<typename R, typename P>
FilterRange<R, detail::FilterPred<R, P>> filter(R range, P pred) {
inline FilterRange<R, detail::FilterPred<R, P>> filter(R range, P pred) {
return FilterRange<R, P>(range, pred);
}
template<typename F> auto filter(F func) {
template<typename F> inline auto filter(F func) {
return [f = move(func)](auto obj) { return filter(obj, f); };
}

View File

@ -606,6 +606,7 @@ inline auto chunks(T n) {
return [n](auto obj) { return obj.chunks(n); };
}
/* TODO: can't use generalized captures on packs so gotta workaround */
template<typename R1, typename ...R>
inline auto join(R1 r1, R ...rr) {
return [=](auto obj) mutable { return obj.join(move(r1), move(rr)...); };