// algorithm standard header #pragma once #ifndef _ALGORITHM_ #define _ALGORITHM_ #include #pragma pack(push,8) #pragma warning(push,3) #pragma warning(disable: 4244) _STD_BEGIN // COMMON SORT PARAMETERS const int _ISORT_MAX = 32; // maximum size for insertion sort // TEMPLATE FUNCTION for_each template inline _Fn1 for_each(_InIt _First, _InIt _Last, _Fn1 _Func) { // perform function for each element for (; _First != _Last; ++_First) _Func(*_First); return (_Func); } // TEMPLATE FUNCTION find template inline _InIt find(_InIt _First, _InIt _Last, const _Ty& _Val) { // find first matching _Val for (; _First != _Last; ++_First) if (*_First == _Val) break; return (_First); } inline const char *find(const char *_First, const char *_Last, int _Val) { // find first char that matches _Val _First = (const char *)::memchr(_First, _Val, _Last - _First); return (_First == 0 ? _Last : _First); } inline const signed char *find(const signed char *_First, const signed char *_Last, int _Val) { // find first signed char that matches _Val _First = (const signed char *)::memchr(_First, _Val, _Last - _First); return (_First == 0 ? _Last : _First); } inline const unsigned char *find(const unsigned char *_First, const unsigned char *_Last, int _Val) { // find first unsigned char that matches _Val _First = (const unsigned char *)::memchr(_First, _Val, _Last - _First); return (_First == 0 ? _Last : _First); } // TEMPLATE FUNCTION find_if template inline _InIt find_if(_InIt _First, _InIt _Last, _Pr _Pred) { // find first satisfying _Pred for (; _First != _Last; ++_First) if (_Pred(*_First)) break; return (_First); } // TEMPLATE FUNCTION adjacent_find template inline _FwdIt adjacent_find(_FwdIt _First, _FwdIt _Last) { // find first matching successor for (_FwdIt _Firstb; (_Firstb = _First) != _Last && ++_First != _Last; ) if (*_Firstb == *_First) return (_Firstb); return (_Last); } // TEMPLATE FUNCTION adjacent_find WITH PRED template inline _FwdIt adjacent_find(_FwdIt _First, _FwdIt _Last, _Pr _Pred) { // find first satisfying _Pred with successor for (_FwdIt _Firstb; (_Firstb = _First) != _Last && ++_First != _Last; ) if (_Pred(*_Firstb, *_First)) return (_Firstb); return (_Last); } // TEMPLATE FUNCTION count template inline ptrdiff_t count(_InIt _First, _InIt _Last, const _Ty& _Val) { // count elements that match _Val ptrdiff_t _Count = 0; for (; _First != _Last; ++_First) if (*_First == _Val) ++_Count; return (_Count); } // TEMPLATE FUNCTION count_if template inline ptrdiff_t count_if(_InIt _First, _InIt _Last, _Pr _Pred) { // count elements satisfying _Pred ptrdiff_t _Count = 0; for (; _First != _Last; ++_First) if (_Pred(*_First)) ++_Count; return (_Count); } // TEMPLATE FUNCTION search template inline _FwdIt1 _Search(_FwdIt1 _First1, _FwdIt1 _Last1, _FwdIt2 _First2, _FwdIt2 _Last2, _Diff1 *, _Diff2 *) { // find first [_First2, _Last2) match _Diff1 _Count1 = 0; _Distance(_First1, _Last1, _Count1); _Diff2 _Count2 = 0; _Distance(_First2, _Last2, _Count2); for (; _Count2 <= _Count1; ++_First1, --_Count1) { // room for match, try it _FwdIt1 _Mid1 = _First1; for (_FwdIt2 _Mid2 = _First2; ; ++_Mid1, ++_Mid2) if (_Mid2 == _Last2) return (_First1); else if (!(*_Mid1 == *_Mid2)) break; } return (_Last1); } template inline _FwdIt1 search(_FwdIt1 _First1, _FwdIt1 _Last1, _FwdIt2 _First2, _FwdIt2 _Last2) { // find first [_First2, _Last2) match return (_Search(_First1, _Last1, _First2, _Last2, _Dist_type(_First1), _Dist_type(_First2))); } // TEMPLATE FUNCTION search WITH PRED template inline _FwdIt1 _Search(_FwdIt1 _First1, _FwdIt1 _Last1, _FwdIt2 _First2, _FwdIt2 _Last2, _Pr _Pred, _Diff1 *, _Diff2 *) { // find first [_First2, _Last2) satisfying _Pred _Diff1 _Count1 = 0; _Distance(_First1, _Last1, _Count1); _Diff2 _Count2 = 0; _Distance(_First2, _Last2, _Count2); for (; _Count2 <= _Count1; ++_First1, --_Count1) { // room for match, try it _FwdIt1 _Mid1 = _First1; for (_FwdIt2 _Mid2 = _First2; ; ++_Mid1, ++_Mid2) if (_Mid2 == _Last2) return (_First1); else if (!_Pred(*_Mid1, *_Mid2)) break; } return (_Last1); } template inline _FwdIt1 search(_FwdIt1 _First1, _FwdIt1 _Last1, _FwdIt2 _First2, _FwdIt2 _Last2, _Pr _Pred) { // find first [_First2, _Last2) satisfying _Pred return (_Search(_First1, _Last1, _First2, _Last2, _Pred, _Dist_type(_First1), _Dist_type(_First2))); } // TEMPLATE FUNCTION search_n template inline _FwdIt1 _Search_n(_FwdIt1 _First1, _FwdIt1 _Last1, _Diff2 _Count, const _Ty& _Val, _Diff1 *) { // find first _Count * _Val match _Diff1 _Count1 = 0; _Distance(_First1, _Last1, _Count1); for (; _Count <= _Count1; ++_First1, --_Count1) { // room for match, try it _FwdIt1 _Mid1 = _First1; for (_Diff2 _Count2 = _Count; ; ++_Mid1, --_Count2) if (_Count2 == 0) return (_First1); else if (!(*_Mid1 == _Val)) break; } return (_Last1); } template inline _FwdIt1 search_n(_FwdIt1 _First1, _FwdIt1 _Last1, _Diff2 _Count, const _Ty& _Val) { // find first _Count * _Val match return (_Search_n(_First1, _Last1, _Count, _Val, _Dist_type(_First1))); } // TEMPLATE FUNCTION search_n WITH PRED template inline _FwdIt1 _Search_n(_FwdIt1 _First1, _FwdIt1 _Last1, _Diff2 _Count, const _Ty& _Val, _Pr _Pred, _Diff1 *) { // find first _Count * _Val satisfying _Pred _Diff1 _Count1 = 0; _Distance(_First1, _Last1, _Count1); for (; _Count <= _Count1; ++_First1, --_Count1) { // room for match, try it _FwdIt1 _Mid1 = _First1; for (_Diff2 _Count2 = _Count; ; ++_Mid1, --_Count2) if (_Count2 == 0) return (_First1); else if (!_Pred(*_Mid1, _Val)) break; } return (_Last1); } template inline _FwdIt1 search_n(_FwdIt1 _First1, _FwdIt1 _Last1, _Diff2 _Count, const _Ty& _Val, _Pr _Pred) { // find first _Count * _Val satisfying _Pred return (_Search_n(_First1, _Last1, _Count, _Val, _Pred, _Dist_type(_First1))); } // TEMPLATE FUNCTION find_end template inline _FwdIt1 _Find_end(_FwdIt1 _First1, _FwdIt1 _Last1, _FwdIt2 _First2, _FwdIt2 _Last2, _Diff1 *, _Diff2 *) { // find last [_First2, _Last2) match _Diff1 _Count1 = 0; _Distance(_First1, _Last1, _Count1); _Diff2 _Count2 = 0; _Distance(_First2, _Last2, _Count2); _FwdIt1 _Ans = _Last1; if (0 < _Count2) for (; _Count2 <= _Count1; ++_First1, --_Count1) { // room for match, try it _FwdIt1 _Mid1 = _First1; for (_FwdIt2 _Mid2 = _First2; ; ++_Mid1) if (!(*_Mid1 == *_Mid2)) break; else if (++_Mid2 == _Last2) { // potential answer, save it _Ans = _First1; break; } } return (_Ans); } template inline _FwdIt1 find_end(_FwdIt1 _First1, _FwdIt1 _Last1, _FwdIt2 _First2, _FwdIt2 _Last2) { // find last [_First2, _Last2) match return (_Find_end(_First1, _Last1, _First2, _Last2, _Dist_type(_First1), _Dist_type(_First2))); } // TEMPLATE FUNCTION find_end WITH PRED template inline _FwdIt1 _Find_end(_FwdIt1 _First1, _FwdIt1 _Last1, _FwdIt2 _First2, _FwdIt2 _Last2, _Pr _Pred, _Diff1 *, _Diff2 *) { // find last [_First2, _Last2) satisfying _Pred _Diff1 _Count1 = 0; _Distance(_First1, _Last1, _Count1); _Diff2 _Count2 = 0; _Distance(_First2, _Last2, _Count2); _FwdIt1 _Ans = _Last1; if (0 < _Count2) for (; _Count2 <= _Count1; ++_First1, --_Count1) { // room for match, try it _FwdIt1 _Mid1 = _First1; for (_FwdIt2 _Mid2 = _First2; ; ++_Mid1) if (!_Pred(*_Mid1, *_Mid2)) break; else if (++_Mid2 == _Last2) { // potential answer, save it _Ans = _First1; break; } } return (_Ans); } template inline _FwdIt1 find_end(_FwdIt1 _First1, _FwdIt1 _Last1, _FwdIt2 _First2, _FwdIt2 _Last2, _Pr _Pred) { // find last [_First2, _Last2) satisfying _Pred return (_Find_end(_First1, _Last1, _First2, _Last2, _Pred, _Dist_type(_First1), _Dist_type(_First2))); } // TEMPLATE FUNCTION find_first_of template inline _FwdIt1 find_first_of(_FwdIt1 _First1, _FwdIt1 _Last1, _FwdIt2 _First2, _FwdIt2 _Last2) { // look for one of [_First2, _Last2) that matches element for (; _First1 != _Last1; ++_First1) for (_FwdIt2 _Mid2 = _First2; _Mid2 != _Last2; ++_Mid2) if (*_First1 == *_Mid2) return (_First1); return (_First1); } // TEMPLATE FUNCTION find_first_of WITH PRED template inline _FwdIt1 find_first_of(_FwdIt1 _First1, _FwdIt1 _Last1, _FwdIt2 _First2, _FwdIt2 _Last2, _Pr _Pred) { // look for one of [_First2, _Last2) satisfying _Pred with element for (; _First1 != _Last1; ++_First1) for (_FwdIt2 _Mid2 = _First2; _Mid2 != _Last2; ++_Mid2) if (_Pred(*_First1, *_Mid2)) return (_First1); return (_First1); } // TEMPLATE FUNCTION iter_swap template inline void iter_swap(_FwdIt1 _Left, _FwdIt2 _Right) { // swap *_Left and *_Right std::swap(*_Left, *_Right); } // TEMPLATE FUNCTION swap_ranges template inline _FwdIt2 swap_ranges(_FwdIt1 _First1, _FwdIt1 _Last1, _FwdIt2 _First2) { // swap [_First1, _Last1) with [_First2, ...) for (; _First1 != _Last1; ++_First1, ++_First2) std::iter_swap(_First1, _First2); return (_First2); } // TEMPLATE FUNCTION transform WITH UNARY OP template inline _OutIt transform(_InIt _First, _InIt _Last, _OutIt _Dest, _Fn1 _Func) { // transform [_First, _Last) with _Func for (; _First != _Last; ++_First, ++_Dest) *_Dest = _Func(*_First); return (_Dest); } // TEMPLATE FUNCTION transform WITH BINARY OP template inline _OutIt transform(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _OutIt _Dest, _Fn2 _Func) { // transform [_First1, _Last1) and [_First2, _Last2) with _Func for (; _First1 != _Last1; ++_First1, ++_First2, ++_Dest) *_Dest = _Func(*_First1, *_First2); return (_Dest); } // TEMPLATE FUNCTION replace template inline void replace(_FwdIt _First, _FwdIt _Last, const _Ty& _Oldval, const _Ty& _Newval) { // replace each matching _Oldval with _Newval for (; _First != _Last; ++_First) if (*_First == _Oldval) *_First = _Newval; } // TEMPLATE FUNCTION replace_if template inline void replace_if(_FwdIt _First, _FwdIt _Last, _Pr _Pred, const _Ty& _Val) { // replace each satisfying _Pred with _Val for (; _First != _Last; ++_First) if (_Pred(*_First)) *_First = _Val; } // TEMPLATE FUNCTION replace_copy template inline _OutIt replace_copy(_InIt _First, _InIt _Last, _OutIt _Dest, const _Ty& _Oldval, const _Ty& _Newval) { // copy replacing each matching _Oldval with _Newval for (; _First != _Last; ++_First, ++_Dest) *_Dest = *_First == _Oldval ? _Newval : *_First; return (_Dest); } // TEMPLATE FUNCTION replace_copy_if template inline _OutIt replace_copy_if(_InIt _First, _InIt _Last, _OutIt _Dest, _Pr _Pred, const _Ty& _Val) { // copy replacing each satisfying _Pred with _Val for (; _First != _Last; ++_First, ++_Dest) *_Dest = _Pred(*_First) ? _Val : *_First; return (_Dest); } // TEMPLATE FUNCTION generate template inline void generate(_FwdIt _First, _FwdIt _Last, _Fn0 _Func) { // replace [_First, _Last) with _Func() for (; _First != _Last; ++_First) *_First = _Func(); } // TEMPLATE FUNCTION generate_n template inline void generate_n(_OutIt _Dest, _Diff _Count, _Fn0 _Func) { // replace [_Dest, _Dest + _Count) with _Func() for (; 0 < _Count; --_Count, ++_Dest) *_Dest = _Func(); } // TEMPLATE FUNCTION remove_copy template inline _OutIt remove_copy(_InIt _First, _InIt _Last, _OutIt _Dest, const _Ty& _Val) { // copy omitting each matching _Val for (; _First != _Last; ++_First) if (!(*_First == _Val)) *_Dest++ = *_First; return (_Dest); } // TEMPLATE FUNCTION remove_copy_if template inline _OutIt remove_copy_if(_InIt _First, _InIt _Last, _OutIt _Dest, _Pr _Pred) { // copy omitting each element satisfying _Pred for (; _First != _Last; ++_First) if (!_Pred(*_First)) *_Dest++ = *_First; return (_Dest); } // TEMPLATE FUNCTION remove template inline _FwdIt remove(_FwdIt _First, _FwdIt _Last, const _Ty& _Val) { // remove each matching _Val _First = find(_First, _Last, _Val); if (_First == _Last) return (_First); // empty sequence, all done else { // nonempty sequence, worth doing _FwdIt _First1 = _First; return (std::remove_copy(++_First1, _Last, _First, _Val)); } } // TEMPLATE FUNCTION remove_if template inline _FwdIt remove_if(_FwdIt _First, _FwdIt _Last, _Pr _Pred) { // remove each satisfying _Pred _First = std::find_if(_First, _Last, _Pred); if (_First == _Last) return (_First); // empty sequence, all done else { // nonempty sequence, worth doing _FwdIt _First1 = _First; return (std::remove_copy_if(++_First1, _Last, _First, _Pred)); } } // TEMPLATE FUNCTION unique template inline _FwdIt unique(_FwdIt _First, _FwdIt _Last) { // remove each matching previous for (_FwdIt _Firstb; (_Firstb = _First) != _Last && ++_First != _Last; ) if (*_Firstb == *_First) { // copy down for (; ++_First != _Last; ) if (!(*_Firstb == *_First)) *++_Firstb = *_First; return (++_Firstb); } return (_Last); } // TEMPLATE FUNCTION unique WITH PRED template inline _FwdIt unique(_FwdIt _First, _FwdIt _Last, _Pr _Pred) { // remove each satisfying _Pred with previous for (_FwdIt _Firstb; (_Firstb = _First) != _Last && ++_First != _Last; ) if (_Pred(*_Firstb, *_First)) { // copy down for (; ++_First != _Last; ) if (!_Pred(*_Firstb, *_First)) *++_Firstb = *_First; return (++_Firstb); } return (_Last); } // TEMPLATE FUNCTION unique_copy template inline _OutIt _Unique_copy(_InIt _First, _InIt _Last, _OutIt _Dest, _Ty *) { // copy compressing pairs that match, input iterators _Ty _Val = *_First; for (*_Dest++ = _Val; ++_First != _Last; ) if (!(_Val == *_First)) _Val = *_First, *_Dest++ = _Val; return (_Dest); } template inline _OutIt _Unique_copy(_InIt _First, _InIt _Last, _OutIt _Dest, input_iterator_tag) { // copy compressing pairs that match, input iterators return (_Unique_copy(_First, _Last, _Dest, _Val_type(_First))); } template inline _OutIt _Unique_copy(_FwdIt _First, _FwdIt _Last, _OutIt _Dest, forward_iterator_tag) { // copy compressing pairs that match, forward iterators _FwdIt _Firstb = _First; for (*_Dest++ = *_Firstb; ++_First != _Last; ) if (!(*_Firstb == *_First)) _Firstb = _First, *_Dest++ = *_Firstb; return (_Dest); } template inline _OutIt _Unique_copy(_BidIt _First, _BidIt _Last, _OutIt _Dest, bidirectional_iterator_tag) { // copy compressing pairs that match, bidirectional iterators return (_Unique_copy(_First, _Last, _Dest, forward_iterator_tag())); } template inline _OutIt _Unique_copy(_RanIt _First, _RanIt _Last, _OutIt _Dest, random_access_iterator_tag) { // copy compressing pairs that match, random-access iterators return (_Unique_copy(_First, _Last, _Dest, forward_iterator_tag())); } template inline _OutIt unique_copy(_InIt _First, _InIt _Last, _OutIt _Dest) { // copy compressing pairs that match return (_First == _Last ? _Dest : _Unique_copy(_First, _Last, _Dest, _Iter_cat(_First))); } // TEMPLATE FUNCTION unique_copy WITH PRED template inline _OutIt _Unique_copy(_InIt _First, _InIt _Last, _OutIt _Dest, _Pr _Pred, _Ty *) { // copy compressing pairs satisfying _Pred, input iterators _Ty _Val = *_First; for (*_Dest++ = _Val; ++_First != _Last; ) if (!_Pred(_Val, *_First)) _Val = *_First, *_Dest++ = _Val; return (_Dest); } template inline _OutIt _Unique_copy(_InIt _First, _InIt _Last, _OutIt _Dest, _Pr _Pred, input_iterator_tag) { // copy compressing pairs satisfying _Pred, input iterators return (_Unique_copy(_First, _Last, _Dest, _Pred, _Val_type(_First))); } template inline _OutIt _Unique_copy(_FwdIt _First, _FwdIt _Last, _OutIt _Dest, _Pr _Pred, forward_iterator_tag) { // copy compressing pairs satisfying _Pred, forward iterators _FwdIt _Firstb = _First; for (*_Dest++ = *_Firstb; ++_First != _Last; ) if (!_Pred(*_Firstb, *_First)) _Firstb = _First, *_Dest++ = *_Firstb; return (_Dest); } template inline _OutIt _Unique_copy(_BidIt _First, _BidIt _Last, _OutIt _Dest, _Pr _Pred, bidirectional_iterator_tag) { // copy compressing pairs satisfying _Pred, bidirectional iterators return (_Unique_copy(_First, _Last, _Dest, _Pred, forward_iterator_tag())); } template inline _OutIt _Unique_copy(_RanIt _First, _RanIt _Last, _OutIt _Dest, _Pr _Pred, random_access_iterator_tag) { // copy compressing pairs satisfying _Pred, random-access iterators return (_Unique_copy(_First, _Last, _Dest, _Pred, forward_iterator_tag())); } template inline _OutIt unique_copy(_InIt _First, _InIt _Last, _OutIt _Dest, _Pr _Pred) { // copy compressing pairs satisfying _Pred return (_First == _Last ? _Dest : _Unique_copy(_First, _Last, _Dest, _Pred, _Iter_cat(_First))); } // TEMPLATE FUNCTION reverse template inline void _Reverse(_BidIt _First, _BidIt _Last, bidirectional_iterator_tag) { // reverse elements in [_First, _Last), bidirectional iterators for (; _First != _Last && _First != --_Last; ++_First) std::iter_swap(_First, _Last); } template inline void _Reverse(_RanIt _First, _RanIt _Last, random_access_iterator_tag) { // reverse elements in [_First, _Last), random-access iterators for (; _First < _Last; ++_First) std::iter_swap(_First, --_Last); } template inline void reverse(_BidIt _First, _BidIt _Last) { // reverse elements in [_First, _Last) _Reverse(_First, _Last, _Iter_cat(_First)); } // TEMPLATE FUNCTION reverse_copy template inline _OutIt reverse_copy(_BidIt _First, _BidIt _Last, _OutIt _Dest) { // copy reversing elements in [_First, _Last) for (; _First != _Last; ++_Dest) *_Dest = *--_Last; return (_Dest); } // TEMPLATE FUNCTION rotate template inline void _Rotate(_FwdIt _First, _FwdIt _Mid, _FwdIt _Last, forward_iterator_tag) { // rotate [_First, _Last), forward iterators for (_FwdIt _Next = _Mid; ; ) { // swap [_First, ...) into place std::iter_swap(_First, _Next); if (++_First == _Mid) if (++_Next == _Last) break; // done, quit else _Mid = _Next; // mark end of next interval else if (++_Next == _Last) _Next = _Mid; // wrap to last end } } template inline void _Rotate(_BidIt _First, _BidIt _Mid, _BidIt _Last, bidirectional_iterator_tag) { // rotate [_First, _Last), bidirectional iterators std::reverse(_First, _Mid); std::reverse(_Mid, _Last); std::reverse(_First, _Last); } template inline void _Rotate(_RanIt _First, _RanIt _Mid, _RanIt _Last, _Diff *, _Ty *) { // rotate [_First, _Last), random-access iterators _Diff _Shift = _Mid - _First; _Diff _Count = _Last - _First; for (_Diff _Factor = _Shift; _Factor != 0; ) { // find subcycle count as GCD of shift count and length _Diff _Tmp = _Count % _Factor; _Count = _Factor, _Factor = _Tmp; } if (_Count < _Last - _First) for (; 0 < _Count; --_Count) { // rotate each subcycle _RanIt _Hole = _First + _Count; _RanIt _Next = _Hole; _Ty _Holeval = *_Hole; _RanIt _Next1 = _Next + _Shift == _Last ? _First : _Next + _Shift; while (_Next1 != _Hole) { // percolate elements back around subcycle *_Next = *_Next1; _Next = _Next1; _Next1 = _Shift < _Last - _Next1 ? _Next1 + _Shift : _First + (_Shift - (_Last - _Next1)); } *_Next = _Holeval; } } template inline void _Rotate(_RanIt _First, _RanIt _Mid, _RanIt _Last, random_access_iterator_tag) { // rotate [_First, _Last), random-access iterators _Rotate(_First, _Mid, _Last, _Dist_type(_First), _Val_type(_First)); } template inline void rotate(_FwdIt _First, _FwdIt _Mid, _FwdIt _Last) { // rotate [_First, _Last) if (_First != _Mid && _Mid != _Last) _Rotate(_First, _Mid, _Last, _Iter_cat(_First)); } // TEMPLATE FUNCTION rotate_copy template inline _OutIt rotate_copy(_FwdIt _First, _FwdIt _Mid, _FwdIt _Last, _OutIt _Dest) { // copy rotating [_First, _Last) _Dest = std::copy(_Mid, _Last, _Dest); return (std::copy(_First, _Mid, _Dest)); } // TEMPLATE FUNCTION random_shuffle template inline void _Random_shuffle(_RanIt _First, _RanIt _Last, _Diff *) { // shuffle [_First, _Last) const int _RANDOM_BITS = 15; // minimum random bits from rand() const int _RANDOM_MAX = (1U << _RANDOM_BITS) - 1; _RanIt _Next = _First; for (unsigned long _Index = 2; ++_Next != _Last; ++_Index) { // assume unsigned long big enough for _Diff count unsigned long _Rm = _RANDOM_MAX; unsigned long _Rn = ::rand() & _RANDOM_MAX; for (; _Rm < _Index && _Rm != ~0UL; _Rm = _Rm << _RANDOM_BITS | _RANDOM_MAX) _Rn = _Rn << _RANDOM_BITS | _RANDOM_MAX; // build random value std::iter_swap(_Next, _First + _Diff(_Rn % _Index)); // swap a pair } } template inline void random_shuffle(_RanIt _First, _RanIt _Last) { // shuffle [_First, _Last) if (_First != _Last) _Random_shuffle(_First, _Last, _Dist_type(_First)); } // TEMPLATE FUNCTION random_shuffle WITH RANDOM FN template inline void _Random_shuffle(_RanIt _First, _RanIt _Last, _Fn1& _Func, _Diff *) { // shuffle nonempty [_First, _Last) using random function _Func _RanIt _Next = _First; for (_Diff _Index = 2; ++_Next != _Last; ++_Index) std::iter_swap(_Next, _First + _Diff(_Func(_Index))); } template inline void random_shuffle(_RanIt _First, _RanIt _Last, _Fn1& _Func) { // shuffle [_First, _Last) using random function _Func if (_First != _Last) _Random_shuffle(_First, _Last, _Func, _Dist_type(_First)); } // TEMPLATE FUNCTION partition template inline _BidIt partition(_BidIt _First, _BidIt _Last, _Pr _Pred) { // move elements satisfying _Pred to beginning of sequence for (; ; ++_First) { // find any out-of-order pair for (; _First != _Last && _Pred(*_First); ++_First) ; // skip in-place elements at beginning if (_First == _Last) break; // done for (; _First != --_Last && !_Pred(*_Last); ) ; // skip in-place elements at end if (_First == _Last) break; // done std::iter_swap(_First, _Last); // swap out-of-place pair and loop } return (_First); } // TEMPLATE FUNCTION stable_partition template inline _BidIt _Stable_partition(_BidIt _First, _BidIt _Last, _Pr _Pred, _Diff _Count, _Temp_iterator<_Ty>& _Tempbuf) { // partition using _Pred, preserving order of equivalents if (_Count == 1) return (_Pred(*_First) ? _Last : _First); else if (_Count <= _Tempbuf._Maxlen()) { // temp buffer big enough, copy right partition out and back _BidIt _Next = _First; for (_Tempbuf._Init(); _First != _Last; ++_First) if (_Pred(*_First)) *_Next++ = *_First; else *_Tempbuf++ = *_First; std::copy(_Tempbuf._First(), _Tempbuf._Last(), _Next); // copy back return (_Next); } else { // temp buffer not big enough, divide and conquer _BidIt _Mid = _First; std::advance(_Mid, _Count / 2); _BidIt _Left = _Stable_partition(_First, _Mid, _Pred, _Count / 2, _Tempbuf); // form L1R1 in left half _BidIt _Right = _Stable_partition(_Mid, _Last, _Pred, _Count - _Count / 2, _Tempbuf); // form L2R2 in right half _Diff _Count1 = 0; _Distance(_Left, _Mid, _Count1); _Diff _Count2 = 0; _Distance(_Mid, _Right, _Count2); return (_Buffered_rotate(_Left, _Mid, _Right, _Count1, _Count2, _Tempbuf)); // rotate L1R1L2R2 to L1L2R1R2 } } template inline _BidIt _Stable_partition(_BidIt _First, _BidIt _Last, _Pr _Pred, _Diff *, _Ty *) { // partition preserving order of equivalents, using _Pred _Diff _Count = 0; _Distance(_First, _Last, _Count); _Temp_iterator<_Ty> _Tempbuf(_Count); return (_Stable_partition(_First, _Last, _Pred, _Count, _Tempbuf)); } template inline _BidIt stable_partition(_BidIt _First, _BidIt _Last, _Pr _Pred) { // partition preserving order of equivalents, using _Pred return (_First == _Last ? _First : _Stable_partition(_First, _Last, _Pred, _Dist_type(_First), _Val_type(_First))); } // TEMPLATE FUNCTION push_heap template inline void _Push_heap(_RanIt _First, _Diff _Hole, _Diff _Top, _Ty _Val) { // percolate _Hole to _Top or where _Val belongs, using operator< for (_Diff _Idx = (_Hole - 1) / 2; _Top < _Hole && *(_First + _Idx) < _Val; _Idx = (_Hole - 1) / 2) { // move _Hole up to parent *(_First + _Hole) = *(_First + _Idx); _Hole = _Idx; } *(_First + _Hole) = _Val; // drop _Val into final hole } template inline void _Push_heap_0(_RanIt _First, _RanIt _Last, _Diff *, _Ty *) { // push *(_Last - 1) onto heap at [_First, _Last - 1), using operator< _Diff _Count = _Last - _First; if (1 < _Count) _Push_heap(_First, --_Count, _Diff(0), _Ty(*(_Last - 1))); } template inline void push_heap(_RanIt _First, _RanIt _Last) { // push *(_Last - 1) onto heap at [_First, _Last - 1), using operator< _Push_heap_0(_First, _Last, _Dist_type(_First), _Val_type(_First)); } // TEMPLATE FUNCTION push_heap WITH PRED template inline void _Push_heap(_RanIt _First, _Diff _Hole, _Diff _Top, _Ty _Val, _Pr _Pred) { // percolate _Hole to _Top or where _Val belongs, using operator< for (_Diff _Idx = (_Hole - 1) / 2; _Top < _Hole && _Pred(*(_First + _Idx), _Val); _Idx = (_Hole - 1) / 2) { // move _Hole up to parent *(_First + _Hole) = *(_First + _Idx); _Hole = _Idx; } *(_First + _Hole) = _Val; // drop _Val into final hole } template inline void _Push_heap_0(_RanIt _First, _RanIt _Last, _Pr _Pred, _Diff *, _Ty *) { // push *(_Last - 1) onto heap at [_First, _Last - 1), using _Pred _Diff _Count = _Last - _First; if (1 < _Count) _Push_heap(_First, --_Count, _Diff(0), _Ty(*(_Last - 1)), _Pred); } template inline void push_heap(_RanIt _First, _RanIt _Last, _Pr _Pred) { // push *(_Last - 1) onto heap at [_First, _Last - 1), using _Pred _Push_heap_0(_First, _Last, _Pred, _Dist_type(_First), _Val_type(_First)); } // TEMPLATE FUNCTION pop_heap template inline void _Adjust_heap(_RanIt _First, _Diff _Hole, _Diff _Bottom, _Ty _Val) { // percolate _Hole to _Bottom, then push _Val, using operator< _Diff _Top = _Hole; _Diff _Idx = 2 * _Hole + 2; for (; _Idx < _Bottom; _Idx = 2 * _Idx + 2) { // move _Hole down to larger child if (*(_First + _Idx) < *(_First + (_Idx - 1))) --_Idx; *(_First + _Hole) = *(_First + _Idx), _Hole = _Idx; } if (_Idx == _Bottom) { // only child at bottom, move _Hole down to it *(_First + _Hole) = *(_First + (_Bottom - 1)); _Hole = _Bottom - 1; } _Push_heap(_First, _Hole, _Top, _Val); } template inline void _Pop_heap(_RanIt _First, _RanIt _Last, _RanIt _Dest, _Ty _Val, _Diff *) { // pop *_First to *_Dest and reheap, using operator< *_Dest = *_First; _Adjust_heap(_First, _Diff(0), _Diff(_Last - _First), _Val); } template inline void _Pop_heap_0(_RanIt _First, _RanIt _Last, _Ty *) { // pop *_First to *(_Last - 1) and reheap, using operator< _Pop_heap(_First, _Last - 1, _Last - 1, _Ty(*(_Last - 1)), _Dist_type(_First)); } template inline void pop_heap(_RanIt _First, _RanIt _Last) { // pop *_First to *(_Last - 1) and reheap, using operator< if (1 < _Last - _First) _Pop_heap_0(_First, _Last, _Val_type(_First)); } // TEMPLATE FUNCTION pop_heap WITH PRED template inline void _Adjust_heap(_RanIt _First, _Diff _Hole, _Diff _Bottom, _Ty _Val, _Pr _Pred) { // percolate _Hole to _Bottom, then push _Val, using _Pred _Diff _Top = _Hole; _Diff _Idx = 2 * _Hole + 2; for (; _Idx < _Bottom; _Idx = 2 * _Idx + 2) { // move _Hole down to larger child if (_Pred(*(_First + _Idx), *(_First + (_Idx - 1)))) --_Idx; *(_First + _Hole) = *(_First + _Idx), _Hole = _Idx; } if (_Idx == _Bottom) { // only child at bottom, move _Hole down to it *(_First + _Hole) = *(_First + (_Bottom - 1)); _Hole = _Bottom - 1; } _Push_heap(_First, _Hole, _Top, _Val, _Pred); } template inline void _Pop_heap(_RanIt _First, _RanIt _Last, _RanIt _Dest, _Ty _Val, _Pr _Pred, _Diff *) { // pop *_First to *_Dest and reheap, using _Pred *_Dest = *_First; _Adjust_heap(_First, _Diff(0), _Diff(_Last - _First), _Val, _Pred); } template inline void _Pop_heap_0(_RanIt _First, _RanIt _Last, _Pr _Pred, _Ty *) { // pop *_First to *(_Last - 1) and reheap, using _Pred _Pop_heap(_First, _Last - 1, _Last - 1, _Ty(*(_Last - 1)), _Pred, _Dist_type(_First)); } template inline void pop_heap(_RanIt _First, _RanIt _Last, _Pr _Pred) { // pop *_First to *(_Last - 1) and reheap, using _Pred if (1 < _Last - _First) _Pop_heap_0(_First, _Last, _Pred, _Val_type(_First)); } // TEMPLATE FUNCTION make_heap template inline void _Make_heap(_RanIt _First, _RanIt _Last, _Diff *, _Ty *) { // make nontrivial [_First, _Last) into a heap, using operator< _Diff _Bottom = _Last - _First; for (_Diff _Hole = _Bottom / 2; 0 < _Hole; ) { // reheap top half, bottom to top --_Hole; _Adjust_heap(_First, _Hole, _Bottom, _Ty(*(_First + _Hole))); } } template inline void make_heap(_RanIt _First, _RanIt _Last) { // make [_First, _Last) into a heap, using operator< if (1 < _Last - _First) _Make_heap(_First, _Last, _Dist_type(_First), _Val_type(_First)); } // TEMPLATE FUNCTION make_heap WITH PRED template inline void _Make_heap(_RanIt _First, _RanIt _Last, _Pr _Pred, _Diff *, _Ty *) { // make nontrivial [_First, _Last) into a heap, using _Pred _Diff _Bottom = _Last - _First; for (_Diff _Hole = _Bottom / 2; 0 < _Hole; ) { // reheap top half, bottom to top --_Hole; _Adjust_heap(_First, _Hole, _Bottom, _Ty(*(_First + _Hole)), _Pred); } } template inline void make_heap(_RanIt _First, _RanIt _Last, _Pr _Pred) { // make [_First, _Last) into a heap, using _Pred if (1 < _Last - _First) _Make_heap(_First, _Last, _Pred, _Dist_type(_First), _Val_type(_First)); } // TEMPLATE FUNCTION sort_heap template inline void sort_heap(_RanIt _First, _RanIt _Last) { // order heap by repeatedly popping, using operator< for (; 1 < _Last - _First; --_Last) std::pop_heap(_First, _Last); } // TEMPLATE FUNCTION sort_heap WITH PRED template inline void sort_heap(_RanIt _First, _RanIt _Last, _Pr _Pred) { // order heap by repeatedly popping, using _Pred for (; 1 < _Last - _First; --_Last) std::pop_heap(_First, _Last, _Pred); } // TEMPLATE FUNCTION lower_bound template inline _FwdIt _Lower_bound(_FwdIt _First, _FwdIt _Last, const _Ty& _Val, _Diff *) { // find first element not before _Val, using operator< _Diff _Count = 0; _Distance(_First, _Last, _Count); for (; 0 < _Count; ) { // divide and conquer, find half that contains answer _Diff _Count2 = _Count / 2; _FwdIt _Mid = _First; std::advance(_Mid, _Count2); if (*_Mid < _Val) _First = ++_Mid, _Count -= _Count2 + 1; else _Count = _Count2; } return (_First); } template inline _FwdIt lower_bound(_FwdIt _First, _FwdIt _Last, const _Ty& _Val) { // find first element not before _Val, using operator< return (_Lower_bound(_First, _Last, _Val, _Dist_type(_First))); } // TEMPLATE FUNCTION lower_bound WITH PRED template inline _FwdIt _Lower_bound(_FwdIt _First, _FwdIt _Last, const _Ty& _Val, _Pr _Pred, _Diff *) { // find first element not before _Val, using _Pred _Diff _Count = 0; _Distance(_First, _Last, _Count); for (; 0 < _Count; ) { // divide and conquer, find half that contains answer _Diff _Count2 = _Count / 2; _FwdIt _Mid = _First; std::advance(_Mid, _Count2); if (_Pred(*_Mid, _Val)) _First = ++_Mid, _Count -= _Count2 + 1; else _Count = _Count2; } return (_First); } template inline _FwdIt lower_bound(_FwdIt _First, _FwdIt _Last, const _Ty& _Val, _Pr _Pred) { // find first element not before _Val, using _Pred return (_Lower_bound(_First, _Last, _Val, _Pred, _Dist_type(_First))); } // TEMPLATE FUNCTION upper_bound template inline _FwdIt _Upper_bound(_FwdIt _First, _FwdIt _Last, const _Ty& _Val, _Diff *) { // find first element that _Val is before, using operator< _Diff _Count = 0; _Distance(_First, _Last, _Count); for (; 0 < _Count; ) { // divide and conquer, find half that contains answer _Diff _Count2 = _Count / 2; _FwdIt _Mid = _First; std::advance(_Mid, _Count2); if (!(_Val < *_Mid)) _First = ++_Mid, _Count -= _Count2 + 1; else _Count = _Count2; } return (_First); } template inline _FwdIt upper_bound(_FwdIt _First, _FwdIt _Last, const _Ty& _Val) { // find first element that _Val is before, using operator< return (_Upper_bound(_First, _Last, _Val, _Dist_type(_First))); } // TEMPLATE FUNCTION upper_bound WITH PRED template inline _FwdIt _Upper_bound(_FwdIt _First, _FwdIt _Last, const _Ty& _Val, _Pr _Pred, _Diff *) { // find first element that _Val is before, using _Pred _Diff _Count = 0; _Distance(_First, _Last, _Count); for (; 0 < _Count; ) { // divide and conquer, find half that contains answer _Diff _Count2 = _Count / 2; _FwdIt _Mid = _First; std::advance(_Mid, _Count2); if (!_Pred(_Val, *_Mid)) _First = ++_Mid, _Count -= _Count2 + 1; else _Count = _Count2; } return (_First); } template inline _FwdIt upper_bound(_FwdIt _First, _FwdIt _Last, const _Ty& _Val, _Pr _Pred) { // find first element that _Val is before, using _Pred return (_Upper_bound(_First, _Last, _Val, _Pred, _Dist_type(_First))); } // TEMPLATE FUNCTION equal_range template inline pair<_FwdIt, _FwdIt> _Equal_range(_FwdIt _First, _FwdIt _Last, const _Ty& _Val, _Diff *) { // find range equivalent to _Val, using operator< _Diff _Count = 0; _Distance(_First, _Last, _Count); for (; 0 < _Count; ) { // divide and conquer, check midpoint _Diff _Count2 = _Count / 2; _FwdIt _Mid = _First; std::advance(_Mid, _Count2); if (*_Mid < _Val) { // range begins above _Mid, loop _First = ++_Mid; _Count -= _Count2 + 1; } else if (_Val < *_Mid) _Count = _Count2; // range in first half, loop else { // range straddles mid, find each end and return _FwdIt _First2 = lower_bound(_First, _Mid, _Val); std::advance(_First, _Count); _FwdIt _Last2 = upper_bound(++_Mid, _First, _Val); return (pair<_FwdIt, _FwdIt>(_First2, _Last2)); } } return (pair<_FwdIt, _FwdIt>(_First, _First)); // empty range } template inline pair<_FwdIt, _FwdIt> equal_range(_FwdIt _First, _FwdIt _Last, const _Ty& _Val) { // find range equivalent to _Val, using operator< return (_Equal_range(_First, _Last, _Val, _Dist_type(_First))); } // TEMPLATE FUNCTION equal_range WITH PRED template inline pair<_FwdIt, _FwdIt> _Equal_range(_FwdIt _First, _FwdIt _Last, const _Ty& _Val, _Pr _Pred, _Diff *) { // find range equivalent to _Val, using _Pred _Diff _Count = 0; _Distance(_First, _Last, _Count); for (; 0 < _Count; ) { // divide and conquer, check midpoint _Diff _Count2 = _Count / 2; _FwdIt _Mid = _First; std::advance(_Mid, _Count2); if (_Pred(*_Mid, _Val)) { // range begins above _Mid, loop _First = ++_Mid; _Count -= _Count2 + 1; } else if (_Pred(_Val, *_Mid)) _Count = _Count2; // range in first half, loop else { // range straddles _Mid, find each end and return _FwdIt _First2 = lower_bound(_First, _Mid, _Val, _Pred); std::advance(_First, _Count); _FwdIt _Last2 = upper_bound(++_Mid, _First, _Val, _Pred); return (pair<_FwdIt, _FwdIt>(_First2, _Last2)); } } return (pair<_FwdIt, _FwdIt>(_First, _First)); // empty range } template inline pair<_FwdIt, _FwdIt> equal_range(_FwdIt _First, _FwdIt _Last, const _Ty& _Val, _Pr _Pred) { // find range equivalent to _Val, using _Pred return (_Equal_range(_First, _Last, _Val, _Pred, _Dist_type(_First))); } // TEMPLATE FUNCTION binary_search template inline bool binary_search(_FwdIt _First, _FwdIt _Last, const _Ty& _Val) { // test if _Val equivalent to some element, using operator< _First = std::lower_bound(_First, _Last, _Val); return (_First != _Last && !(_Val < *_First)); } // TEMPLATE FUNCTION binary_search WITH PRED template inline bool binary_search(_FwdIt _First, _FwdIt _Last, const _Ty& _Val, _Pr _Pred) { // test if _Val equivalent to some element, using _Pred _First = std::lower_bound(_First, _Last, _Val, _Pred); return (_First != _Last && !_Pred(_Val, *_First)); } // TEMPLATE FUNCTION merge template inline _OutIt merge(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _OutIt _Dest) { // copy merging ranges, both using operator< for (; _First1 != _Last1 && _First2 != _Last2; ++_Dest) if (*_First2 < *_First1) *_Dest = *_First2, ++_First2; else *_Dest = *_First1, ++_First1; _Dest = std::copy(_First1, _Last1, _Dest); // copy any tail return (std::copy(_First2, _Last2, _Dest)); } // TEMPLATE FUNCTION merge WITH PRED template inline _OutIt merge(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _OutIt _Dest, _Pr _Pred) { // copy merging ranges, both using _Pred for (; _First1 != _Last1 && _First2 != _Last2; ++_Dest) if (_Pred(*_First2, *_First1)) *_Dest = *_First2, ++_First2; else *_Dest = *_First1, ++_First1; _Dest = std::copy(_First1, _Last1, _Dest); // copy any tail return (std::copy(_First2, _Last2, _Dest)); } // TEMPLATE FUNCTION inplace_merge template inline _BidIt _Buffered_rotate(_BidIt _First, _BidIt _Mid, _BidIt _Last, _Diff _Count1, _Diff _Count2, _Temp_iterator<_Ty>& _Tempbuf) { // rotate [_First, _Last) using temp buffer if (_Count1 <= _Count2 && _Count1 <= _Tempbuf._Maxlen()) { // buffer left partition, then copy parts std::copy(_First, _Mid, _Tempbuf._Init()); std::copy(_Mid, _Last, _First); return (std::copy_backward(_Tempbuf._First(), _Tempbuf._Last(), _Last)); } else if (_Count2 <= _Tempbuf._Maxlen()) { // buffer right partition, then copy parts std::copy(_Mid, _Last, _Tempbuf._Init()); std::copy_backward(_First, _Mid, _Last); return (std::copy(_Tempbuf._First(), _Tempbuf._Last(), _First)); } else { // buffer too small, rotate in place std::rotate(_First, _Mid, _Last); std::advance(_First, _Count2); return (_First); } } template inline _BidIt3 _Merge_backward(_BidIt1 _First1, _BidIt1 _Last1, _BidIt2 _First2, _BidIt2 _Last2, _BidIt3 _Dest) { // merge backwards to _Dest, using operator< for (; ; ) if (_First1 == _Last1) return (std::copy_backward(_First2, _Last2, _Dest)); else if (_First2 == _Last2) return (std::copy_backward(_First1, _Last1, _Dest)); else if (*--_Last2 < *--_Last1) *--_Dest = *_Last1, ++_Last2; else *--_Dest = *_Last2, ++_Last1; } template inline void _Buffered_merge(_BidIt _First, _BidIt _Mid, _BidIt _Last, _Diff _Count1, _Diff _Count2, _Temp_iterator<_Ty>& _Tempbuf) { // merge [_First, _Mid) with [_Mid, _Last), using operator< if (_Count1 + _Count2 == 2) { // order two one-element partitions if (*_Mid < *_First) std::iter_swap(_First, _Mid); } else if (_Count1 <= _Count2 && _Count1 <= _Tempbuf._Maxlen()) { // buffer left partition, then merge std::copy(_First, _Mid, _Tempbuf._Init()); std::merge(_Tempbuf._First(), _Tempbuf._Last(), _Mid, _Last, _First); } else if (_Count2 <= _Tempbuf._Maxlen()) { // buffer right partition, then merge std::copy(_Mid, _Last, _Tempbuf._Init()); _Merge_backward(_First, _Mid, _Tempbuf._First(), _Tempbuf._Last(), _Last); } else { // buffer too small, divide and conquer _BidIt _Firstn, _Lastn; _Diff _Count1n, _Count2n; if (_Count2 < _Count1) { // left larger, cut it in half and partition right to match _Count1n = _Count1 / 2, _Count2n = 0; _Firstn = _First; std::advance(_Firstn, _Count1n); _Lastn = std::lower_bound(_Mid, _Last, *_Firstn); _Distance(_Mid, _Lastn, _Count2n); } else { // right larger, cut it in half and partition left to match _Count1n = 0, _Count2n = _Count2 / 2; _Lastn = _Mid; std::advance(_Lastn, _Count2n); _Firstn = std::upper_bound(_First, _Mid, *_Lastn); _Distance(_First, _Firstn, _Count1n); } _BidIt _Midn = _Buffered_rotate(_Firstn, _Mid, _Lastn, _Count1 - _Count1n, _Count2n, _Tempbuf); // rearrange middle _Buffered_merge(_First, _Firstn, _Midn, _Count1n, _Count2n, _Tempbuf); // merge each new part _Buffered_merge(_Midn, _Lastn, _Last, _Count1 - _Count1n, _Count2 - _Count2n, _Tempbuf); } } template inline void _Inplace_merge(_BidIt _First, _BidIt _Mid, _BidIt _Last, _Diff *, _Ty *) { // merge [_First, _Mid) with [_Mid, _Last), using operator< _Diff _Count1 = 0; _Distance(_First, _Mid, _Count1); _Diff _Count2 = 0; _Distance(_Mid, _Last, _Count2); _Temp_iterator<_Ty> _Tempbuf(_Count1 < _Count2 ? _Count1 : _Count2); _Buffered_merge(_First, _Mid, _Last, _Count1, _Count2, _Tempbuf); } template inline void inplace_merge(_BidIt _First, _BidIt _Mid, _BidIt _Last) { // merge [_First, _Mid) with [_Mid, _Last), using operator< if (_First != _Mid && _Mid != _Last) _Inplace_merge(_First, _Mid, _Last, _Dist_type(_First), _Val_type(_First)); } // TEMPLATE FUNCTION inplace_merge WITH PRED template inline _BidIt3 _Merge_backward(_BidIt1 _First1, _BidIt1 _Last1, _BidIt2 _First2, _BidIt2 _Last2, _BidIt3 _Dest, _Pr _Pred) { // merge backwards to _Dest, using _Pred for (; ; ) if (_First1 == _Last1) return (std::copy_backward(_First2, _Last2, _Dest)); else if (_First2 == _Last2) return (std::copy_backward(_First1, _Last1, _Dest)); else if (_Pred(*--_Last2, *--_Last1)) *--_Dest = *_Last1, ++_Last2; else *--_Dest = *_Last2, ++_Last1; } template inline void _Buffered_merge(_BidIt _First, _BidIt _Mid, _BidIt _Last, _Diff _Count1, _Diff _Count2, _Temp_iterator<_Ty>& _Tempbuf, _Pr _Pred) { // merge [_First, _Mid) with [_Mid, _Last), using _Pred if (_Count1 + _Count2 == 2) { // order two one-element partitions if (_Pred(*_Mid, *_First)) std::iter_swap(_First, _Mid); } else if (_Count1 <= _Count2 && _Count1 <= _Tempbuf._Maxlen()) { // buffer left partition, then merge std::copy(_First, _Mid, _Tempbuf._Init()); std::merge(_Tempbuf._First(), _Tempbuf._Last(), _Mid, _Last, _First, _Pred); } else if (_Count2 <= _Tempbuf._Maxlen()) { // buffer right partition, then merge std::copy(_Mid, _Last, _Tempbuf._Init()); _Merge_backward(_First, _Mid, _Tempbuf._First(), _Tempbuf._Last(), _Last, _Pred); } else { // buffer too small, divide and conquer _BidIt _Firstn, _Lastn; _Diff _Count1n, _Count2n; if (_Count2 < _Count1) { // left larger, cut it in half and partition right to match _Count1n = _Count1 / 2, _Count2n = 0; _Firstn = _First; std::advance(_Firstn, _Count1n); _Lastn = lower_bound(_Mid, _Last, *_Firstn, _Pred); _Distance(_Mid, _Lastn, _Count2n); } else { // right larger, cut it in half and partition left to match _Count1n = 0, _Count2n = _Count2 / 2; _Lastn = _Mid; std::advance(_Lastn, _Count2n); _Firstn = upper_bound(_First, _Mid, *_Lastn, _Pred); _Distance(_First, _Firstn, _Count1n); } _BidIt _Midn = _Buffered_rotate(_Firstn, _Mid, _Lastn, _Count1 - _Count1n, _Count2n, _Tempbuf); // rearrange middle _Buffered_merge(_First, _Firstn, _Midn, _Count1n, _Count2n, _Tempbuf, _Pred); // merge each new part _Buffered_merge(_Midn, _Lastn, _Last, _Count1 - _Count1n, _Count2 - _Count2n, _Tempbuf, _Pred); } } template inline void _Inplace_merge(_BidIt _First, _BidIt _Mid, _BidIt _Last, _Pr _Pred, _Diff *, _Ty *) { // merge [_First, _Mid) with [_Mid, _Last), using _Pred _Diff _Count1 = 0; _Distance(_First, _Mid, _Count1); _Diff _Count2 = 0; _Distance(_Mid, _Last, _Count2); _Temp_iterator<_Ty> _Tempbuf(_Count1 < _Count2 ? _Count1 : _Count2); _Buffered_merge(_First, _Mid, _Last, _Count1, _Count2, _Tempbuf, _Pred); } template inline void inplace_merge(_BidIt _First, _BidIt _Mid, _BidIt _Last, _Pr _Pred) { // merge [_First, _Mid) with [_Mid, _Last), using _Pred if (_First != _Mid && _Mid != _Last) _Inplace_merge(_First, _Mid, _Last, _Pred, _Dist_type(_First), _Val_type(_First)); } // TEMPLATE FUNCTION sort template inline void _Insertion_sort(_BidIt _First, _BidIt _Last) { // insertion sort [_First, _Last), using operator< if (_First != _Last) for (_BidIt _Next = _First; ++_Next != _Last; ) if (*_Next < *_First) { // found new earliest element, rotate to front _BidIt _Next1 = _Next; std::rotate(_First, _Next, ++_Next1); } else { // look for insertion point after first _BidIt _Dest = _Next; for (_BidIt _Dest0 = _Dest; *_Next < *--_Dest0; ) _Dest = _Dest0; if (_Dest != _Next) { // rotate into place _BidIt _Next1 = _Next; std::rotate(_Dest, _Next, ++_Next1); } } } template inline void _Med3(_RanIt _First, _RanIt _Mid, _RanIt _Last) { // sort median of three elements to middle if (*_Mid < *_First) std::iter_swap(_Mid, _First); if (*_Last < *_Mid) std::iter_swap(_Last, _Mid); if (*_Mid < *_First) std::iter_swap(_Mid, _First); } template inline void _Median(_RanIt _First, _RanIt _Mid, _RanIt _Last) { // sort median element to middle if (40 < _Last - _First) { // median of nine int _Step = (_Last - _First + 1) / 8; _Med3(_First, _First + _Step, _First + 2 * _Step); _Med3(_Mid - _Step, _Mid, _Mid + _Step); _Med3(_Last - 2 * _Step, _Last - _Step, _Last); _Med3(_First + _Step, _Mid, _Last - _Step); } else _Med3(_First, _Mid, _Last); } template inline pair<_RanIt, _RanIt> _Unguarded_partition(_RanIt _First, _RanIt _Last) { // partition [_First, _Last), using operator< _RanIt _Mid = _First + (_Last - _First) / 2; // sort median to _Mid _Median(_First, _Mid, _Last - 1); _RanIt _Pfirst = _Mid; _RanIt _Plast = _Pfirst + 1; while (_First < _Pfirst && !(*(_Pfirst - 1) < *_Pfirst) && !(*_Pfirst < *(_Pfirst - 1))) --_Pfirst; while (_Plast < _Last && !(*_Plast < *_Pfirst) && !(*_Pfirst < *_Plast)) ++_Plast; _RanIt _Gfirst = _Plast; _RanIt _Glast = _Pfirst; for (; ; ) { // partition for (; _Gfirst < _Last; ++_Gfirst) if (*_Pfirst < *_Gfirst) ; else if (*_Gfirst < *_Pfirst) break; else std::iter_swap(_Plast++, _Gfirst); for (; _First < _Glast; --_Glast) if (*(_Glast - 1) < *_Pfirst) ; else if (*_Pfirst < *(_Glast - 1)) break; else std::iter_swap(--_Pfirst, _Glast - 1); if (_Glast == _First && _Gfirst == _Last) return (pair<_RanIt, _RanIt>(_Pfirst, _Plast)); if (_Glast == _First) { // no room at bottom, rotate pivot upward if (_Plast != _Gfirst) std::iter_swap(_Pfirst, _Plast); ++_Plast; std::iter_swap(_Pfirst++, _Gfirst++); } else if (_Gfirst == _Last) { // no room at top, rotate pivot downward if (--_Glast != --_Pfirst) std::iter_swap(_Glast, _Pfirst); std::iter_swap(_Pfirst, --_Plast); } else std::iter_swap(_Gfirst++, --_Glast); } } template inline void _Sort(_RanIt _First, _RanIt _Last, _Diff _Ideal) { // order [_First, _Last), using operator< _Diff _Count; for (; _ISORT_MAX < (_Count = _Last - _First) && 0 < _Ideal; ) { // divide and conquer by quicksort pair<_RanIt, _RanIt> _Mid = _Unguarded_partition(_First, _Last); _Ideal /= 2, _Ideal += _Ideal / 2; // allow 1.5 log2(N) divisions if (_Mid.first - _First < _Last - _Mid.second) // loop on larger half _Sort(_First, _Mid.first, _Ideal), _First = _Mid.second; else _Sort(_Mid.second, _Last, _Ideal), _Last = _Mid.first; } if (_ISORT_MAX < _Count) { // heap sort if too many divisions std::make_heap(_First, _Last); std::sort_heap(_First, _Last); } else if (1 < _Count) _Insertion_sort(_First, _Last); // small, insertion sort } template inline void sort(_RanIt _First, _RanIt _Last) { // order [_First, _Last), using operator< _Sort(_First, _Last, _Last - _First); } // TEMPLATE FUNCTION sort WITH PRED template inline void _Insertion_sort(_BidIt _First, _BidIt _Last, _Pr _Pred) { // insertion sort [_First, _Last), using _Pred if (_First != _Last) for (_BidIt _Next = _First; ++_Next != _Last; ) if (_Pred(*_Next, *_First)) { // found new earliest element, rotate to front _BidIt _Next1 = _Next; std::rotate(_First, _Next, ++_Next1); } else { // look for insertion point after first _BidIt _Dest = _Next; for (_BidIt _Dest0 = _Dest; _Pred(*_Next, *--_Dest0); ) _Dest = _Dest0; if (_Dest != _Next) { // rotate into place _BidIt _Next1 = _Next; std::rotate(_Dest, _Next, ++_Next1); } } } template inline void _Med3(_RanIt _First, _RanIt _Mid, _RanIt _Last, _Pr _Pred) { // sort median of three elements to middle if (_Pred(*_Mid, *_First)) std::iter_swap(_Mid, _First); if (_Pred(*_Last, *_Mid)) std::iter_swap(_Last, _Mid); if (_Pred(*_Mid, *_First)) std::iter_swap(_Mid, _First); } template inline void _Median(_RanIt _First, _RanIt _Mid, _RanIt _Last, _Pr _Pred) { // sort median element to middle if (40 < _Last - _First) { // median of nine int _Step = (_Last - _First + 1) / 8; _Med3(_First, _First + _Step, _First + 2 * _Step, _Pred); _Med3(_Mid - _Step, _Mid, _Mid + _Step, _Pred); _Med3(_Last - 2 * _Step, _Last - _Step, _Last, _Pred); _Med3(_First + _Step, _Mid, _Last - _Step, _Pred); } else _Med3(_First, _Mid, _Last, _Pred); } template inline pair<_RanIt, _RanIt> _Unguarded_partition(_RanIt _First, _RanIt _Last, _Pr _Pred) { // partition [_First, _Last), using _Pred _RanIt _Mid = _First + (_Last - _First) / 2; _Median(_First, _Mid, _Last - 1, _Pred); _RanIt _Pfirst = _Mid; _RanIt _Plast = _Pfirst + 1; while (_First < _Pfirst && !_Pred(*(_Pfirst - 1), *_Pfirst) && !_Pred(*_Pfirst, *(_Pfirst - 1))) --_Pfirst; while (_Plast < _Last && !_Pred(*_Plast, *_Pfirst) && !_Pred(*_Pfirst, *_Plast)) ++_Plast; _RanIt _Gfirst = _Plast; _RanIt _Glast = _Pfirst; for (; ; ) { // partition for (; _Gfirst < _Last; ++_Gfirst) if (_Pred(*_Pfirst, *_Gfirst)) ; else if (_Pred(*_Gfirst, *_Pfirst)) break; else std::iter_swap(_Plast++, _Gfirst); for (; _First < _Glast; --_Glast) if (_Pred(*(_Glast - 1), *_Pfirst)) ; else if (_Pred(*_Pfirst, *(_Glast - 1))) break; else std::iter_swap(--_Pfirst, _Glast - 1); if (_Glast == _First && _Gfirst == _Last) return (pair<_RanIt, _RanIt>(_Pfirst, _Plast)); if (_Glast == _First) { // no room at bottom, rotate pivot upward if (_Plast != _Gfirst) std::iter_swap(_Pfirst, _Plast); ++_Plast; std::iter_swap(_Pfirst++, _Gfirst++); } else if (_Gfirst == _Last) { // no room at top, rotate pivot downward if (--_Glast != --_Pfirst) std::iter_swap(_Glast, _Pfirst); std::iter_swap(_Pfirst, --_Plast); } else std::iter_swap(_Gfirst++, --_Glast); } } template inline void _Sort(_RanIt _First, _RanIt _Last, _Diff _Ideal, _Pr _Pred) { // order [_First, _Last), using _Pred _Diff _Count; for (; _ISORT_MAX < (_Count = _Last - _First) && 0 < _Ideal; ) { // divide and conquer by quicksort pair<_RanIt, _RanIt> _Mid = _Unguarded_partition(_First, _Last, _Pred); _Ideal /= 2, _Ideal += _Ideal / 2; // allow 1.5 log2(N) divisions if (_Mid.first - _First < _Last - _Mid.second) // loop on larger half _Sort(_First, _Mid.first, _Ideal, _Pred), _First = _Mid.second; else _Sort(_Mid.second, _Last, _Ideal, _Pred), _Last = _Mid.first; } if (_ISORT_MAX < _Count) { // heap sort if too many divisions std::make_heap(_First, _Last, _Pred); std::sort_heap(_First, _Last, _Pred); } else if (1 < _Count) _Insertion_sort(_First, _Last, _Pred); // small, insertion sort } template inline void sort(_RanIt _First, _RanIt _Last, _Pr _Pred) { // order [_First, _Last), using _Pred _Sort(_First, _Last, _Last - _First, _Pred); } // TEMPLATE FUNCTION stable_sort template inline void _Chunked_merge(_BidIt _First, _BidIt _Last, _OutIt _Dest, _Diff _Chunk, _Diff _Count) { // copy merging chunks, using operator< for (_Diff _Chunk2 = _Chunk * 2; _Chunk2 <= _Count; _Count -= _Chunk2) { // copy merging pairs of adjacent chunks _BidIt _Mid1 = _First; std::advance(_Mid1, _Chunk); _BidIt _Mid2 = _Mid1; std::advance(_Mid2, _Chunk); _Dest = std::merge(_First, _Mid1, _Mid1, _Mid2, _Dest); _First = _Mid2; } if (_Count <= _Chunk) std::copy(_First, _Last, _Dest); // copy partial last chunk else { // copy merging whole and partial last chunk _BidIt _Mid = _First; std::advance(_Mid, _Chunk); std::merge(_First, _Mid, _Mid, _Last, _Dest); } } template inline void _Buffered_merge_sort(_BidIt _First, _BidIt _Last, _Diff _Count, _Temp_iterator<_Ty>& _Tempbuf) { // sort using temp buffer for merges, using operator< _BidIt _Mid = _First; for (_Diff _Nleft = _Count; _ISORT_MAX <= _Nleft; _Nleft -= _ISORT_MAX) { // sort chunks _BidIt _Midend = _Mid; std::advance(_Midend, (int)_ISORT_MAX); _Insertion_sort(_Mid, _Midend); _Mid = _Midend; } _Insertion_sort(_Mid, _Last); // sort partial last chunk for (_Diff _Chunk = _ISORT_MAX; _Chunk < _Count; _Chunk *= 2) { // merge adjacent pairs of chunks to and from temp buffer _Chunked_merge(_First, _Last, _Tempbuf._Init(), _Chunk, _Count); _Chunked_merge(_Tempbuf._First(), _Tempbuf._Last(), _First, _Chunk *= 2, _Count); } } template inline void _Stable_sort(_BidIt _First, _BidIt _Last, _Diff _Count, _Temp_iterator<_Ty>& _Tempbuf) { // sort preserving order of equivalents, using operator< if (_Count <= _ISORT_MAX) _Insertion_sort(_First, _Last); // small, insertion sort else { // sort halves and merge _Diff _Count2 = (_Count + 1) / 2; _BidIt _Mid = _First; std::advance(_Mid, _Count2); if (_Count2 <= _Tempbuf._Maxlen()) { // temp buffer big enough, sort each half using buffer _Buffered_merge_sort(_First, _Mid, _Count2, _Tempbuf); _Buffered_merge_sort(_Mid, _Last, _Count - _Count2, _Tempbuf); } else { // temp buffer not big enough, divide and conquer _Stable_sort(_First, _Mid, _Count2, _Tempbuf); _Stable_sort(_Mid, _Last, _Count - _Count2, _Tempbuf); } _Buffered_merge(_First, _Mid, _Last, _Count2, _Count - _Count2, _Tempbuf); // merge sorted halves } } template inline void _Stable_sort(_BidIt _First, _BidIt _Last, _Diff *, _Ty *) { // sort preserving order of equivalents, using operator< _Diff _Count = 0; _Distance(_First, _Last, _Count); _Temp_iterator<_Ty> _Tempbuf(_Count); _Stable_sort(_First, _Last, _Count, _Tempbuf); } template inline void stable_sort(_BidIt _First, _BidIt _Last) { // sort preserving order of equivalents, using operator< if (_First != _Last) _Stable_sort(_First, _Last, _Dist_type(_First), _Val_type(_First)); } // TEMPLATE FUNCTION stable_sort WITH PRED template inline void _Chunked_merge(_BidIt _First, _BidIt _Last, _OutIt _Dest, _Diff _Chunk, _Diff _Count, _Pr _Pred) { // copy merging chunks, using _Pred for (_Diff _Chunk2 = _Chunk * 2; _Chunk2 <= _Count; _Count -= _Chunk2) { // copy merging pairs of adjacent chunks _BidIt _Mid1 = _First; std::advance(_Mid1, _Chunk); _BidIt _Mid2 = _Mid1; std::advance(_Mid2, _Chunk); _Dest = std::merge(_First, _Mid1, _Mid1, _Mid2, _Dest, _Pred); _First = _Mid2; } if (_Count <= _Chunk) std::copy(_First, _Last, _Dest); // copy partial last chunk else { // copy merging whole and partial last chunk _BidIt _Mid1 = _First; std::advance(_Mid1, _Chunk); std::merge(_First, _Mid1, _Mid1, _Last, _Dest, _Pred); } } template inline void _Buffered_merge_sort(_BidIt _First, _BidIt _Last, _Diff _Count, _Temp_iterator<_Ty>& _Tempbuf, _Pr _Pred) { // sort using temp buffer for merges, using _Pred _BidIt _Mid = _First; for (_Diff _Nleft = _Count; _ISORT_MAX <= _Nleft; _Nleft -= _ISORT_MAX) { // sort chunks _BidIt _Midn = _Mid; std::advance(_Midn, (int)_ISORT_MAX); _Insertion_sort(_Mid, _Midn, _Pred); _Mid = _Midn; } _Insertion_sort(_Mid, _Last, _Pred); // sort partial last chunk for (_Diff _Chunk = _ISORT_MAX; _Chunk < _Count; _Chunk *= 2) { // merge adjacent pairs of chunks to and from temp buffer _Chunked_merge(_First, _Last, _Tempbuf._Init(), _Chunk, _Count, _Pred); _Chunked_merge(_Tempbuf._First(), _Tempbuf._Last(), _First, _Chunk *= 2, _Count, _Pred); } } template inline void _Stable_sort(_BidIt _First, _BidIt _Last, _Diff _Count, _Temp_iterator<_Ty>& _Tempbuf, _Pr _Pred) { // sort preserving order of equivalents, using _Pred if (_Count <= _ISORT_MAX) _Insertion_sort(_First, _Last, _Pred); // small, insertion sort else { // sort halves and merge _Diff _Count2 = (_Count + 1) / 2; _BidIt _Mid = _First; std::advance(_Mid, _Count2); if (_Count2 <= _Tempbuf._Maxlen()) { // temp buffer big enough, sort each half using buffer _Buffered_merge_sort(_First, _Mid, _Count2, _Tempbuf, _Pred); _Buffered_merge_sort(_Mid, _Last, _Count - _Count2, _Tempbuf, _Pred); } else { // temp buffer not big enough, divide and conquer _Stable_sort(_First, _Mid, _Count2, _Tempbuf, _Pred); _Stable_sort(_Mid, _Last, _Count - _Count2, _Tempbuf, _Pred); } _Buffered_merge(_First, _Mid, _Last, _Count2, _Count - _Count2, _Tempbuf, _Pred); // merge halves } } template inline void _Stable_sort(_BidIt _First, _BidIt _Last, _Diff *, _Ty *, _Pr _Pred) { // sort preserving order of equivalents, using _Pred _Diff _Count = 0; _Distance(_First, _Last, _Count); _Temp_iterator<_Ty> _Tempbuf(_Count); _Stable_sort(_First, _Last, _Count, _Tempbuf, _Pred); } template inline void stable_sort(_BidIt _First, _BidIt _Last, _Pr _Pred) { // sort preserving order of equivalents, using _Pred if (_First != _Last) _Stable_sort(_First, _Last, _Dist_type(_First), _Val_type(_First), _Pred); } // TEMPLATE FUNCTION partial_sort template inline void _Partial_sort(_RanIt _First, _RanIt _Mid, _RanIt _Last, _Ty *) { // order [First, _Last) up to _Mid, using operator< std::make_heap(_First, _Mid); for (_RanIt _Next = _Mid; _Next < _Last; ++_Next) if (*_Next < *_First) _Pop_heap(_First, _Mid, _Next, _Ty(*_Next), _Dist_type(_First)); // replace top with new largest std::sort_heap(_First, _Mid); } template inline void partial_sort(_RanIt _First, _RanIt _Mid, _RanIt _Last) { // order [First, _Last) up to _Mid, using operator< _Partial_sort(_First, _Mid, _Last, _Val_type(_First)); } // TEMPLATE FUNCTION partial_sort WITH PRED template inline void _Partial_sort(_RanIt _First, _RanIt _Mid, _RanIt _Last, _Pr _Pred, _Ty *) { // order [First, _Last) up to _Mid, using _Pred std::make_heap(_First, _Mid, _Pred); for (_RanIt _Next = _Mid; _Next < _Last; ++_Next) if (_Pred(*_Next, *_First)) _Pop_heap(_First, _Mid, _Next, _Ty(*_Next), _Pred, _Dist_type(_First)); // replace top with new largest std::sort_heap(_First, _Mid, _Pred); } template inline void partial_sort(_RanIt _First, _RanIt _Mid, _RanIt _Last, _Pr _Pred) { // order [First, _Last) up to _Mid, using _Pred _Partial_sort(_First, _Mid, _Last, _Pred, _Val_type(_First)); } // TEMPLATE FUNCTION partial_sort_copy template inline _RanIt _Partial_sort_copy(_InIt _First1, _InIt _Last1, _RanIt _First2, _RanIt _Last2, _Diff *, _Ty *) { // copy [First1, _Last1) into [_First2, _Last2), using operator< _RanIt _Mid2 = _First2; for (; _First1 != _Last1 && _Mid2 != _Last2; ++_First1, ++_Mid2) *_Mid2 = *_First1; // copy min(_Last1 - _First1, _Last2 - _First2) std::make_heap(_First2, _Mid2); for (; _First1 != _Last1; ++_First1) if (*_First1 < *_First2) _Adjust_heap(_First2, _Diff(0), _Diff(_Mid2 - _First2), _Ty(*_First1)); // replace top with new largest std::sort_heap(_First2, _Mid2); return (_Mid2); } template inline _RanIt partial_sort_copy(_InIt _First1, _InIt _Last1, _RanIt _First2, _RanIt _Last2) { // copy [First1, _Last1) into [_First2, _Last2), using operator< return (_First1 == _Last1 || _First2 == _Last2 ? _First2 : _Partial_sort_copy(_First1, _Last1, _First2, _Last2, _Dist_type(_First2), _Val_type(_First1))); } // TEMPLATE FUNCTION partial_sort_copy WITH PRED template inline _RanIt _Partial_sort_copy(_InIt _First1, _InIt _Last1, _RanIt _First2, _RanIt _Last2, _Pr _Pred, _Diff *, _Ty *) { // copy [First1, _Last1) into [_First2, _Last2) using _Pred _RanIt _Mid2 = _First2; for (; _First1 != _Last1 && _Mid2 != _Last2; ++_First1, ++_Mid2) *_Mid2 = *_First1; // copy min(_Last1 - _First1, _Last2 - _First2) std::make_heap(_First2, _Mid2, _Pred); for (; _First1 != _Last1; ++_First1) if (_Pred(*_First1, *_First2)) _Adjust_heap(_First2, _Diff(0), _Diff(_Mid2 - _First2), _Ty(*_First1), _Pred); // replace top with new largest std::sort_heap(_First2, _Mid2, _Pred); return (_Mid2); } template inline _RanIt partial_sort_copy(_InIt _First1, _InIt _Last1, _RanIt _First2, _RanIt _Last2, _Pr _Pred) { // copy [First1, _Last1) into [_First2, _Last2) using _Pred return (_First1 == _Last1 || _First2 == _Last2 ? _First2 : _Partial_sort_copy(_First1, _Last1, _First2, _Last2, _Pred, _Dist_type(_First2), _Val_type(_First1))); } // TEMPLATE FUNCTION nth_element template inline void nth_element(_RanIt _First, _RanIt _Nth, _RanIt _Last) { // order Nth element, using operator< for (; _ISORT_MAX < _Last - _First; ) { // divide and conquer, ordering partition containing Nth pair<_RanIt, _RanIt> _Mid = _Unguarded_partition(_First, _Last); if (_Mid.second <= _Nth) _First = _Mid.second; else if (_Mid.first <= _Nth) return; // Nth inside fat pivot, done else _Last = _Mid.first; } _Insertion_sort(_First, _Last); // sort any remainder } // TEMPLATE FUNCTION nth_element WITH PRED template inline void nth_element(_RanIt _First, _RanIt _Nth, _RanIt _Last, _Pr _Pred) { // order Nth element, using _Pred for (; _ISORT_MAX < _Last - _First; ) { // divide and conquer, ordering partition containing Nth pair<_RanIt, _RanIt> _Mid = _Unguarded_partition(_First, _Last, _Pred); if (_Mid.second <= _Nth) _First = _Mid.second; else if (_Mid.first <= _Nth) return; // Nth inside fat pivot, done else _Last = _Mid.first; } _Insertion_sort(_First, _Last, _Pred); // sort any remainder } // TEMPLATE FUNCTION includes template inline bool includes(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2) { // test if all [_First1, _Last1) in [_First2, _Last2), using operator< for (; _First1 != _Last1 && _First2 != _Last2; ) if (*_First2 < *_First1) return (false); else if (*_First1 < *_First2) ++_First1; else ++_First1, ++_First2; return (_First2 == _Last2); } // TEMPLATE FUNCTION includes WITH PRED template inline bool includes(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _Pr _Pred) { // test if set [_First1, _Last1) in [_First2, _Last2), using _Pred for (; _First1 != _Last1 && _First2 != _Last2; ) if (_Pred(*_First2, *_First1)) return (false); else if (_Pred(*_First1, *_First2)) ++_First1; else ++_First1, ++_First2; return (_First2 == _Last2); } // TEMPLATE FUNCTION set_union template inline _OutIt set_union(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _OutIt _Dest) { // OR sets [_First1, _Last1) and [_First2, _Last2), using operator< for (; _First1 != _Last1 && _First2 != _Last2; ) if (*_First1 < *_First2) *_Dest++ = *_First1, ++_First1; else if (*_First2 < *_First1) *_Dest++ = *_First2, ++_First2; else *_Dest++ = *_First1, ++_First1, ++_First2; _Dest = std::copy(_First1, _Last1, _Dest); return (std::copy(_First2, _Last2, _Dest)); } // TEMPLATE FUNCTION set_union WITH PRED template inline _OutIt set_union(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _OutIt _Dest, _Pr _Pred) { // OR sets [_First1, _Last1) and [_First2, _Last2), using _Pred for (; _First1 != _Last1 && _First2 != _Last2; ) if (_Pred(*_First1, *_First2)) *_Dest++ = *_First1, ++_First1; else if (_Pred(*_First2, *_First1)) *_Dest++ = *_First2, ++_First2; else *_Dest++ = *_First1, ++_First1, ++_First2; _Dest = std::copy(_First1, _Last1, _Dest); return (std::copy(_First2, _Last2, _Dest)); } // TEMPLATE FUNCTION set_intersection template inline _OutIt set_intersection(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _OutIt _Dest) { // AND sets [_First1, _Last1) and [_First2, _Last2), using operator< for (; _First1 != _Last1 && _First2 != _Last2; ) if (*_First1 < *_First2) ++_First1; else if (*_First2 < *_First1) ++_First2; else *_Dest++ = *_First1++, ++_First2; return (_Dest); } // TEMPLATE FUNCTION set_intersection WITH PRED template inline _OutIt set_intersection(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _OutIt _Dest, _Pr _Pred) { // AND sets [_First1, _Last1) and [_First2, _Last2), using _Pred for (; _First1 != _Last1 && _First2 != _Last2; ) if (_Pred(*_First1, *_First2)) ++_First1; else if (_Pred(*_First2, *_First1)) ++_First2; else *_Dest++ = *_First1++, ++_First2; return (_Dest); } // TEMPLATE FUNCTION set_difference template inline _OutIt set_difference(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _OutIt _Dest) { // take set [_First2, _Last2) from [_First1, _Last1), using operator< for (; _First1 != _Last1 && _First2 != _Last2; ) if (*_First1 < *_First2) *_Dest++ = *_First1, ++_First1; else if (*_First2 < *_First1) ++_First2; else ++_First1, ++_First2; return (std::copy(_First1, _Last1, _Dest)); } // TEMPLATE FUNCTION set_difference WITH PRED template inline _OutIt set_difference(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _OutIt _Dest, _Pr _Pred) { // take set [_First2, _Last2) from [_First1, _Last1), using _Pred for (; _First1 != _Last1 && _First2 != _Last2; ) if (_Pred(*_First1, *_First2)) *_Dest++ = *_First1, ++_First1; else if (_Pred(*_First2, *_First1)) ++_First2; else ++_First1, ++_First2; return (std::copy(_First1, _Last1, _Dest)); } // TEMPLATE FUNCTION set_symmetric_difference template inline _OutIt set_symmetric_difference(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _OutIt _Dest) { // XOR sets [_First1, _Last1) and [_First2, _Last2), using operator< for (; _First1 != _Last1 && _First2 != _Last2; ) if (*_First1 < *_First2) *_Dest++ = *_First1, ++_First1; else if (*_First2 < *_First1) *_Dest++ = *_First2, ++_First2; else ++_First1, ++_First2; _Dest = std::copy(_First1, _Last1, _Dest); return (std::copy(_First2, _Last2, _Dest)); } // TEMPLATE FUNCTION set_symmetric_difference WITH PRED template inline _OutIt set_symmetric_difference(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _OutIt _Dest, _Pr _Pred) { // XOR sets [_First1, _Last1) and [_First2, _Last2), using _Pred for (; _First1 != _Last1 && _First2 != _Last2; ) if (_Pred(*_First1, *_First2)) *_Dest++ = *_First1, ++_First1; else if (_Pred(*_First2, *_First1)) *_Dest++ = *_First2, ++_First2; else ++_First1, ++_First2; _Dest = std::copy(_First1, _Last1, _Dest); return (std::copy(_First2, _Last2, _Dest)); } // TEMPLATE FUNCTION max_element template inline _FwdIt max_element(_FwdIt _First, _FwdIt _Last) { // find largest element, using operator< _FwdIt _Found = _First; if (_First != _Last) for (; ++_First != _Last; ) if (*_Found < *_First) _Found = _First; return (_Found); } // TEMPLATE FUNCTION max_element WITH PRED template inline _FwdIt max_element(_FwdIt _First, _FwdIt _Last, _Pr _Pred) { // find largest element, using _Pred _FwdIt _Found = _First; if (_First != _Last) for (; ++_First != _Last; ) if (_Pred(*_Found, *_First)) _Found = _First; return (_Found); } // TEMPLATE FUNCTION min_element template inline _FwdIt min_element(_FwdIt _First, _FwdIt _Last) { // find smallest element, using operator< _FwdIt _Found = _First; if (_First != _Last) for (; ++_First != _Last; ) if (*_First < *_Found) _Found = _First; return (_Found); } // TEMPLATE FUNCTION min_element WITH PRED template inline _FwdIt min_element(_FwdIt _First, _FwdIt _Last, _Pr _Pred) { // find smallest element, using _Pred _FwdIt _Found = _First; if (_First != _Last) for (; ++_First != _Last; ) if (_Pred(*_First, *_Found)) _Found = _First; return (_Found); } // TEMPLATE FUNCTION next_permutation template inline bool next_permutation(_BidIt _First, _BidIt _Last) { // permute and test for pure ascending, using operator< _BidIt _Next = _Last; if (_First == _Last || _First == --_Next) return (false); for (; ; ) { // find rightmost element smaller than successor _BidIt _Next1 = _Next; if (*--_Next < *_Next1) { // swap with rightmost element that's smaller, flip suffix _BidIt _Mid = _Last; for (; !(*_Next < *--_Mid); ) ; std::iter_swap(_Next, _Mid); std::reverse(_Next1, _Last); return (true); } if (_Next == _First) { // pure descending, flip all std::reverse(_First, _Last); return (false); } } } // TEMPLATE FUNCTION next_permutation WITH PRED template inline bool next_permutation(_BidIt _First, _BidIt _Last, _Pr _Pred) { // permute and test for pure ascending, using _Pred _BidIt _Next = _Last; if (_First == _Last || _First == --_Next) return (false); for (; ; ) { // find rightmost element smaller than successor _BidIt _Next1 = _Next; if (_Pred(*--_Next, *_Next1)) { // swap with rightmost element that's smaller, flip suffix _BidIt _Mid = _Last; for (; !_Pred(*_Next, *--_Mid); ) ; std::iter_swap(_Next, _Mid); std::reverse(_Next1, _Last); return (true); } if (_Next == _First) { // pure descending, flip all std::reverse(_First, _Last); return (false); } } } // TEMPLATE FUNCTION prev_permutation template inline bool prev_permutation(_BidIt _First, _BidIt _Last) { // reverse permute and test for pure descending, using operator< _BidIt _Next = _Last; if (_First == _Last || _First == --_Next) return (false); for (; ; ) { // find rightmost element not smaller than successor _BidIt _Next1 = _Next; if (!(*--_Next < *_Next1)) { // swap with rightmost element that's not smaller, flip suffix _BidIt _Mid = _Last; for (; *_Next < *--_Mid; ) ; std::iter_swap(_Next, _Mid); std::reverse(_Next1, _Last); return (true); } if (_Next == _First) { // pure ascending, flip all std::reverse(_First, _Last); return (false); } } } // TEMPLATE FUNCTION prev_permutation WITH PRED template inline bool prev_permutation(_BidIt _First, _BidIt _Last, _Pr _Pred) { // reverse permute and test for pure descending, using _Pred _BidIt _Next = _Last; if (_First == _Last || _First == --_Next) return (false); for (; ; ) { // find rightmost element not smaller than successor _BidIt _Next1 = _Next; if (!_Pred(*--_Next, *_Next1)) { // swap with rightmost element that's not smaller, flip suffix _BidIt _Mid = _Last; for (; _Pred(*_Next, *--_Mid); ) ; std::iter_swap(_Next, _Mid); std::reverse(_Next1, _Last); return (true); } if (_Next == _First) { // pure ascending, flip all std::reverse(_First, _Last); return (false); } } } _STD_END #pragma warning(default: 4244) #pragma warning(pop) #pragma pack(pop) #endif /* _ALGORITHM_ */ /* * Copyright (c) 1992-2001 by P.J. Plauger. ALL RIGHTS RESERVED. * Consult your license regarding permissions and restrictions. */ /* * This file is derived from software bearing the following * restrictions: * * Copyright (c) 1994 * Hewlett-Packard Company * * Permission to use, copy, modify, distribute and sell this * software and its documentation for any purpose is hereby * granted without fee, provided that the above copyright notice * appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation. * Hewlett-Packard Company makes no representations about the * suitability of this software for any purpose. It is provided * "as is" without express or implied warranty. V3.10:0009 */