/* Ranges for OctaSTD. * * This file is part of OctaSTD. See COPYING.md for futher information. */ #ifndef OCTA_RANGE_H #define OCTA_RANGE_H #include #include "octa/types.h" #include "octa/utility.h" #include "octa/type_traits.h" namespace octa { struct InputRangeTag {}; struct OutputRangeTag {}; struct ForwardRangeTag: InputRangeTag {}; struct BidirectionalRangeTag: ForwardRangeTag {}; struct RandomAccessRangeTag: BidirectionalRangeTag {}; struct FiniteRandomAccessRangeTag: RandomAccessRangeTag {}; template struct RangeHalf; #define __OCTA_RANGE_TRAIT(_Name, _TypeName) \ template \ struct __OctaRange##_Name { \ typedef typename _T::_TypeName Type; \ }; \ template \ struct __OctaRange##_Name> { \ typedef typename _T::_TypeName Type; \ }; \ template \ using Range##_Name = typename __OctaRange##_Name<_T>::Type; __OCTA_RANGE_TRAIT(Category, Category) __OCTA_RANGE_TRAIT(Size, Size) __OCTA_RANGE_TRAIT(Value, Value) __OCTA_RANGE_TRAIT(Reference, Reference) __OCTA_RANGE_TRAIT(Difference, Difference) #undef __OCTA_RANGE_TRAIT // is input range template, InputRangeTag >::value> struct IsInputRange: False {}; template struct IsInputRange<_T, true>: True {}; // is forward range template, ForwardRangeTag >::value> struct IsForwardRange: False {}; template struct IsForwardRange<_T, true>: True {}; // is bidirectional range template, BidirectionalRangeTag >::value> struct IsBidirectionalRange: False {}; template struct IsBidirectionalRange<_T, true>: True {}; // is random access range template, RandomAccessRangeTag >::value> struct IsRandomAccessRange: False {}; template struct IsRandomAccessRange<_T, true>: True {}; // is finite random access range template, FiniteRandomAccessRangeTag >::value> struct IsFiniteRandomAccessRange: False {}; template struct IsFiniteRandomAccessRange<_T, true>: True {}; // is infinite random access range template struct IsInfiniteRandomAccessRange: IntegralConstant::value && !IsFiniteRandomAccessRange<_T>::value) > {}; // is output range template struct __OctaOutputRangeTest { template struct __Test {}; template static char __test(__Test<_U, &_U::put> *); template static int __test(...); static constexpr bool value = (sizeof(__test<_T>(0)) == sizeof(char)); }; template, OutputRangeTag >::value || (IsInputRange<_T>::value && (__OctaOutputRangeTest<_T, const RangeValue<_T> &>::value || __OctaOutputRangeTest<_T, RangeValue<_T> &&>::value) ))> struct IsOutputRange: False {}; template struct IsOutputRange<_T, true>: True {}; // range iterator template struct __OctaRangeIterator { __OctaRangeIterator(): __range() {} explicit __OctaRangeIterator(const _T &__range): __range(__range) {} __OctaRangeIterator &operator++() { __range.pop_front(); return *this; } RangeReference<_T> operator*() const { return __range.front(); } bool operator!=(__OctaRangeIterator) const { return !__range.empty(); } private: _T __range; }; // range half template struct RangeHalf { private: _T __range; public: typedef _T Range; RangeHalf(): __range() {} RangeHalf(const _T &__range): __range(__range) {} RangeHalf(const RangeHalf &__half): __range(__half.__range) {} RangeHalf(RangeHalf &&__half): __range(octa::move(__half.__range)) {} RangeHalf &operator=(const RangeHalf &__half) { __range = __half.__range; return *this; } RangeHalf &operator=(RangeHalf &&__half) { __range = octa::move(__half.__range); return *this; } _T range() const { return __range; } bool next() { return __range.pop_front(); } bool prev() { return __range.push_front(); } RangeSize<_T> next_n(RangeSize<_T> __n) { return __range.pop_front_n(__n); } RangeSize<_T> prev_n(RangeSize<_T> __n) { return __range.push_front_n(__n); } RangeReference<_T> get() const { return __range.front(); } RangeDifference<_T> distance(const RangeHalf &__half) const { return __range.distance_front(__half.__range); } bool equals(const RangeHalf &__half) const { return __range.equals_front(__half.__range); } bool operator==(const RangeHalf &__half) const { return equals(__half); } bool operator!=(const RangeHalf &__half) const { return !equals(__half); } /* iterator like interface */ RangeReference<_T> operator*() const { return get(); } RangeReference<_T> operator[](RangeSize<_T> __idx) const { return __range[__idx]; } RangeHalf &operator++() { next(); return *this; } RangeHalf operator++(int) { RangeHalf __tmp(*this); next(); return octa::move(__tmp); } RangeHalf &operator--() { prev(); return *this; } RangeHalf operator--(int) { RangeHalf __tmp(*this); prev(); return octa::move(__tmp); } RangeHalf operator+(RangeDifference<_T> __n) { RangeHalf __tmp(*this); if (__n < 0) __tmp.prev_n(-__n); else __tmp.next_n(__n); return octa::move(__tmp); } RangeHalf operator-(RangeDifference<_T> __n) { RangeHalf __tmp(*this); if (__n < 0) __tmp.next_n(-__n); else __tmp.prev_n(__n); return octa::move(__tmp); } RangeHalf &operator+=(RangeDifference<_T> __n) { if (__n < 0) prev_n(-__n); else next_n(__n); return *this; } RangeHalf &operator-=(RangeDifference<_T> __n) { if (__n < 0) next_n(-__n); else prev_n(__n); return *this; } }; template RangeDifference<_R> operator-(const _R &__lhs, const _R &__rhs) { return __rhs.distance(__lhs); } template RangeSize<_R> __octa_pop_front_n(_R &__range, RangeSize<_R> __n) { for (RangeSize<_R> __i = 0; __i < __n; ++__i) if (!__range.pop_front()) return __i; return __n; } template RangeSize<_R> __octa_pop_back_n(_R &__range, RangeSize<_R> __n) { for (RangeSize<_R> __i = 0; __i < __n; ++__i) if (!__range.pop_back()) return __i; return __n; } template RangeSize<_R> __octa_push_front_n(_R &__range, RangeSize<_R> __n) { for (RangeSize<_R> __i = 0; __i < __n; ++__i) if (!__range.push_front()) return __i; return __n; } template RangeSize<_R> __octa_push_back_n(_R &__range, RangeSize<_R> __n) { for (RangeSize<_R> __i = 0; __i < __n; ++__i) if (!__range.push_back()) return __i; return __n; } template struct InputRange { typedef _C Category; typedef _S Size; typedef _D Difference; typedef _V Value; typedef _R Reference; __OctaRangeIterator<_B> begin() const { return __OctaRangeIterator<_B>((const _B &)*this); } __OctaRangeIterator<_B> end() const { return __OctaRangeIterator<_B>(); } Size pop_front_n(Size __n) { return __octa_pop_front_n<_B>(*((_B *)this), __n); } Size pop_back_n(Size __n) { return __octa_pop_back_n<_B>(*((_B *)this), __n); } Size push_front_n(Size __n) { return __octa_push_front_n<_B>(*((_B *)this), __n); } Size push_back_n(Size __n) { return __octa_push_back_n<_B>(*((_B *)this), __n); } _B each() const { return _B(*((_B *)this)); } RangeHalf<_B> half() const { return RangeHalf<_B>(*((_B *)this)); } }; template struct OutputRange { typedef OutputRangeTag Category; typedef _S Size; typedef _D Difference; typedef _V Value; typedef _R Reference; }; template struct ReverseRange: InputRange, RangeCategory<_T>, RangeValue<_T>, RangeReference<_T>, RangeSize<_T>, RangeDifference<_T> > { private: typedef RangeReference<_T> _r_ref; typedef RangeSize<_T> _r_size; _T __range; public: ReverseRange(): __range() {} ReverseRange(const _T &__range): __range(__range) {} ReverseRange(const ReverseRange &__it): __range(__it.__range) {} ReverseRange(ReverseRange &&__it): __range(octa::move(__it.__range)) {} ReverseRange &operator=(const ReverseRange &__v) { __range = __v.__range; return *this; } ReverseRange &operator=(ReverseRange &&__v) { __range = octa::move(__v.__range); return *this; } ReverseRange &operator=(const _T &__v) { __range = __v; return *this; } ReverseRange &operator=(_T &&__v) { __range = octa::move(__v); return *this; } bool empty() const { return __range.empty(); } _r_size size() const { return __range.size(); } bool equals_front(const ReverseRange &__r) const { return __range.equals_back(__r.__range); } bool equals_back(const ReverseRange &__r) const { return __range.equals_front(__r.__range); } RangeDifference<_T> distance_front(const ReverseRange &__r) const { return -__range.distance_back(__r.__range); } RangeDifference<_T> distance_back(const ReverseRange &__r) const { return -__range.distance_front(__r.__range); } bool pop_front() { return __range.pop_back(); } bool pop_back() { return __range.pop_front(); } bool push_front() { return __range.push_back(); } bool push_back() { return __range.push_front(); } _r_size pop_front_n(_r_size __n) { return __range.pop_front_n(__n); } _r_size pop_back_n(_r_size __n) { return __range.pop_back_n(__n); } _r_size push_front_n(_r_size __n) { return __range.push_front_n(__n); } _r_size push_back_n(_r_size __n) { return __range.push_back_n(__n); } _r_ref front() const { return __range.back(); } _r_ref back() const { return __range.front(); } _r_ref operator[](_r_size __i) const { return __range[size() - __i - 1]; } ReverseRange<_T> slice(_r_size __start, _r_size __end) const { _r_size __len = __range.size(); return ReverseRange<_T>(__range.slice(__len - __end, __len - __start)); } }; template ReverseRange<_T> make_reverse_range(const _T &__it) { return ReverseRange<_T>(__it); } template struct MoveRange: InputRange, RangeCategory<_T>, RangeValue<_T>, RangeValue<_T> &&, RangeSize<_T>, RangeDifference<_T> > { private: typedef RangeValue<_T> _r_val; typedef RangeValue<_T> &&_r_ref; typedef RangeSize<_T> _r_size; _T __range; public: MoveRange(): __range() {} MoveRange(const _T &__range): __range(__range) {} MoveRange(const MoveRange &__it): __range(__it.__range) {} MoveRange(MoveRange &&__it): __range(octa::move(__it.__range)) {} MoveRange &operator=(const MoveRange &__v) { __range = __v.__range; return *this; } MoveRange &operator=(MoveRange &&__v) { __range = octa::move(__v.__range); return *this; } MoveRange &operator=(const _T &__v) { __range = __v; return *this; } MoveRange &operator=(_T &&__v) { __range = octa::move(__v); return *this; } bool empty() const { return __range.empty(); } _r_size size() const { return __range.size(); } bool equals_front(const MoveRange &__r) const { return __range.equals_front(__r.__range); } bool equals_back(const MoveRange &__r) const { return __range.equals_back(__r.__range); } RangeDifference<_T> distance_front(const MoveRange &__r) const { return __range.distance_front(__r.__range); } RangeDifference<_T> distance_back(const MoveRange &__r) const { return __range.distance_back(__r.__range); } bool pop_front() { return __range.pop_front(); } bool pop_back() { return __range.pop_back(); } bool push_front() { return __range.push_front(); } bool push_back() { return __range.push_back(); } _r_size pop_front_n(_r_size __n) { return __range.pop_front_n(__n); } _r_size pop_back_n(_r_size __n) { return __range.pop_back_n(__n); } _r_size push_front_n(_r_size __n) { return __range.push_front_n(__n); } _r_size push_back_n(_r_size __n) { return __range.push_back_n(__n); } _r_ref front() const { return octa::move(__range.front()); } _r_ref back() const { return octa::move(__range.back()); } _r_ref operator[](_r_size __i) const { return octa::move(__range[__i]); } MoveRange<_T> slice(_r_size __start, _r_size __end) const { return MoveRange<_T>(__range.slice(__start, __end)); } void put(const _r_val &__v) { __range.put(__v); } void put(_r_val &&__v) { __range.put(octa::move(__v)); } }; template MoveRange<_T> make_move_range(const _T &__it) { return MoveRange<_T>(__it); } template struct NumberRange: InputRange, ForwardRangeTag, _T, _T> { NumberRange(): __a(0), __b(0), __step(0) {} NumberRange(const NumberRange &__it): __a(__it.__a), __b(__it.__b), __step(__it.__step) {} NumberRange(_T __a, _T __b, _T __step = _T(1)): __a(__a), __b(__b), __step(__step) {} NumberRange(_T __v): __a(0), __b(__v), __step(1) {} bool empty() const { return __a * __step >= __b * __step; } bool equals_front(const NumberRange &__range) const { return __a == __range.__a; } bool pop_front() { __a += __step; return true; } bool push_front() { __a -= __step; return true; } _T front() const { return __a; } private: _T __a, __b, __step; }; template NumberRange<_T> range(_T __a, _T __b, _T __step = _T(1)) { return NumberRange<_T>(__a, __b, __step); } template NumberRange<_T> range(_T __v) { return NumberRange<_T>(__v); } template struct PointerRange: InputRange, FiniteRandomAccessRangeTag, _T> { PointerRange(): __beg(nullptr), __end(nullptr) {} PointerRange(const PointerRange &__v): __beg(__v.__beg), __end(__v.__end) {} PointerRange(_T *__beg, _T *__end): __beg(__beg), __end(__end) {} PointerRange(_T *__beg, size_t __n): __beg(__beg), __end(__beg + __n) {} PointerRange &operator=(const PointerRange &__v) { __beg = __v.__beg; __end = __v.__end; return *this; } /* satisfy InputRange / ForwardRange */ bool empty() const { return __beg == __end; } bool pop_front() { if (__beg == __end) return false; ++__beg; return true; } bool push_front() { --__beg; return true; } size_t pop_front_n(size_t __n) { size_t __olen = __end - __beg; __beg += __n; if (__beg > __end) { __beg = __end; return __olen; } return __n; } size_t push_front_n(size_t __n) { __beg -= __n; return true; } _T &front() const { return *__beg; } bool equals_front(const PointerRange &__range) const { return __beg == __range.__beg; } ptrdiff_t distance_front(const PointerRange &__range) const { return __range.__beg - __beg; } /* satisfy BidirectionalRange */ bool pop_back() { if (__end == __beg) return false; --__end; return true; } bool push_back() { ++__end; return true; } size_t pop_back_n(size_t __n) { size_t __olen = __end - __beg; __end -= __n; if (__end < __beg) { __end = __beg; return __olen; } return __n; } size_t push_back_n(size_t __n) { __end += __n; return true; } _T &back() const { return *(__end - 1); } bool equals_back(const PointerRange &__range) const { return __end == __range.__end; } ptrdiff_t distance_back(const PointerRange &__range) const { return __range.__end - __end; } /* satisfy FiniteRandomAccessRange */ size_t size() const { return __end - __beg; } PointerRange slice(size_t __start, size_t __end) const { return PointerRange(__beg + __start, __beg + __end); } _T &operator[](size_t __i) const { return __beg[__i]; } /* satisfy OutputRange */ void put(const _T &__v) { *(__beg++) = __v; } void put(_T &&__v) { *(__beg++) = octa::move(__v); } private: _T *__beg, *__end; }; template struct EnumeratedValue { _S index; _T value; }; template struct EnumeratedRange: InputRange, CommonType, ForwardRangeTag>, RangeValue<_T>, EnumeratedValue, RangeSize<_T>>, RangeSize<_T> > { private: typedef RangeReference<_T> _r_ref; typedef RangeSize<_T> _r_size; _T __range; _r_size __index; public: EnumeratedRange(): __range(), __index(0) {} EnumeratedRange(const _T &__range): __range(__range), __index(0) {} EnumeratedRange(const EnumeratedRange &__it): __range(__it.__range), __index(__it.__index) {} EnumeratedRange(EnumeratedRange &&__it): __range(octa::move(__it.__range)), __index(__it.__index) {} EnumeratedRange &operator=(const EnumeratedRange &__v) { __range = __v.__range; __index = __v.__index; return *this; } EnumeratedRange &operator=(EnumeratedRange &&__v) { __range = octa::move(__v.__range); __index = __v.__index; return *this; } EnumeratedRange &operator=(const _T &__v) { __range = __v; __index = 0; return *this; } EnumeratedRange &operator=(_T &&__v) { __range = octa::move(__v); __index = 0; return *this; } bool empty() const { return __range.empty(); } bool equals_front(const EnumeratedRange &__r) const { return __range.equals_front(__r.__range); } bool pop_front() { if (__range.pop_front()) { ++__index; return true; } return false; } _r_size pop_front_n(_r_size __n) { _r_size __ret = __range.pop_front_n(__n); __index += __ret; return __ret; } EnumeratedValue<_r_ref, _r_size> front() const { return EnumeratedValue<_r_ref, _r_size> { __index, __range.front() }; } }; template EnumeratedRange<_T> enumerate(const _T &__it) { return EnumeratedRange<_T>(__it); } template struct TakeRange: InputRange, CommonType, ForwardRangeTag>, RangeValue<_T>, RangeReference<_T>, RangeSize<_T> > { private: _T __range; RangeSize<_T> __remaining; public: TakeRange(): __range(), __remaining(0) {} TakeRange(const _T &__range, RangeSize<_T> __rem): __range(__range), __remaining(__rem) {} TakeRange(const TakeRange &__it): __range(__it.__range), __remaining(__it.__remaining) {} TakeRange(TakeRange &&__it): __range(octa::move(__it.__range)), __remaining(__it.__remaining) {} TakeRange &operator=(const TakeRange &__v) { __range = __v.__range; __remaining = __v.__remaining; return *this; } TakeRange &operator=(TakeRange &&__v) { __range = octa::move(__v.__range); __remaining = __v.__remaining; return *this; } bool empty() const { return (__remaining <= 0) || __range.empty(); } bool pop_front() { if (__range.pop_front()) { --__remaining; return true; } return false; } bool push_front() { if (__range.push_front()) { ++__remaining; return true; } return false; } RangeSize<_T> pop_front_n(RangeSize<_T> __n) { RangeSize<_T> __ret = __range.pop_front_n(__n); __remaining -= __ret; return __ret; } RangeSize<_T> push_front_n(RangeSize<_T> __n) { RangeSize<_T> __ret = __range.push_front_n(__n); __remaining += __ret; return __ret; } RangeReference<_T> front() const { return __range.front(); } bool equals_front(const TakeRange &__r) const { return __range.equals_front(__r.__range); } RangeDifference<_T> distance_front(const TakeRange &__r) const { return __range.distance_front(__r.__range); } }; template TakeRange<_T> take(const _T &__it, RangeSize<_T> __n) { return TakeRange<_T>(__it, __n); } template struct ChunksRange: InputRange, CommonType, ForwardRangeTag>, TakeRange<_T>, TakeRange<_T>, RangeSize<_T> > { private: _T __range; RangeSize<_T> __chunksize; public: ChunksRange(): __range(), __chunksize(0) {} ChunksRange(const _T &__range, RangeSize<_T> __chs): __range(__range), __chunksize(__chs) {} ChunksRange(const ChunksRange &__it): __range(__it.__range), __chunksize(__it.__chunksize) {} ChunksRange(ChunksRange &&__it): __range(octa::move(__it.__range)), __chunksize(__it.__chunksize) {} ChunksRange &operator=(const ChunksRange &__v) { __range = __v.__range; __chunksize = __v.p_chunksize; return *this; } ChunksRange &operator=(ChunksRange &&__v) { __range = octa::move(__v.__range); __chunksize = __v.__chunksize; return *this; } bool empty() const { return __range.empty(); } bool equals_front(const ChunksRange &__r) const { return __range.equals_front(__r.__range); } bool pop_front() { return __range.pop_front_n(__chunksize) > 0; } bool push_front() { _T __tmp = __range; RangeSize<_T> __an = __tmp.push_front_n(__chunksize); if (__an != __chunksize) return false; __range = __tmp; return true; } RangeSize<_T> pop_front_n(RangeSize<_T> __n) { return __range.pop_front_n(__chunksize * __n) / __chunksize; } RangeSize<_T> push_front_n(RangeSize<_T> __n) { _T __tmp = __range; RangeSize<_T> __an = __tmp.push_front_n(__chunksize * __n); RangeSize<_T> __pn = __an / __chunksize; if (!__pn) return 0; if (__pn == __n) { __range = __tmp; return __pn; } return __range.push_front_n(__chunksize * __an) / __chunksize; } TakeRange<_T> front() const { return take(__range, __chunksize); } }; template ChunksRange<_T> chunks(const _T &__it, RangeSize<_T> __chs) { return ChunksRange<_T>(__it, __chs); } template auto each(_T &__r) -> decltype(__r.each()) { return __r.each(); } template auto each(const _T &__r) -> decltype(__r.each()) { return __r.each(); } template PointerRange<_T> each(_T (&__array)[_N]) { return PointerRange<_T>(__array, _N); } // range of template using RangeOf = decltype(octa::each(octa::declval<_T>())); template struct HalfRange: InputRange, RangeCategory<_T>, RangeValue<_T>, RangeReference<_T>, RangeSize<_T>, RangeDifference<_T> > { private: _T __beg; _T __end; public: HalfRange(): __beg(), __end() {} HalfRange(const HalfRange &__range): __beg(__range.__beg), __end(__range.__end) {} HalfRange(HalfRange &&__range): __beg(octa::move(__range.__beg)), __end(octa::move(__range.__end)) {} HalfRange(const _T &__beg, const _T &__end): __beg(__beg), __end(__end) {} HalfRange(_T &&__beg, _T &&__end): __beg(octa::move(__beg)), __end(octa::move(__end)) {} HalfRange &operator=(const HalfRange &__range) { __beg = __range.p_beg; __end = __range.p_end; return *this; } HalfRange &operator=(HalfRange &&__range) { __beg = octa::move(__range.p_beg); __end = octa::move(__range.p_end); return *this; } bool empty() const { return __beg == __end; } bool pop_front() { if (empty()) return false; return __beg.next(); } bool push_front() { return __beg.prev(); } bool pop_back() { if (empty()) return false; return __end.prev(); } bool push_back() { return __end.next(); } RangeReference<_T> front() const { return *__beg; } RangeReference<_T> back() const { return *(__end - 1); } bool equals_front(const HalfRange &__range) const { return __beg == __range.__beg; } bool equals_back(const HalfRange &__range) const { return __end == __range.__end; } RangeDifference<_T> distance_front(const HalfRange &__range) const { return __range.__beg - __beg; } RangeDifference<_T> distance_back(const HalfRange &__range) const { return __range.__end - __end; } RangeSize<_T> size() const { return __end - __beg; } HalfRange<_T> slice(RangeSize<_T> __start, RangeSize<_T> __end) const { return HalfRange<_T>(__beg + __start, __beg + __end); } RangeReference<_T> operator[](RangeSize<_T> __idx) const { return __beg[__idx]; } void put(const RangeValue<_T> &__v) { __beg.range().put(__v); } void put(RangeValue<_T> &&__v) { __beg.range().put(octa::move(__v)); } }; template HalfRange> make_half_range(const RangeHalf<_T> &__a, const RangeHalf<_T> &__b) { return HalfRange>(__a, __b); } } #endif