2671 lines
76 KiB
Plaintext
2671 lines
76 KiB
Plaintext
|
// algorithm standard header
|
||
|
#pragma once
|
||
|
#ifndef _ALGORITHM_
|
||
|
#define _ALGORITHM_
|
||
|
#include <memory>
|
||
|
|
||
|
#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<class _InIt,
|
||
|
class _Fn1> 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<class _InIt,
|
||
|
class _Ty> 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<class _InIt,
|
||
|
class _Pr> 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<class _FwdIt> 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<class _FwdIt,
|
||
|
class _Pr> 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<class _InIt,
|
||
|
class _Ty> 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<class _InIt,
|
||
|
class _Pr> 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<class _FwdIt1,
|
||
|
class _FwdIt2,
|
||
|
class _Diff1,
|
||
|
class _Diff2> 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<class _FwdIt1,
|
||
|
class _FwdIt2> 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<class _FwdIt1,
|
||
|
class _FwdIt2,
|
||
|
class _Diff1,
|
||
|
class _Diff2,
|
||
|
class _Pr> 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<class _FwdIt1,
|
||
|
class _FwdIt2,
|
||
|
class _Pr> 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<class _FwdIt1,
|
||
|
class _Diff2,
|
||
|
class _Ty,
|
||
|
class _Diff1> 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<class _FwdIt1,
|
||
|
class _Diff2,
|
||
|
class _Ty> 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<class _FwdIt1,
|
||
|
class _Diff2,
|
||
|
class _Ty,
|
||
|
class _Diff1,
|
||
|
class _Pr> 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<class _FwdIt1,
|
||
|
class _Diff2,
|
||
|
class _Ty,
|
||
|
class _Pr> 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<class _FwdIt1,
|
||
|
class _FwdIt2,
|
||
|
class _Diff1,
|
||
|
class _Diff2> 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<class _FwdIt1,
|
||
|
class _FwdIt2> 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<class _FwdIt1,
|
||
|
class _FwdIt2,
|
||
|
class _Diff1,
|
||
|
class _Diff2,
|
||
|
class _Pr> 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<class _FwdIt1,
|
||
|
class _FwdIt2,
|
||
|
class _Pr> 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<class _FwdIt1,
|
||
|
class _FwdIt2> 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<class _FwdIt1,
|
||
|
class _FwdIt2,
|
||
|
class _Pr> 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<class _FwdIt1,
|
||
|
class _FwdIt2> inline
|
||
|
void iter_swap(_FwdIt1 _Left, _FwdIt2 _Right)
|
||
|
{ // swap *_Left and *_Right
|
||
|
std::swap(*_Left, *_Right);
|
||
|
}
|
||
|
|
||
|
// TEMPLATE FUNCTION swap_ranges
|
||
|
template<class _FwdIt1,
|
||
|
class _FwdIt2> 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<class _InIt,
|
||
|
class _OutIt,
|
||
|
class _Fn1> 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<class _InIt1,
|
||
|
class _InIt2,
|
||
|
class _OutIt,
|
||
|
class _Fn2> 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<class _FwdIt,
|
||
|
class _Ty> 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<class _FwdIt,
|
||
|
class _Pr,
|
||
|
class _Ty> 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<class _InIt,
|
||
|
class _OutIt,
|
||
|
class _Ty> 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<class _InIt,
|
||
|
class _OutIt,
|
||
|
class _Pr,
|
||
|
class _Ty> 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<class _FwdIt,
|
||
|
class _Fn0> 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<class _OutIt,
|
||
|
class _Diff,
|
||
|
class _Fn0> 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<class _InIt,
|
||
|
class _OutIt,
|
||
|
class _Ty> 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<class _InIt,
|
||
|
class _OutIt,
|
||
|
class _Pr> 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<class _FwdIt,
|
||
|
class _Ty> 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<class _FwdIt,
|
||
|
class _Pr> 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<class _FwdIt> 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<class _FwdIt,
|
||
|
class _Pr> 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<class _InIt,
|
||
|
class _OutIt,
|
||
|
class _Ty> 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<class _InIt,
|
||
|
class _OutIt> 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<class _FwdIt,
|
||
|
class _OutIt> 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<class _BidIt,
|
||
|
class _OutIt> 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<class _RanIt,
|
||
|
class _OutIt> 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<class _InIt,
|
||
|
class _OutIt> 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<class _InIt,
|
||
|
class _OutIt,
|
||
|
class _Ty,
|
||
|
class _Pr> 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<class _InIt,
|
||
|
class _OutIt,
|
||
|
class _Pr> 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<class _FwdIt,
|
||
|
class _OutIt,
|
||
|
class _Pr> 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<class _BidIt,
|
||
|
class _OutIt,
|
||
|
class _Pr> 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<class _RanIt,
|
||
|
class _OutIt,
|
||
|
class _Pr> 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<class _InIt,
|
||
|
class _OutIt,
|
||
|
class _Pr> 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<class _BidIt> 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<class _RanIt> 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<class _BidIt> inline
|
||
|
void reverse(_BidIt _First, _BidIt _Last)
|
||
|
{ // reverse elements in [_First, _Last)
|
||
|
_Reverse(_First, _Last, _Iter_cat(_First));
|
||
|
}
|
||
|
|
||
|
// TEMPLATE FUNCTION reverse_copy
|
||
|
template<class _BidIt,
|
||
|
class _OutIt> 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<class _FwdIt> 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<class _BidIt> 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<class _RanIt,
|
||
|
class _Diff,
|
||
|
class _Ty> 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<class _RanIt> 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<class _FwdIt> 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<class _FwdIt,
|
||
|
class _OutIt> 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<class _RanIt,
|
||
|
class _Diff> 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<class _RanIt> 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<class _RanIt,
|
||
|
class _Fn1,
|
||
|
class _Diff> 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<class _RanIt,
|
||
|
class _Fn1> 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<class _BidIt,
|
||
|
class _Pr> 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<class _BidIt,
|
||
|
class _Pr,
|
||
|
class _Diff,
|
||
|
class _Ty> 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<class _BidIt,
|
||
|
class _Pr,
|
||
|
class _Diff,
|
||
|
class _Ty> 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<class _BidIt,
|
||
|
class _Pr> 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<class _RanIt,
|
||
|
class _Diff,
|
||
|
class _Ty> 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<class _RanIt,
|
||
|
class _Diff,
|
||
|
class _Ty> 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<class _RanIt> 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<class _RanIt,
|
||
|
class _Diff,
|
||
|
class _Ty,
|
||
|
class _Pr> 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<class _RanIt,
|
||
|
class _Diff,
|
||
|
class _Ty,
|
||
|
class _Pr> 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<class _RanIt,
|
||
|
class _Pr> 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<class _RanIt,
|
||
|
class _Diff,
|
||
|
class _Ty> 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<class _RanIt,
|
||
|
class _Diff,
|
||
|
class _Ty> 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<class _RanIt,
|
||
|
class _Ty> 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<class _RanIt> 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<class _RanIt,
|
||
|
class _Diff,
|
||
|
class _Ty,
|
||
|
class _Pr> 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<class _RanIt,
|
||
|
class _Diff,
|
||
|
class _Ty,
|
||
|
class _Pr> 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<class _RanIt,
|
||
|
class _Ty,
|
||
|
class _Pr> 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<class _RanIt,
|
||
|
class _Pr> 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<class _RanIt,
|
||
|
class _Diff,
|
||
|
class _Ty> 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<class _RanIt> 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<class _RanIt,
|
||
|
class _Diff,
|
||
|
class _Ty,
|
||
|
class _Pr> 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<class _RanIt,
|
||
|
class _Pr> 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<class _RanIt> 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<class _RanIt,
|
||
|
class _Pr> 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<class _FwdIt,
|
||
|
class _Ty,
|
||
|
class _Diff> 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<class _FwdIt,
|
||
|
class _Ty> 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<class _FwdIt,
|
||
|
class _Ty,
|
||
|
class _Diff,
|
||
|
class _Pr> 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<class _FwdIt,
|
||
|
class _Ty,
|
||
|
class _Pr> 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<class _FwdIt,
|
||
|
class _Ty,
|
||
|
class _Diff> 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<class _FwdIt,
|
||
|
class _Ty> 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<class _FwdIt,
|
||
|
class _Ty,
|
||
|
class _Diff,
|
||
|
class _Pr> 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<class _FwdIt,
|
||
|
class _Ty,
|
||
|
class _Pr> 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<class _FwdIt,
|
||
|
class _Ty,
|
||
|
class _Diff> 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<class _FwdIt,
|
||
|
class _Ty> 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<class _FwdIt,
|
||
|
class _Ty,
|
||
|
class _Diff,
|
||
|
class _Pr> 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<class _FwdIt,
|
||
|
class _Ty,
|
||
|
class _Pr> 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<class _FwdIt,
|
||
|
class _Ty> 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<class _FwdIt,
|
||
|
class _Ty,
|
||
|
class _Pr> 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<class _InIt1,
|
||
|
class _InIt2,
|
||
|
class _OutIt> 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<class _InIt1,
|
||
|
class _InIt2,
|
||
|
class _OutIt,
|
||
|
class _Pr> 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<class _BidIt,
|
||
|
class _Diff,
|
||
|
class _Ty> 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<class _BidIt1,
|
||
|
class _BidIt2,
|
||
|
class _BidIt3> 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<class _BidIt,
|
||
|
class _Diff,
|
||
|
class _Ty> 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<class _BidIt,
|
||
|
class _Diff,
|
||
|
class _Ty> 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<class _BidIt> 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<class _BidIt1,
|
||
|
class _BidIt2,
|
||
|
class _BidIt3,
|
||
|
class _Pr> 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<class _BidIt,
|
||
|
class _Diff,
|
||
|
class _Ty,
|
||
|
class _Pr> 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<class _BidIt,
|
||
|
class _Diff,
|
||
|
class _Ty,
|
||
|
class _Pr> 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<class _BidIt,
|
||
|
class _Pr> 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<class _BidIt> 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<class _RanIt> 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<class _RanIt> 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<class _RanIt> 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<class _RanIt,
|
||
|
class _Diff> 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<class _RanIt> inline
|
||
|
void sort(_RanIt _First, _RanIt _Last)
|
||
|
{ // order [_First, _Last), using operator<
|
||
|
_Sort(_First, _Last, _Last - _First);
|
||
|
}
|
||
|
|
||
|
// TEMPLATE FUNCTION sort WITH PRED
|
||
|
template<class _BidIt,
|
||
|
class _Pr> 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<class _RanIt,
|
||
|
class _Pr> 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<class _RanIt,
|
||
|
class _Pr> 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<class _RanIt,
|
||
|
class _Pr> 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<class _RanIt,
|
||
|
class _Diff,
|
||
|
class _Pr> 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<class _RanIt,
|
||
|
class _Pr> 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<class _BidIt,
|
||
|
class _OutIt,
|
||
|
class _Diff> 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<class _BidIt,
|
||
|
class _Diff,
|
||
|
class _Ty> 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<class _BidIt,
|
||
|
class _Diff,
|
||
|
class _Ty> 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<class _BidIt,
|
||
|
class _Diff,
|
||
|
class _Ty> 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<class _BidIt> 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<class _BidIt,
|
||
|
class _OutIt,
|
||
|
class _Diff,
|
||
|
class _Pr> 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<class _BidIt,
|
||
|
class _Diff,
|
||
|
class _Ty,
|
||
|
class _Pr> 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<class _BidIt,
|
||
|
class _Diff,
|
||
|
class _Ty,
|
||
|
class _Pr> 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<class _BidIt,
|
||
|
class _Diff,
|
||
|
class _Ty,
|
||
|
class _Pr> 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<class _BidIt,
|
||
|
class _Pr> 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<class _RanIt,
|
||
|
class _Ty> 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<class _RanIt> 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<class _RanIt,
|
||
|
class _Ty,
|
||
|
class _Pr> 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<class _RanIt,
|
||
|
class _Pr> 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<class _InIt,
|
||
|
class _RanIt,
|
||
|
class _Diff,
|
||
|
class _Ty> 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<class _InIt,
|
||
|
class _RanIt> 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<class _InIt,
|
||
|
class _RanIt,
|
||
|
class _Diff,
|
||
|
class _Ty, class _Pr> 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<class _InIt,
|
||
|
class _RanIt,
|
||
|
class _Pr> 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<class _RanIt> 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<class _RanIt,
|
||
|
class _Pr> 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<class _InIt1,
|
||
|
class _InIt2> 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<class _InIt1,
|
||
|
class _InIt2,
|
||
|
class _Pr> 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<class _InIt1,
|
||
|
class _InIt2,
|
||
|
class _OutIt> 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<class _InIt1,
|
||
|
class _InIt2,
|
||
|
class _OutIt,
|
||
|
class _Pr> 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<class _InIt1,
|
||
|
class _InIt2,
|
||
|
class _OutIt> 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<class _InIt1,
|
||
|
class _InIt2,
|
||
|
class _OutIt,
|
||
|
class _Pr> 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<class _InIt1,
|
||
|
class _InIt2,
|
||
|
class _OutIt> 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<class _InIt1,
|
||
|
class _InIt2,
|
||
|
class _OutIt,
|
||
|
class _Pr> 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<class _InIt1,
|
||
|
class _InIt2,
|
||
|
class _OutIt> 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<class _InIt1,
|
||
|
class _InIt2,
|
||
|
class _OutIt,
|
||
|
class _Pr> 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<class _FwdIt> 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<class _FwdIt,
|
||
|
class _Pr> 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<class _FwdIt> 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<class _FwdIt,
|
||
|
class _Pr> 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<class _BidIt> 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<class _BidIt,
|
||
|
class _Pr> 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<class _BidIt> 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<class _BidIt,
|
||
|
class _Pr> 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 */
|