#ifndef __Metaiterators__
#define __Metaiterators__
#include <tuple>
#include <utility>
#include <functional>
#include "Debug/Assertion.hpp"
#include "Forwards.hpp"
#include "Lib/Recycled.hpp"
#include "Debug/TimeProfiling.hpp"
#include "Lib/Reflection.hpp"
#include "List.hpp"
#include "DHSet.hpp"
#include "VirtualIterator.hpp"
#include "Lib/Option.hpp"
#include "Lib/Coproduct.hpp"
#include "Debug/TimeProfiling.hpp"
namespace Lib {
template<class C>
ITERATOR_TYPE(C) getContentIterator(C& c)
{
return ITERATOR_TYPE(C)(c);
}
template<typename T>
class SingletonIterator
{
public:
DECL_ELEMENT_TYPE(T);
DEFAULT_CONSTRUCTORS(SingletonIterator)
explicit SingletonIterator(T el) : _finished(false), _el(el) {}
inline bool hasNext() { return !_finished; };
inline T next() { ASS(!_finished); _finished=true; return _el; };
inline bool knowsSize() const { return true; }
inline size_t size() const { return 1; }
private:
bool _finished;
T _el;
};
template<typename T>
inline
SingletonIterator<T> getSingletonIterator(T el)
{
return SingletonIterator<T>(el);
}
struct NonzeroFn
{
template<typename T>
bool operator()(T obj)
{
return obj!=0;
}
};
template<bool cond> struct __doDeletion
{ template<class Iter> void operator()(Iter& iter) { } };
template<> struct __doDeletion<true>
{ template<class Iter> void operator()(Iter& iter) { iter.del(); } };
template<class Inner, class Functor, bool deleteFilteredOut = false>
class FilteredIterator
{
public:
DECL_ELEMENT_TYPE(ELEMENT_TYPE(Inner));
DEFAULT_CONSTRUCTORS(FilteredIterator)
FilteredIterator(Inner inn, Functor func)
: _func(std::move(func)), _inn(std::move(inn)), _next() {}
bool hasNext()
{
if(_next.isSome()) {
return true;
}
while(_inn.hasNext()) {
OWN_ELEMENT_TYPE next = move_if_value<OWN_ELEMENT_TYPE>(_inn.next());
if(_func(next)) {
_next = Option<OWN_ELEMENT_TYPE>(move_if_value<OWN_ELEMENT_TYPE>(next));
return true;
} else {
__doDeletion<deleteFilteredOut>{}(_inn);
}
}
return false;
}
OWN_ELEMENT_TYPE next()
{
ALWAYS(hasNext());
ASS(_next.isSome());
OWN_ELEMENT_TYPE out = move_if_value<OWN_ELEMENT_TYPE>(_next.unwrap());
_next = Option<OWN_ELEMENT_TYPE>();
return out;
}
bool knowsSize() const { return false; }
size_t size() const { ASSERTION_VIOLATION }
private:
Functor _func;
Inner _inn;
Option<OWN_ELEMENT_TYPE> _next;
};
template<class Iter, class Pred>
class TakeWhileIter
{
public:
DECL_ELEMENT_TYPE(ELEMENT_TYPE(Iter));
DEFAULT_CONSTRUCTORS(TakeWhileIter)
TakeWhileIter(Iter iter, Pred pred)
: _pred(std::move(pred)), _iter(std::move(iter)), _next(), _break(false) {}
bool hasNext()
{
if (_break) return false;
if(_next.isSome()) return true;
while(_iter.hasNext()) {
OWN_ELEMENT_TYPE next = move_if_value<OWN_ELEMENT_TYPE>(_iter.next());
if(_pred(next)) {
_next = Option<OWN_ELEMENT_TYPE>(move_if_value<OWN_ELEMENT_TYPE>(next));
return true;
} else {
_break = true;
return false;
}
}
return false;
}
OWN_ELEMENT_TYPE next()
{
ASS(!_break)
ALWAYS(hasNext());
ASS(_next.isSome());
OWN_ELEMENT_TYPE out = move_if_value<OWN_ELEMENT_TYPE>(_next.unwrap());
_next = Option<OWN_ELEMENT_TYPE>();
return out;
}
private:
Pred _pred;
Iter _iter;
Option<OWN_ELEMENT_TYPE> _next;
bool _break;
};
template<class I1, class I2, class Cmp>
class SortedIterDiff {
public:
DECL_ELEMENT_TYPE(ELEMENT_TYPE(I1));
DEFAULT_CONSTRUCTORS(SortedIterDiff)
SortedIterDiff(I1 i1, I2 i2, Cmp cmp)
: _i1(std::move(i1))
, _i2(std::move(i2))
, _curr1()
, _curr2(someIf(_i2.hasNext(), [&]() -> OWN_ELEMENT_TYPE { return move_if_value<OWN_ELEMENT_TYPE>(_i2.next()); }))
, _cmp(std::move(cmp))
{}
void moveToNext()
{
# if VDEBUG
Option<OWN_ELEMENT_TYPE> old1;
# endif
while (_curr1.isNone() && _i1.hasNext()) {
_curr1 = Option<OWN_ELEMENT_TYPE>(move_if_value<OWN_ELEMENT_TYPE>(_i1.next()));
ASS_REP(!_curr1.isSome() || !old1.isSome() || _cmp(*old1, *_curr1) <= 0, "iterator I1 must be sorted");
while (_curr2.isSome() && _cmp(*_curr2, *_curr1) < 0) {
# if VDEBUG
Option<OWN_ELEMENT_TYPE> old2 = _curr2.take();
# endif
_curr2 = someIf(_i2.hasNext(), [&]() -> OWN_ELEMENT_TYPE
{ return move_if_value<OWN_ELEMENT_TYPE>(_i2.next()); });
ASS_REP(!_curr2.isSome() || !old2.isSome() || _cmp(*old2, *_curr2) <= 0, "iterator I2 must be sorted");
}
if (( _curr1.isSome() && _curr2.isSome() && _cmp(*_curr1, *_curr2) == 0 )
|| (_curr1.isNone() && _curr2.isNone())) {
# if VDEBUG
old1 = _curr1.take();
# endif
_curr1 = Option<OWN_ELEMENT_TYPE>();
_curr2 = someIf(_i2.hasNext(), [&]() -> OWN_ELEMENT_TYPE
{ return move_if_value<OWN_ELEMENT_TYPE>(_i2.next()); });
}
}
}
bool hasNext()
{
moveToNext();
return _curr1.isSome();
}
OWN_ELEMENT_TYPE next()
{
moveToNext();
return move_if_value<OWN_ELEMENT_TYPE>(_curr1.take().unwrap());
}
private:
I1 _i1;
I2 _i2;
Option<OWN_ELEMENT_TYPE> _curr1;
Option<OWN_ELEMENT_TYPE> _curr2;
Cmp _cmp;
};
template<class Inner, class Functor>
class FilterMapIter
{
public:
DECL_ELEMENT_TYPE(typename std::invoke_result<Functor, ELEMENT_TYPE(Inner)>::type::Content);
DEFAULT_CONSTRUCTORS(FilterMapIter)
FilterMapIter(Inner inn, Functor func)
: _func(std::move(func)), _inn(std::move(inn)), _next() {}
bool hasNext()
{
if(_next.isSome()) {
return true;
}
while(_inn.hasNext()) {
_next = _func(move_if_value<ELEMENT_TYPE(Inner)>(_inn.next()));
if(_next.isSome()) {
return true;
}
}
return false;
};
OWN_ELEMENT_TYPE next()
{
ALWAYS(hasNext());
ASS(_next.isSome());
OWN_ELEMENT_TYPE out = move_if_value<OWN_ELEMENT_TYPE>(_next.unwrap());
_next = Option<OWN_ELEMENT_TYPE>();
return out;
};
private:
Functor _func;
Inner _inn;
Option<OWN_ELEMENT_TYPE> _next;
};
template<class Inner, class Functor>
inline
FilteredIterator<Inner,Functor> getFilteredIterator(Inner inn, Functor func)
{
return FilteredIterator<Inner,Functor>(std::move(inn), std::move(func));
}
template<class Inner, class Functor>
inline
auto getFilteredDelIterator(Inner inn, Functor func)
{ return FilteredIterator<Inner, Functor, true>(inn, func); }
template<class Inner, class Functor>
class WhileLimitedIterator
{
public:
DECL_ELEMENT_TYPE(ELEMENT_TYPE(Inner));
DEFAULT_CONSTRUCTORS(WhileLimitedIterator)
WhileLimitedIterator(Inner inn, Functor func)
: _func(std::move(func)), _inn(std::move(inn)), _nextStored(false) {}
bool hasNext()
{
if(!_nextStored) {
if(!_inn.hasNext()) {
return false;
}
_next=_inn.next();
_nextStored=true;
}
return _func(_next);
};
OWN_ELEMENT_TYPE next()
{
if(!_nextStored) {
ALWAYS(hasNext());
ASS(_nextStored);
}
_nextStored=false;
return _next;
};
private:
Functor _func;
Inner _inn;
OWN_ELEMENT_TYPE _next;
bool _nextStored;
};
template<class Inner, class Functor>
inline
WhileLimitedIterator<Inner,Functor> getWhileLimitedIterator(Inner inn, Functor func)
{
return WhileLimitedIterator<Inner,Functor>(inn, func);
}
template<class It1,class It2>
class CatIterator
{
public:
DECL_ELEMENT_TYPE(ELEMENT_TYPE(It1));
DEFAULT_CONSTRUCTORS(CatIterator)
CatIterator(It1 it1, It2 it2)
:_first(true), _it1(std::move(it1)), _it2(std::move(it2)) {}
bool hasNext()
{
if(_first) {
if(_it1.hasNext()) {
return true;
}
_first=false;
}
return _it2.hasNext();
};
OWN_ELEMENT_TYPE next()
{
ALWAYS(hasNext())
if(_first) {
return _it1.next();
}
return _it2.next();
};
bool knowsSize() const { return _it1.knowsSize() && _it2.knowsSize(); }
size_t size() const { return _it1.size()+_it2.size(); }
private:
bool _first;
It1 _it1;
It2 _it2;
};
template<typename Inner, typename Functor, typename ResultType=std::invoke_result_t<Functor, ELEMENT_TYPE(Inner)>>
class MappingIterator
{
public:
DECL_ELEMENT_TYPE(ResultType);
IGNORE_MAYBE_UNINITIALIZED(DEFAULT_CONSTRUCTORS(MappingIterator))
explicit MappingIterator(Inner inner, Functor func)
: _func(std::move(func)), _inner(std::move(inner)) {}
inline bool hasNext() { return _inner.hasNext(); };
inline ResultType next() { return _func(move_if_value<ELEMENT_TYPE(Inner)>(_inner.next())); };
inline bool knowsSize() const { return _inner.knowsSize(); }
inline size_t size() const { return _inner.size(); }
auto reverse() &&
{ return MappingIterator<decltype(std::move(_inner).reverse()), Functor, ResultType>(std::move(_inner).reverse(), std::move(_func)); }
private:
Functor _func;
Inner _inner;
};
template<typename Iter>
class IterTraits;
template<typename Iter>
IterTraits<Iter> iterTraits(Iter);
template<typename Iter>
class IterFromTryNext
{
public:
DECL_ELEMENT_TYPE(ELEMENT_TYPE(Iter));
DEFAULT_CONSTRUCTORS(IterFromTryNext)
IterFromTryNext(Iter iter)
: _iter(std::move(iter)) {}
bool hasNext() {
if (!_nextCached) { _nextCached = some(_iter.tryNext()); }
return _nextCached->isSome();
}
OWN_ELEMENT_TYPE next() {
if (!_nextCached) { _nextCached = some(_iter.tryNext()); }
return _nextCached.take()->unwrap();
}
private:
Iter _iter;
Option<Option<OWN_ELEMENT_TYPE>> _nextCached;
};
template<typename Iter>
IterFromTryNext<Iter> iterFromTryNext(Iter iter)
{ return IterFromTryNext<Iter>(std::move(iter)); }
template<typename Inner, typename Functor>
MappingIterator<Inner,Functor,ResultOf<Functor, ELEMENT_TYPE(Inner)>> getMappingIterator(Inner it, Functor f)
{
return MappingIterator<Inner,Functor, ResultOf<Functor, ELEMENT_TYPE(Inner)>>(std::move(it), std::move(f));
}
template<typename ResultType, typename Inner, typename Functor>
MappingIterator<Inner,Functor,ResultType> getMappingIteratorKnownRes(Inner it, Functor f)
{
return MappingIterator<Inner,Functor,ResultType>(it, f);
}
template<typename Constructor, typename Inner>
class ConstructingIterator
{
public:
DECL_ELEMENT_TYPE(Constructor*);
DEFAULT_CONSTRUCTORS(ConstructingIterator)
explicit ConstructingIterator(Inner inner)
: _inner(inner) {}
inline bool hasNext() { return _inner.hasNext(); };
inline Constructor* next() { return new Constructor(_inner.next()); };
private:
Inner _inner;
};
template<typename Constructor, typename Inner>
inline
ConstructingIterator<Constructor,Inner> getConstructingIterator(Inner it)
{
return ConstructingIterator<Constructor,Inner>(it);
}
template<typename Master>
class FlatteningIterator
{
public:
using Inner = ELEMENT_TYPE(Master);
DECL_ELEMENT_TYPE(ELEMENT_TYPE(Inner));
DEFAULT_CONSTRUCTORS(FlatteningIterator)
explicit FlatteningIterator(Master master)
: _master(std::move(master))
, _current(_master.hasNext()
? Option<Inner>(move_if_value<Inner>(_master.next()))
: Option<Inner>())
{ }
bool hasNext()
{
while (_current.isSome()) {
if (_current->hasNext()) {
return true;
} else {
_current = _master.hasNext()
? Option<Inner>(move_if_value<Inner>(_master.next()))
: Option<Inner>();
}
}
return false;
}
inline
ELEMENT_TYPE(FlatteningIterator) next()
{
ASS(_current.isSome());
ASS(_current.unwrap().hasNext());
return move_if_value<OWN_ELEMENT_TYPE>(_current.unwrap().next());
}
private:
Master _master;
Option<Inner> _current;
};
template<typename T>
inline
FlatteningIterator<T> getFlattenedIterator(T it)
{ return FlatteningIterator<T>(std::move(it)); }
template<class Inner, class Functor>
using FlatMapIter = FlatteningIterator<MappingIterator<Inner,Functor>>;
template<typename Inner, typename Functor>
inline
FlatMapIter<Inner,Functor> getMapAndFlattenIterator(Inner it, Functor f)
{
return FlatteningIterator<MappingIterator<Inner,Functor> >(
MappingIterator<Inner,Functor>(std::move(it), f) );
}
template<class Inner>
class UniquePersistentIterator
: public IteratorCore<ELEMENT_TYPE(Inner)>
{
public:
typedef ELEMENT_TYPE(Inner) T;
private:
typedef List<T> ItemList;
public:
explicit UniquePersistentIterator(Inner& inn)
{
_items=getUniqueItemList(inn, _size);
}
~UniquePersistentIterator() override
{
if(_items) {
ItemList::destroy(_items);
}
}
inline bool hasNext() override { return _items; };
inline T next() override
{
return ItemList::pop(_items);
};
inline bool knowsSize() const override { return true; }
inline size_t size() const override { return _size; }
private:
typedef DHSet<T> ItemSet;
static ItemList* getUniqueItemList(Inner& inn, size_t& sizeRef)
{
ItemList* res=0;
Recycled<ItemSet> iset;
sizeRef=0;
while(inn.hasNext()) {
T el=inn.next();
if(iset->insert(el)) {
ItemList::push(el, res);
sizeRef++;
}
}
return res;
}
ItemList* _items;
size_t _size;
};
template<class Inner>
inline
VirtualIterator<ELEMENT_TYPE(Inner)> getUniquePersistentIterator(Inner it)
{
if(!it.hasNext()) {
return VirtualIterator<ELEMENT_TYPE(Inner)>::getEmpty();
}
return vi( new UniquePersistentIterator<Inner>(it) );
}
template<class Inner>
inline
VirtualIterator<ELEMENT_TYPE(Inner)> getUniquePersistentIteratorFromPtr(Inner* it)
{
if(!it->hasNext()) {
return VirtualIterator<ELEMENT_TYPE(Inner)>::getEmpty();
}
return vi( new UniquePersistentIterator<Inner>(*it) );
}
template<class It>
size_t countIteratorElements(It it)
{
size_t res = 0;
while(it.hasNext()) {
it.next();
res++;
}
return res;
}
template<typename T>
class RangeIterator
{
public:
DECL_ELEMENT_TYPE(T);
DEFAULT_CONSTRUCTORS(RangeIterator)
inline
RangeIterator(T from, T to)
: _next(from), _from(from), _to(to) {}
inline bool hasNext() { return _next<_to; };
inline T next() { return _next++; };
inline bool knowsSize() const { return true; }
inline size_t size() const { return (_to>_from) ? (_to-_from) : 0; }
auto reverse() &&
{
auto to = _to;
return getMappingIterator(std::move(*this), [to](auto i) { return to - 1 - i; });
}
private:
T _next;
T _from;
T _to;
};
template<typename T>
RangeIterator<T> getRangeIterator(T from, T to)
{
return RangeIterator<T>(from, to);
}
template<typename T>
class CombinationIterator
{
public:
DECL_ELEMENT_TYPE(std::pair<T,T>);
DEFAULT_CONSTRUCTORS(CombinationIterator)
CombinationIterator(T from, T to)
: _first(from), _second(from), _afterLast(to)
{
ASS_LE(from,to);
if(from!=to) {
if(from+1==to) {
_second=_afterLast;
} else {
moveToNext();
}
}
}
inline bool hasNext()
{ ASS_LE(_first,_afterLast); return _second!=_afterLast; }
std::pair<T,T> next()
{
ASS(hasNext());
std::pair<T,T> res=std::pair<T,T>(_first,_second);
moveToNext();
return res;
}
private:
void moveToNext()
{
_second++;
ASS_LE(_second,_afterLast);
if(_second==_afterLast) {
_first++;
_second=_first;
_second++;
}
}
T _first;
T _second;
T _afterLast;
};
template<typename T>
inline
CombinationIterator<T> getCombinationIterator(T from, T to)
{
return CombinationIterator<T>(from, to);
}
template<typename T>
class Combination2Iterator
{
public:
DECL_ELEMENT_TYPE(std::pair<T,T>);
DEFAULT_CONSTRUCTORS(Combination2Iterator)
Combination2Iterator(T from, T to1, T to2)
: _first(from), _second(from), _afterLast1(to1), _afterLast2(to2)
{
ASS_LE(from,to1);
ASS_LE(to1,to2);
if(from!=to1) {
moveToNext();
}
}
inline bool hasNext()
{ return _first!=_afterLast1 && _second!=_afterLast2; }
std::pair<T,T> next()
{
ASS(hasNext());
std::pair<T,T> res=std::pair<T,T>(_first,_second);
ASS_LE(_first,_afterLast1);
ASS_LE(_second,_afterLast2);
moveToNext();
return res;
}
private:
void moveToNext()
{
_second++;
ASS_LE(_second,_afterLast2);
if(_second==_afterLast2) {
_first++;
_second=_first;
_second++;
}
}
T _first;
T _second;
T _afterLast1;
T _afterLast2;
};
template<typename T>
inline
Combination2Iterator<T> getCombinationIterator(T from, T to1, T to2)
{
return Combination2Iterator<T>(from, to1, to2);
}
template<class Inner, class Ctx>
class ContextualIterator
{
public:
DECL_ELEMENT_TYPE(ELEMENT_TYPE(Inner));
DEFAULT_CONSTRUCTORS(ContextualIterator)
ContextualIterator(Inner iit, Ctx context)
: _inContext(false), _used(true), _context(std::move(context)), _iit(std::move(iit)) {}
~ContextualIterator()
{
assureContextLeft();
}
bool hasNext()
{
if(!_used) {
return true;
}
assureContextLeft();
do {
if(!_iit.hasNext()) {
return false;
}
_current = Option<ELEMENT_TYPE(Inner)>(_iit.next());
} while (!_context.enter(_current.unwrap()));
_inContext=true;
_used=false;
return true;
}
inline
ELEMENT_TYPE(Inner) next()
{
ASS(!_used);
_used=true;
return move_if_value<ELEMENT_TYPE(Inner)>(_current.unwrap());
}
private:
void assureContextLeft()
{
if(_inContext) {
_context.leave(_current.unwrap());
_inContext=false;
}
}
bool _inContext;
bool _used;
Ctx _context;
Inner _iit;
Option<ELEMENT_TYPE(Inner)> _current;
};
template<class Inner, class Ctx>
inline
ContextualIterator<Inner,Ctx> getContextualIterator(Inner it, Ctx context)
{
return ContextualIterator<Inner,Ctx>(it, context);
}
#if VTIME_PROFILING
template<class Iter>
class TimeTracedIter
{
const char* _name;
Iter _iter;
public:
TimeTracedIter(const char* name, Iter iter)
: _name(name)
, _iter(std::move(iter))
{}
DECL_ELEMENT_TYPE(ELEMENT_TYPE(Iter));
OWN_ELEMENT_TYPE next() { TIME_TRACE(_name); return _iter.next(); }
bool hasNext() { TIME_TRACE(_name); return _iter.hasNext(); }
bool knowsSize() const
{ return _iter.knowsSize(); }
size_t size() const
{ return _iter.size(); }
};
template<class Iter>
auto timeTraceIter(const char* name, Iter iter)
{ return TimeTracedIter<Iter>(name, std::move(iter)); }
#define TIME_TRACE_ITER(name, iter) timeTraceIter(name, iter)
#else
#define TIME_TRACE_ITER(name, iter) iter
#endif
template<class It1, class It2>
bool iteratorsEqual(It1 it1, It2 it2)
{
while(it1.hasNext()) {
if(!it2.hasNext()) {
return false;
}
if(it1.next()!=it2.next()) {
return false;
}
}
return !it2.hasNext();
}
template<typename T>
static bool lessThan(T a, T b) { return a<b; }
template<class It>
bool isSorted(It it)
{
if(!it.hasNext()) { return true; }
ELEMENT_TYPE(It) prev = it.next();
while(it.hasNext()) {
ELEMENT_TYPE(It) curr = it.next();
if(!(prev<curr)) {
return false;
}
prev = curr;
}
return true;
}
template<class It, typename Pred>
bool isSorted(It it, Pred lessThan)
{
if(!it.hasNext()) { return true; }
ELEMENT_TYPE(It) prev = it.next();
while(it.hasNext()) {
ELEMENT_TYPE(It) curr = it.next();
if(!lessThan(prev, curr)) {
return false;
}
prev = curr;
}
return true;
}
template<class It, typename Pred>
bool forAll(It it, Pred pred)
{
while(it.hasNext()) {
if(!pred(it.next())) {
return false;
}
}
return true;
}
template<class It, typename Pred>
ELEMENT_TYPE(It) getFirstTrue(It it, Pred pred)
{
while(it.hasNext()) {
ELEMENT_TYPE(It) el = it.next();
if(pred(el)) {
return el;
}
}
ASSERTION_VIOLATION;
}
template<class It, typename Fun, typename Res>
Res fold(It it, Fun fn, Res init)
{
Res res = init;
while(it.hasNext()) {
res = fn(it.next(), res);
}
return res;
}
template<class It, typename Fun>
ELEMENT_TYPE(It) fold(It it, Fun fn)
{
ALWAYS(it.hasNext());
ELEMENT_TYPE(It) init = it.next();
return fold(it,fn,init);
}
template<typename T>
T sumFn(T a1, T a2) { return a1+a2; }
template<typename T>
T maxFn(T a1, T a2) { return std::max(a1,a2); }
template<typename T>
T minFn(T a1, T a2) { return std::min(a1,a2); }
template<class It>
struct StmJoinAuxStruct
{
StmJoinAuxStruct(std::string glue, It it) : _glue(glue), _it(it) {}
std::string _glue;
It _it;
};
template<class It>
StmJoinAuxStruct<It> join(std::string glue, It it)
{
return StmJoinAuxStruct<It>(glue, it);
}
template<typename It>
std::ostream& operator<< (std::ostream& out, const StmJoinAuxStruct<It>& info )
{
It it = info._it;
while(it.hasNext()) {
out << it.next();
if(it.hasNext()) {
out << info._glue;
}
}
return out;
}
template<class It, class Pred>
bool splitIterator(It it, Pred edge, VirtualIterator<ELEMENT_TYPE(It)>& res1, VirtualIterator<ELEMENT_TYPE(It)>& res2)
{
typedef ELEMENT_TYPE(It) T;
bool success = false;
List<T>* firstPart = 0;
while(it.hasNext()) {
T itm = it.next();
if(edge(itm)) {
success = true;
break;
}
List<T>::push(itm, firstPart);
}
firstPart = firstPart->reverse();
res1 = fpvi(typename List<T>::DestructiveIterator(firstPart));
res2 = pvi(it);
return success;
}
template<typename Inner>
struct NegPred
{
NegPred(const Inner& inner) : _inner(inner) {}
template<typename Arg>
bool operator()(Arg a) { return !_inner(a); }
private:
Inner _inner;
};
template<typename Inner>
NegPred<Inner> negPred(Inner inner) {
return NegPred<Inner>(inner);
}
template<typename T>
struct ConstEqPred
{
ConstEqPred(const T& val) : _val(val) {}
template<typename Arg>
bool operator()(Arg a) { return a==_val; }
private:
T _val;
};
template<typename T>
ConstEqPred<T> constEqPred(const T& val) {
return ConstEqPred<T>(val);
}
template<typename OuterFn, typename InnerFn>
struct CompositionFn {
CompositionFn(OuterFn outer, InnerFn inner)
: _outer(outer), _inner(inner) { }
template<typename Arg>
std::invoke_result_t<OuterFn, std::invoke_result_t<InnerFn, Arg>> operator()(Arg a) {
return _outer(_inner(a));
}
private:
OuterFn _outer;
InnerFn _inner;
};
template<typename OuterFn, typename InnerFn>
CompositionFn<OuterFn,InnerFn> getCompositionFn(OuterFn outer, InnerFn inner)
{
return CompositionFn<OuterFn,InnerFn>(outer,inner);
}
template<class P>
struct GetFirstOfPair {
typename P::first_type operator()(P p) {
return p.first;
}
};
template<class P>
struct GetSecondOfPair {
typename P::second_type operator()(P p) {
return p.second;
}
};
template<class... Is>
class CoproductIter
{
Coproduct<Is...> _inner;
public:
DECL_ELEMENT_TYPE(ELEMENT_TYPE(TypeList::Get<0, TypeList::List<Is...>>));
DEFAULT_CONSTRUCTORS(CoproductIter)
CoproductIter(Coproduct<Is...> i) : _inner(Coproduct<Is...>(std::move(i))) {}
bool hasNext() const
{
Coproduct<Is...> const& inner = _inner;;
return inner.apply([](auto& x) { return x.hasNext();}); }
bool hasNext()
{
Coproduct<Is...> & inner = _inner;;
return inner.apply([](auto& x) { return x.hasNext();}); }
OWN_ELEMENT_TYPE next()
{
Coproduct<Is...> & inner = _inner;;
return inner.apply([](auto&& x) { return x.next();}); }
bool knowsSize() const
{
Coproduct<Is...> const& inner = _inner;;
return inner.apply([](auto& x) { return x.knowsSize();}); }
size_t size() const
{
Coproduct<Is...> const& inner = _inner;;
return inner.apply([](auto& x) { return x.size();}); }
};
template<class... Is>
auto coproductIter(Coproduct<Is...> is)
{ return iterTraits(CoproductIter<Is...>(std::move(is))); }
template<class Closure>
struct ApplyClosure {
template<class A>
using apply = std::invoke_result_t<Closure, A>;
};
template<unsigned N>
struct Times {
template<class C>
using apply = Constant<C::value * N>;
};
template<unsigned N>
struct Plus {
template<class C>
using apply = Constant<C::value + N>;
};
#define LAZY(...) [&]() { return __VA_ARGS__; }
template<class A
, std::enable_if_t<!std::is_invocable_v<A>, bool> = true
>
auto makeLazy(A a)
{ return [a = std::move(a)]() mutable -> A { return std::move(a); }; }
template<class A
, std::enable_if_t<std::is_invocable_v<A>, bool> = true
>
auto makeLazy(A a) -> A
{ return a; }
template<class... Args>
static auto __ifElseIter(Args... args)
{
auto tuple = std::tie(args...);
constexpr unsigned total = TL::Size<TL::List<Args...>>::val;
auto tupleGetApplied = [&](auto N) -> decltype(auto) { return std::get<N.value>(tuple)(); };
static_assert(total % 2 == 1);
using Out = TL::Into<Coproduct,
TL::Map<
TL::Closure<decltype(tupleGetApplied)>,
TL::Concat<
TL::Map<Plus<1>, TL::Map<Times<2>, TL::Range<0, total / 2>>>,
TL::List<Constant<total - 1>>
>>>;
Option<Out> out;
TL::Range<0, total / 2>::forEach([&](auto token){
constexpr unsigned i = TL::TokenType<decltype(token)>::value;
if (out.isNone()) {
if (tupleGetApplied(Constant<2*i>{})) {
out = some(Out::template variant<i>(tupleGetApplied(Constant<2*i + 1>{})));
}
}
});
return coproductIter(out ? std::move(*out) : Out::template variant<total/2>(tupleGetApplied(Constant<total - 1>{})));
}
template<class... Args>
static auto ifElseIter(Args... args)
{ return __ifElseIter(makeLazy(std::move(args))...); }
#define ifElseIter2(i0, t0, e) ifElseIter(LAZY(i0), LAZY(t0), LAZY(e))
#define ifElseIter3(i0, t0, i1, t1, e) ifElseIter(LAZY(i0), LAZY(t0), LAZY(i1), LAZY(t1), LAZY(e))
#define ifElseIter4(i0, t0, i1, t1, i2, t2, e) ifElseIter(LAZY(i0), LAZY(t0), LAZY(i1), LAZY(t1), LAZY(i2), LAZY(t2), LAZY(e))
template<class IfIterCons>
static auto ifIter(bool cond, IfIterCons ifCons)
{ return iterTraits(someIf(cond, std::move(ifCons)).intoIter()).flatten(); }
template<class T>
struct EmptyIter
{
DECL_ELEMENT_TYPE(T);
bool hasNext() { return false; }
T next() { ASSERTION_VIOLATION }
unsigned size() { return 0; }
bool knowsSize() { return true; }
};
template<class Pointer>
class IterPointer
{
Pointer _p;
public:
IterPointer(Pointer p) : _p(std::move(p)) {}
DEFAULT_CONSTRUCTORS(IterPointer);
DECL_ELEMENT_TYPE(ELEMENT_TYPE(std::remove_reference_t<decltype(*_p)>));
bool hasNext() { return (*_p).hasNext(); }
bool hasNext() const { return (*_p).hasNext(); }
OWN_ELEMENT_TYPE next() { return (*_p).next(); }
unsigned size() { return (*_p).size(); }
bool knowsSize() { return (*_p).knowsSize(); }
};
template<class Iter>
class IterTraits
{
Iter _iter;
public:
DECL_ELEMENT_TYPE(ELEMENT_TYPE(Iter));
DEFAULT_CONSTRUCTORS(IterTraits)
using Elem = ELEMENT_TYPE(Iter);
explicit IterTraits(Iter iter) : _iter(std::move(iter)) {}
Elem next()
{ return move_if_value<Elem>(_iter.next()); }
bool hasNext()
{ return _iter.hasNext(); }
bool knowsSize() { return _iter.knowsSize(); }
bool knowsSize() const { return _iter.knowsSize(); }
auto size() { return _iter.size(); }
auto size() const { return _iter.size(); }
Option<Elem> tryNext()
{
return _iter.hasNext()
? Option<Elem>(move_if_value<Elem>(_iter.next()))
: Option<Elem>();
}
template<class P>
bool any(P f)
{
while (hasNext()) {
if (f(next())) return true;
}
return false;
}
template<class P>
bool all(P f)
{
while (hasNext()) {
if (!f(next())) return false;
}
return true;
}
template<class F>
void forEach(F f)
{
while (hasNext()) {
f(next());
}
}
template<class F>
void enumerate(F f)
{
unsigned i = 0;
while (hasNext()) {
f(i++, next());
}
}
template<class P>
Option<Elem> find(P p)
{
while (hasNext()) {
Elem x = next();
if (p(x)) {
return some<Elem>(x);
}
}
return none<Elem>();
}
template<class P>
Option<unsigned> findPosition(P p)
{
unsigned i = 0;
while (hasNext()) {
Elem x = next();
if (p(x)) {
return some<unsigned>(i);
}
i++;
}
return none<unsigned>();
}
template<class... Is>
auto concat(Is... is)
{ return concatIters(std::move(_iter), std::move(is)...); }
template<class F>
IterTraits<MappingIterator<Iter, F>> map(F f)
{ return iterTraits(getMappingIterator<Iter, F>(std::move(_iter), std::move(f))); }
auto eval()
{ return map([](auto f){ return f(); }); }
template<class F>
auto inspect(F f)
{ return map([f = std::move(f)](auto x) { f(x); return x; }); }
template<class F>
IterTraits<FilteredIterator<Iter, F>> filter(F f)
{ return iterTraits(getFilteredIterator<Iter, F>(std::move(_iter), std::move(f))); }
template<class F>
IterTraits<FilterMapIter<Iter, F>> filterMap(F f)
{ return iterTraits(FilterMapIter<Iter, F>(std::move(_iter), std::move(f))); }
template<class F>
IterTraits<FlatMapIter<Iter, F>> flatMap(F f)
{ return iterTraits(getFlattenedIterator(getMappingIterator(std::move(_iter), std::move(f)))); }
auto flatten()
{ return iterTraits(getFlattenedIterator(std::move(_iter))); }
template<class Pred>
auto takeWhile(Pred p)
{ return iterTraits(TakeWhileIter<Iter, Pred>(std::move(_iter), std::move(p))); }
auto unique()
{
Map<OWN_ELEMENT_TYPE, std::tuple<>> found;
return iterTraits(std::move(*this)
.filterMap([found = std::move(found)](OWN_ELEMENT_TYPE next) mutable {
if (found.tryGet(next).isSome()) {
return Option<OWN_ELEMENT_TYPE>();
} else {
found.insert(next, std::make_tuple());
return Option<OWN_ELEMENT_TYPE>(std::move(next));
}
}));
}
auto persistent()
{
auto stack = collect<Stack>();
return iterTraits(arrayIter(std::move(stack)));
}
template<class IsLess>
Option<Elem> minBy(IsLess isLess)
{
if (hasNext()) {
Elem min = next();
while (hasNext()) {
Elem e = next();
if (isLess(e, min)) {
min = e;
}
}
return some<Elem>(min);
} else {
return none<Elem>();
}
}
unsigned count()
{
unsigned i = 0;
while (hasNext()) {
i++;
next();
}
return i;
}
auto output() const
{ return Output::interleaved(", ", *this); }
template<class Separator>
auto output(Separator const& sep) const
{ return Output::interleaved(sep, *this); }
Option<Elem> min()
{ return minBy(std::less<Elem>{}); }
template<class IsLess>
Option<Elem> maxBy(IsLess isLess)
{ return minBy([isLess = std::move(isLess)](Elem const& l, Elem const& r) { return isLess(r,l); }); }
Option<Elem> max()
{ return maxBy(std::less<Elem>{}); }
auto timeTraced(const char* name)
{ return iterTraits(TIME_TRACE_ITER(name, std::move(_iter))); }
template<class Result, class F>
auto fold(Result init, F f) -> Result
{
Result accum = std::move(init);
while (hasNext()) {
accum = f(std::move(accum), next());
}
return accum;
}
template<class F>
auto fold(F fun) -> Option<Elem>
{ return someIf(hasNext(), [&]() { return fold(next(), std::move(fun)); }); }
template<class OtherIter>
auto zip(OtherIter other)
{ return map([other = std::move(other)](Elem x) mutable { ALWAYS(other.hasNext()); return std::make_pair(std::move(x), other.next()); }); }
auto zipWithIndex()
{ return map([idx = 0](Elem x) mutable { return std::make_pair(std::move(x), idx++); }); }
template<class Val>
auto store(Val v)
{ return map([v = std::move(v)](Elem x) -> Elem { return x; }); }
auto reverse() &&
{ return iterTraits(std::move(_iter).reverse()); }
auto sum()
{ return fold([](Elem l, Elem r) { return l + r; }) || []() { return Elem(0); }; }
template<unsigned n>
auto collectTuple()
{ return TL::Range<0, n>::toTuple([&](auto i) { return next(); }); }
template<class Container>
auto collect()
{ return Container::fromIterator(*this); }
template<template<class> class Container>
Container<Elem> collect()
{
return Container<Elem>::fromIterator(std::move(*this));
}
IterTraits clone()
{ return *this; }
class StlIter
{
Option<IterTraits&> _iter; Option<Elem> _cur;
public:
StlIter(IterTraits& iter) : _iter(Option<IterTraits&>(iter)), _cur(iter.tryNext()) {}
StlIter() : _iter(), _cur() {}
void operator++()
{ _cur = _iter.unwrap().tryNext(); }
Elem operator*()
{ return move_if_value<Elem>(_cur.unwrap()); }
friend bool operator!=(StlIter const& lhs, StlIter const& rhs)
{ return !(lhs == rhs); }
friend bool operator==(StlIter const& lhs, StlIter const& rhs)
{
ASS(rhs._iter.isNone());
ASS(lhs._iter.isSome());
return lhs._cur.isNone();
}
};
public:
StlIter begin() { return StlIter(*this); }
StlIter end() { return StlIter(); }
};
template<class Iter>
IterTraits<Iter> iterTraits(Iter i) { return IterTraits<Iter>(std::move(i)); }
static const auto range = [](auto from, auto to)
{ return iterTraits(getRangeIterator<decltype(to)>(decltype(to)(from), to)); };
template<class I1>
static auto concatIters(I1 i1)
{ return iterTraits(std::move(i1)); }
template<class I1, class I2, class... Is>
static auto concatIters(I1 i1, I2 i2, Is... is)
{ return iterTraits(CatIterator<I1, decltype(concatIters(std::move(i2), std::move(is)...))>(std::move(i1), concatIters(std::move(i2), std::move(is)...))); }
template<class I1, class I2, class Cmp>
auto iterSortedDiff(I1 i1, I2 i2, Cmp cmp)
{ return iterTraits(SortedIterDiff<I1,I2, Cmp>(std::move(i1), std::move(i2), std::move(cmp))); }
template<class I1, class I2>
auto iterSortedDiff(I1 i1, I2 i2)
{ return iterSortedDiff(std::move(i1), std::move(i2), [&](auto& l, auto& r) { return l == r ? 0 : l < r ? -1 : 1; }); }
template<class P>
auto iterPointer(P p) { return iterTraits(IterPointer<P>(std::move(p))); }
template<class Iterator>
auto dropElementType(Iterator iter)
{ return iterTraits(std::move(iter)).map([](auto _) { return std::make_tuple(); }); }
template<class Array, class Size>
auto arrayIter(Array const& a, Size s) { return range(0, s).map([&](auto i) -> decltype(auto) { return a[i]; }); }
template<class Array, class Size>
auto arrayIter(Array & a, Size s) { return range(0, s).map([&](auto i) -> decltype(auto) { return a[i]; }); }
template<class Array, class Size>
auto arrayIter(Array && a, Size s) { return range(0, s).map([a = std::move(a)](auto i) mutable { return std::move(a[i]); }); }
template<class Array> auto arrayIter(Array const& a) { return arrayIter( a , a.size()); }
template<class Array> auto arrayIter(Array && a) { return arrayIter(std::move(a), a.size()); }
template<class Array> auto arrayIter(Array & a) { return arrayIter( a , a.size()); }
template<class Item, class... Items>
auto iterItems(Item item, Items... items)
{ return arrayIter(Stack<Item>{Item(std::move(item)), Item(std::move(items))...}); }
template<class Item>
auto iterItems()
{ return arrayIter(Stack<Item>{}); }
}
template <typename Iterator>
class STLIterator
{
private:
Iterator begin;
Iterator end;
public:
using value_type = typename Iterator::value_type;
DECL_ELEMENT_TYPE(value_type);
STLIterator(Iterator begin, Iterator end)
: begin(begin), end(end)
{ }
bool hasNext() {
return begin != end;
}
value_type next() {
value_type x = *begin;
++begin;
return x;
}
};
template <typename Iterator>
STLIterator<Iterator> getSTLIterator(Iterator begin, Iterator end)
{
return STLIterator<Iterator>(begin, end);
}
template<class Inner>
auto getPersistentIterator(Inner it)
{ return pvi(arrayIter(iterTraits(std::move(it)).template collect<Stack>())); }
template<class Iter>
class IterContOps {
Iter const _iter;
public:
IterContOps(Iter iter) : _iter(std::move(iter)) {}
auto defaultHash() const { return DefaultHash::hashIter(Iter(_iter).map([](ELEMENT_TYPE(Iter) x) -> unsigned { return DefaultHash::hash(x); })); }
auto defaultHash2() const { return DefaultHash::hashIter(Iter(_iter).map([](ELEMENT_TYPE(Iter) x) -> unsigned { return DefaultHash2::hash(x); })); }
static int cmp(IterContOps const& lhs, IterContOps const& rhs) {
auto l = lhs._iter;
auto r = rhs._iter;
while (l.hasNext() && r.hasNext()) {
auto ln = l.next();
auto rn = r.next();
if (ln < rn) {
return -1;
} else if (rn < ln) {
return 1;
}
}
return !l.hasNext() ? (r.hasNext() ? -1 : 0) : 1;
}
friend bool operator<(IterContOps const& lhs, IterContOps const& rhs)
{ return cmp(lhs, rhs) < 0; }
friend bool operator==(IterContOps const& lhs, IterContOps const& rhs)
{ return cmp(lhs, rhs) == 0; }
friend bool operator!=(IterContOps const& lhs, IterContOps const& rhs)
{ return !(lhs == rhs); }
};
template<class Iter>
auto iterContOps(Iter iter) { return IterContOps<Iter>(std::move(iter)); }
template<class A, class Iter>
Iter assertIter(Iter iter) {
static_assert(std::is_same_v<A ,ELEMENT_TYPE(Iter)>
&& std::is_same_v<A , decltype(iter.next())>
&& std::is_same_v<bool, decltype(iter.hasNext())>
);
return iter;
}
#endif