1895 lines
55 KiB
C++
1895 lines
55 KiB
C++
/***************************************************************************
|
|
*
|
|
* algorithm.cc - Non-inline definitions for the Standard Library algorithms
|
|
*
|
|
* $Id: algorithm.cc 533854 2007-04-30 20:59:43Z sebor $
|
|
*
|
|
***************************************************************************
|
|
*
|
|
* 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.
|
|
*
|
|
***************************************************************************
|
|
*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed
|
|
* with this work for additional information regarding copyright
|
|
* ownership. The ASF licenses this file to you under the Apache
|
|
* License, Version 2.0 (the "License"); you may not use this file
|
|
* except in compliance with the License. You may obtain a copy of
|
|
* the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
* implied. See the License for the specific language governing
|
|
* permissions and limitations under the License.
|
|
*
|
|
* Copyright 1994-2006 Rogue Wave Software.
|
|
*
|
|
**************************************************************************/
|
|
|
|
|
|
_RWSTD_NAMESPACE (std) {
|
|
|
|
|
|
_EXPORT
|
|
template <class _FwdIter1, class _FwdIter2, class _Dist>
|
|
_FwdIter1 __find_end (_FwdIter1 __first1, _FwdIter1 __last1,
|
|
_FwdIter2 __first2, _FwdIter2 __last2,
|
|
_Dist*)
|
|
{
|
|
_RWSTD_ASSERT_RANGE (__first1, __last1);
|
|
_RWSTD_ASSERT_RANGE (__first2, __last2);
|
|
|
|
const _Dist __dist1 = _DISTANCE (__first2, __last2, _Dist);
|
|
|
|
if (!__dist1)
|
|
return __last1;
|
|
|
|
_Dist __dist2 = _DISTANCE (__first1, __last1, _Dist);
|
|
|
|
_FwdIter1 __res = __last1;
|
|
|
|
while (__dist2 >= __dist1) {
|
|
if (equal (__first2, __last2, __first1))
|
|
__res = __first1;
|
|
|
|
__dist2 = _DISTANCE (++__first1, __last1, _Dist);
|
|
}
|
|
return __res;
|
|
}
|
|
|
|
|
|
|
|
_EXPORT
|
|
template <class _FwdIter1, class _FwdIter2,
|
|
class _BinaryPredicate, class _Dist>
|
|
_FwdIter1 __find_end (_FwdIter1 __first1, _FwdIter1 __last1,
|
|
_FwdIter2 __first2, _FwdIter2 __last2,
|
|
_BinaryPredicate __pred, _Dist*)
|
|
{
|
|
_RWSTD_ASSERT_RANGE (__first1, __last1);
|
|
_RWSTD_ASSERT_RANGE (__first2, __last2);
|
|
|
|
const _Dist __dist1 = _DISTANCE (__first2, __last2, _Dist);
|
|
|
|
if (!__dist1)
|
|
return __last1;
|
|
|
|
_Dist __dist2 = _DISTANCE (__first1, __last1, _Dist);
|
|
|
|
_FwdIter1 __res = __last1;
|
|
|
|
while (__dist2 >= __dist1) {
|
|
if (_STD::equal (__first2, __last2, __first1, __pred))
|
|
__res = __first1;
|
|
|
|
__dist2 = _DISTANCE (++__first1, __last1, _Dist);
|
|
}
|
|
return __res;
|
|
}
|
|
|
|
|
|
_EXPORT
|
|
template <class _FwdIter1, class _FwdIter2>
|
|
_FwdIter1 find_first_of (_FwdIter1 __first1, _FwdIter1 __last1,
|
|
_FwdIter2 __first2, _FwdIter2 __last2)
|
|
{
|
|
_RWSTD_ASSERT_RANGE (__first1, __last1);
|
|
_RWSTD_ASSERT_RANGE (__first2, __last2);
|
|
|
|
if (__first2 == __last2)
|
|
return __last1;
|
|
|
|
for (_FwdIter1 __next = __first1; !(__next == __last1); ++__next)
|
|
if (!(_STD::find (__first2, __last2, *__next) == __last2))
|
|
return __next;
|
|
|
|
return __last1;
|
|
}
|
|
|
|
|
|
_EXPORT
|
|
template <class _FwdIter1, class _FwdIter2,
|
|
class _BinaryPredicate>
|
|
_FwdIter1 find_first_of (_FwdIter1 __first1, _FwdIter1 __last1,
|
|
_FwdIter2 __first2, _FwdIter2 __last2,
|
|
_BinaryPredicate __pred)
|
|
{
|
|
_RWSTD_ASSERT_RANGE (__first1, __last1);
|
|
_RWSTD_ASSERT_RANGE (__first2, __last2);
|
|
|
|
if (__first2 == __last2)
|
|
return __last1;
|
|
|
|
for (_FwdIter1 __next = __first1; !(__next == __last1); ++__next)
|
|
for (_FwdIter2 __iter = __first2; !(__iter == __last2); ++__iter)
|
|
if (!(__pred (*__next, *__iter) == false))
|
|
return __next;
|
|
|
|
return __last1;
|
|
}
|
|
|
|
|
|
_EXPORT
|
|
template <class _FwdIter>
|
|
_FwdIter adjacent_find (_FwdIter __first, _FwdIter __last)
|
|
{
|
|
_RWSTD_ASSERT_RANGE (__first, __last);
|
|
|
|
if (__first == __last)
|
|
return __last;
|
|
|
|
for (_FwdIter __next = __first; !(++__next == __last); __first = __next)
|
|
if (*__first == *__next)
|
|
return __first;
|
|
|
|
return __last;
|
|
}
|
|
|
|
|
|
_EXPORT
|
|
template <class _FwdIter, class _BinaryPredicate>
|
|
_FwdIter adjacent_find (_FwdIter __first, _FwdIter __last,
|
|
_BinaryPredicate __pred)
|
|
{
|
|
_RWSTD_ASSERT_RANGE (__first, __last);
|
|
|
|
if (__first == __last)
|
|
return __last;
|
|
|
|
for (_FwdIter __next = __first; !(++__next == __last); __first = __next)
|
|
if (!(__pred (*__first, *__next) == false))
|
|
return __first;
|
|
|
|
return __last;
|
|
}
|
|
|
|
|
|
_EXPORT
|
|
template <class _FwdIter1, class _FwdIter2, class _Dist1, class _Dist2>
|
|
_FwdIter1 __search (_FwdIter1 __first1, _FwdIter1 __last1,
|
|
_FwdIter2 __first2, _FwdIter2 __last2,
|
|
_Dist1*, _Dist2*)
|
|
{
|
|
_RWSTD_ASSERT_RANGE (__first1, __last1);
|
|
_RWSTD_ASSERT_RANGE (__first2, __last2);
|
|
|
|
_Dist1 __dist1 = _DISTANCE (__first1, __last1, _Dist1);
|
|
_Dist2 __dist2 = _DISTANCE (__first2, __last2, _Dist2);
|
|
|
|
if (__dist1 < __dist2)
|
|
return __last1;
|
|
|
|
_FwdIter1 __cur1 = __first1;
|
|
_FwdIter2 __cur2 = __first2;
|
|
|
|
while (!(__cur2 == __last2)) {
|
|
if (!(*__cur1 == *__cur2)) {
|
|
++__cur1;
|
|
++__cur2;
|
|
if (__dist1-- == __dist2)
|
|
return __last1;
|
|
|
|
__cur1 = ++__first1;
|
|
__cur2 = __first2;
|
|
}
|
|
else {
|
|
++__cur1;
|
|
++__cur2;
|
|
}
|
|
}
|
|
|
|
return (__cur2 == __last2) ? __first1 : __last1;
|
|
}
|
|
|
|
|
|
_EXPORT
|
|
template <class _FwdIter1, class _FwdIter2,
|
|
class _BinaryPredicate, class _Dist1, class _Dist2>
|
|
_FwdIter1 __search (_FwdIter1 __first1, _FwdIter1 __last1,
|
|
_FwdIter2 __first2, _FwdIter2 __last2,
|
|
_BinaryPredicate __pred, _Dist1*, _Dist2*)
|
|
{
|
|
_RWSTD_ASSERT_RANGE (__first1, __last1);
|
|
_RWSTD_ASSERT_RANGE (__first2, __last2);
|
|
|
|
_Dist1 __dist1 = _DISTANCE (__first1, __last1, _Dist1);
|
|
_Dist2 __dist2 = _DISTANCE (__first2, __last2, _Dist2);
|
|
|
|
if (__dist1 < __dist2) return __last1;
|
|
|
|
_FwdIter1 __cur1 = __first1;
|
|
_FwdIter2 __cur2 = __first2;
|
|
|
|
while (!(__cur2 == __last2)) {
|
|
if (__pred (*__cur1, *__cur2) == false) {
|
|
++__cur1;
|
|
++__cur2;
|
|
if (__dist1-- == __dist2)
|
|
return __last1;
|
|
|
|
__cur1 = ++__first1;
|
|
__cur2 = __first2;
|
|
}
|
|
else {
|
|
++__cur1;
|
|
++__cur2;
|
|
}
|
|
}
|
|
|
|
return (__cur2 == __last2) ? __first1 : __last1;
|
|
}
|
|
|
|
|
|
_EXPORT
|
|
template <class _FwdIter, class _Dist, class _Size, class _TypeT>
|
|
_FwdIter __search_n (_FwdIter __first, _FwdIter __last,
|
|
_Dist*, _Size __count, const _TypeT& __val)
|
|
{
|
|
_RWSTD_ASSERT_RANGE (__first, __last);
|
|
|
|
if (__count <= 0)
|
|
return __last;
|
|
|
|
const _Dist __dist = _DISTANCE (__first, __last, _Dist);
|
|
|
|
if (__dist < _Dist (__count))
|
|
return __last;
|
|
|
|
_Dist __span = __dist - _Dist (__count);
|
|
_Dist __matches = 0;
|
|
|
|
_FwdIter __current = __first;
|
|
|
|
while (!(__current == __last)) {
|
|
if (!(*__current == __val)) {
|
|
if (__span < __matches + 1)
|
|
return __last;
|
|
__span -= __matches + 1;
|
|
__matches = 0;
|
|
__first = ++__current;
|
|
}
|
|
else {
|
|
if (++__matches == _Dist (__count))
|
|
return __first;
|
|
++__current;
|
|
}
|
|
}
|
|
|
|
return __last;
|
|
}
|
|
|
|
|
|
_EXPORT
|
|
template <class _FwdIter, class _Dist, class _Size, class _TypeT,
|
|
class _BinaryPredicate>
|
|
_FwdIter __search_n (_FwdIter __first, _FwdIter __last,
|
|
_Dist*, _Size __count, const _TypeT& __val,
|
|
_BinaryPredicate __pred)
|
|
{
|
|
_RWSTD_ASSERT_RANGE (__first, __last);
|
|
|
|
const _Dist __dist = _DISTANCE (__first, __last, _Dist);
|
|
|
|
const _RWSTD_PTRDIFF_T __int_count = __count;
|
|
|
|
if (__dist < __int_count || __int_count <= 0)
|
|
return __last;
|
|
|
|
_Dist __span = __dist - __int_count;
|
|
_Dist __matches = 0;
|
|
_FwdIter __current = __first;
|
|
|
|
while (!(__current == __last)) {
|
|
if (__pred (*__current, __val) == false) {
|
|
if (__span < __matches + 1)
|
|
return __last;
|
|
__span -= __matches + 1;
|
|
__matches = 0;
|
|
__first = ++__current;
|
|
}
|
|
else {
|
|
if (++__matches == __count)
|
|
return __first;
|
|
++__current;
|
|
}
|
|
}
|
|
|
|
return __last;
|
|
}
|
|
|
|
//
|
|
// Modifying sequence operations.
|
|
//
|
|
|
|
_EXPORT
|
|
template <class _Iter, class _OutputIter, class _Predicate, class _TypeT>
|
|
_OutputIter replace_copy_if (_Iter __first, _Iter __last,
|
|
_OutputIter __res, _Predicate __pred,
|
|
const _TypeT& __new_value)
|
|
{
|
|
_RWSTD_ASSERT_RANGE (__first, __last);
|
|
|
|
for (; !(__first == __last); ++__res, ++__first)
|
|
*__res = __pred (*__first) == false ? *__first : __new_value;
|
|
|
|
return __res;
|
|
}
|
|
|
|
|
|
_EXPORT
|
|
template <class _InputIter, class _OutputIter, class _TypeT>
|
|
_OutputIter remove_copy (_InputIter __first, _InputIter __last,
|
|
_OutputIter __res, const _TypeT& __val)
|
|
{
|
|
_RWSTD_ASSERT_RANGE (__first, __last);
|
|
|
|
for (; !(__first == __last); ++__first)
|
|
if (!(*__first == __val)) {
|
|
*__res = *__first;
|
|
++__res;
|
|
}
|
|
return __res;
|
|
}
|
|
|
|
|
|
_EXPORT
|
|
template <class _InputIter, class _OutputIter, class _Predicate>
|
|
_OutputIter remove_copy_if (_InputIter __first, _InputIter __last,
|
|
_OutputIter __res, _Predicate __pred)
|
|
{
|
|
_RWSTD_ASSERT_RANGE (__first, __last);
|
|
|
|
for (; !(__first == __last); ++__first)
|
|
if (__pred (*__first) == false) {
|
|
*__res = *__first;
|
|
++__res;
|
|
}
|
|
return __res;
|
|
}
|
|
|
|
|
|
_EXPORT
|
|
template <class _FwdIter>
|
|
_FwdIter
|
|
unique (_FwdIter __first, _FwdIter __last)
|
|
{
|
|
// find the first of two equal elements
|
|
__first = _STD::adjacent_find (__first, __last);
|
|
|
|
if (__first == __last)
|
|
return __first;
|
|
|
|
// advance `first' to point at the copy (may be overwritten later)
|
|
_FwdIter __next = ++__first;
|
|
|
|
// skip over all subsequent elements that are equal to the first
|
|
while (!(++__next == __last))
|
|
if (!(*__next == *__first))
|
|
break;
|
|
|
|
// invoke unique_copy to copy over the original sequence
|
|
// starting at one past the first element
|
|
return __unique_copy (__next, __last, __first,
|
|
_RWSTD_ITERATOR_CATEGORY (_FwdIter, __first));
|
|
}
|
|
|
|
|
|
_EXPORT
|
|
template <class _FwdIter, class _BinaryPredicate>
|
|
_FwdIter
|
|
unique (_FwdIter __first, _FwdIter __last, _BinaryPredicate __pred)
|
|
{
|
|
__first = _STD::adjacent_find (__first, __last, __pred);
|
|
|
|
if (__first == __last)
|
|
return __first;
|
|
|
|
_FwdIter __next = ++__first;
|
|
|
|
while (!(++__next == __last))
|
|
if (__pred (*__next, *__first) == false)
|
|
break;
|
|
|
|
return __unique_copy (__next, __last, __first, __pred,
|
|
_RWSTD_ITERATOR_CATEGORY (_FwdIter, __first));
|
|
}
|
|
|
|
|
|
_EXPORT
|
|
template <class _InputIter, class _FwdIter>
|
|
_FwdIter __unique_copy (_InputIter __first, _InputIter __last,
|
|
_FwdIter __res, forward_iterator_tag)
|
|
{
|
|
_RWSTD_ASSERT_RANGE (__first, __last);
|
|
|
|
if (__first == __last)
|
|
return __res;
|
|
|
|
*__res = *__first;
|
|
while (!(++__first == __last))
|
|
if (!(*__res == *__first))
|
|
*++__res = *__first;
|
|
return ++__res;
|
|
}
|
|
|
|
|
|
_EXPORT
|
|
template <class _InputIter, class _OutputIter, class _TypeT>
|
|
_OutputIter __unique_copy (_InputIter __first, _InputIter __last,
|
|
_OutputIter __res, _TypeT*)
|
|
{
|
|
_RWSTD_ASSERT_RANGE (__first, __last);
|
|
|
|
if (__first == __last)
|
|
return __res;
|
|
|
|
_TypeT __val = *__first;
|
|
|
|
for (*__res = __val; !(++__first == __last); )
|
|
if (!(__val == *__first)) {
|
|
__val = *__first;
|
|
*++__res = __val;
|
|
}
|
|
|
|
return ++__res;
|
|
}
|
|
|
|
|
|
_EXPORT
|
|
template <class _InputIter, class _FwdIter, class _BinaryPredicate>
|
|
_FwdIter __unique_copy (_InputIter __first, _InputIter __last,
|
|
_FwdIter __res,
|
|
_BinaryPredicate __pred,
|
|
forward_iterator_tag)
|
|
{
|
|
_RWSTD_ASSERT_RANGE (__first, __last);
|
|
|
|
if (__first == __last)
|
|
return __res;
|
|
|
|
for (*__res = *__first; !(++__first == __last); )
|
|
if (__pred (*__res, *__first) == false)
|
|
*++__res = *__first;
|
|
|
|
return ++__res;
|
|
}
|
|
|
|
|
|
_EXPORT
|
|
template <class _InputIter, class _OutputIter, class _BinaryPredicate,
|
|
class _TypeT>
|
|
_OutputIter __unique_copy (_InputIter __first, _InputIter __last,
|
|
_OutputIter __res,
|
|
_BinaryPredicate __pred, _TypeT*)
|
|
{
|
|
_RWSTD_ASSERT_RANGE (__first, __last);
|
|
|
|
if (__first == __last)
|
|
return __res;
|
|
|
|
_TypeT __val = *__first;
|
|
|
|
for (*__res = __val; !(++__first == __last); )
|
|
if (__pred (__val, *__first) == false) {
|
|
__val = *__first;
|
|
*++__res = __val;
|
|
}
|
|
|
|
return ++__res;
|
|
}
|
|
|
|
|
|
_EXPORT
|
|
template <class _FwdIter, class _Dist>
|
|
void __rotate (_FwdIter __first, _FwdIter __middle,
|
|
_FwdIter __last, _Dist*, forward_iterator_tag)
|
|
{
|
|
_RWSTD_ASSERT_IN_RANGE (__middle, __first, __last);
|
|
|
|
for (_FwdIter __i = __middle; ; ) {
|
|
_STD::iter_swap (__first, __i);
|
|
++__i;
|
|
if (++__first == __middle) {
|
|
if (__i == __last)
|
|
return;
|
|
__middle = __i;
|
|
}
|
|
else if (__i == __last)
|
|
__i = __middle;
|
|
}
|
|
}
|
|
|
|
|
|
_EXPORT
|
|
template <class _EuclideanRingElement>
|
|
_EuclideanRingElement __gcd (_EuclideanRingElement __m,
|
|
_EuclideanRingElement __n)
|
|
{
|
|
while (!(__n == _EuclideanRingElement ())) {
|
|
const _EuclideanRingElement __r = __m % __n;
|
|
__m = __n;
|
|
__n = __r;
|
|
}
|
|
return __m;
|
|
}
|
|
|
|
|
|
_EXPORT
|
|
template <class _RandomAccessIter, class _Dist, class _TypeT>
|
|
void __rotate_cycle (_RandomAccessIter __first, _RandomAccessIter __last,
|
|
_RandomAccessIter __first2, _Dist __shift, _TypeT*)
|
|
{
|
|
_RWSTD_ASSERT_RANGE (__first, __last);
|
|
|
|
const _TypeT __val = *__first2;
|
|
|
|
_RandomAccessIter __it1 = __first2;
|
|
|
|
for (_RandomAccessIter __it2 = __it1 + __shift; !(__it2 == __first2); ) {
|
|
*__it1 = *__it2;
|
|
__it1 = __it2;
|
|
|
|
if (__last - __it2 > __shift)
|
|
__it2 += __shift;
|
|
else
|
|
__it2 = __first + (__shift - (__last - __it2));
|
|
}
|
|
|
|
*__it1 = __val;
|
|
}
|
|
|
|
|
|
_EXPORT
|
|
template <class _RandomAccessIter, class _Dist>
|
|
void __rotate (_RandomAccessIter __first, _RandomAccessIter __middle,
|
|
_RandomAccessIter __last, _Dist*,
|
|
random_access_iterator_tag)
|
|
{
|
|
_RWSTD_ASSERT_IN_RANGE (__middle, __first, __last);
|
|
|
|
for (_Dist __n = __gcd (__last - __first, __middle - __first); __n--; )
|
|
__rotate_cycle (__first, __last, __first + __n, __middle - __first,
|
|
_RWSTD_VALUE_TYPE (_RandomAccessIter));
|
|
}
|
|
|
|
|
|
_EXPORT
|
|
template <class _RandomAccessIter, class _RandomNumberGenerator>
|
|
void random_shuffle (_RandomAccessIter __first, _RandomAccessIter __last,
|
|
_RandomNumberGenerator &__rand)
|
|
{
|
|
_RWSTD_ASSERT_RANGE (__first, __last);
|
|
|
|
if (!(__first == __last)) {
|
|
|
|
#ifndef _RWSTD_NO_CLASS_PARTIAL_SPEC
|
|
typedef _TYPENAME
|
|
iterator_traits<_RandomAccessIter>::difference_type _DiffT;
|
|
#else // if defined (_RWSTD_NO_CLASS_PARTIAL_SPEC)
|
|
typedef _RWSTD_PTRDIFF_T _DiffT;
|
|
#endif // _RWSTD_NO_CLASS_PARTIAL_SPEC
|
|
|
|
_DiffT __limit = 2;
|
|
|
|
for (_RandomAccessIter __i = __first; !(++__i == __last); ++__limit) {
|
|
|
|
// the argument to and the return value of the random number
|
|
// generator's operator() is required to be convertinble from
|
|
// and to the iterator's difference_type but nothing else
|
|
const _DiffT __rndoff (__rand (__limit));
|
|
|
|
// returned value must be non-negative and less than the limit
|
|
_RWSTD_ASSERT (0 <= __rndoff && __rndoff < __limit);
|
|
|
|
_STD::iter_swap (__i, __first + __rndoff);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
_EXPORT
|
|
template <class _BidirIter, class _Predicate>
|
|
_BidirIter partition (_BidirIter __first, _BidirIter __last, _Predicate __pred)
|
|
{
|
|
_RWSTD_ASSERT_RANGE (__first, __last);
|
|
|
|
for ( ; ; ++__first) {
|
|
for ( ; ; ) {
|
|
if (__first == __last)
|
|
return __first;
|
|
if (!(__pred (*__first) == false))
|
|
++__first;
|
|
else
|
|
break;
|
|
}
|
|
|
|
for (--__last; ; ) {
|
|
if (__first == __last)
|
|
return __first;
|
|
if (__pred (*__last) == false)
|
|
--__last;
|
|
else
|
|
break;
|
|
}
|
|
_STD::iter_swap (__first, __last);
|
|
}
|
|
}
|
|
|
|
|
|
template <class _BidirIter, class _Predicate, class _Dist>
|
|
_BidirIter __inplace_stable_partition (_BidirIter __first, _BidirIter __last,
|
|
_Predicate __pred, _Dist __dist)
|
|
{
|
|
_RWSTD_ASSERT_RANGE (__first, __last);
|
|
|
|
if (__dist == 1)
|
|
return !(__pred (*__first) == false) ? __last : __first;
|
|
|
|
_BidirIter __middle = __first;
|
|
_STD::advance (__middle, __dist / 2);
|
|
_BidirIter
|
|
__first_cut = __inplace_stable_partition (__first, __middle, __pred,
|
|
__dist / 2);
|
|
_BidirIter
|
|
__second_cut = __inplace_stable_partition (__middle, __last, __pred,
|
|
__dist - __dist / 2);
|
|
_STD::rotate (__first_cut, __middle, __second_cut);
|
|
__dist = _DISTANCE (__middle, __second_cut, _Dist);
|
|
_STD::advance (__first_cut, __dist);
|
|
return __first_cut;
|
|
}
|
|
|
|
|
|
_EXPORT
|
|
template <class _BidirIter, class _Pointer, class _Predicate,
|
|
class _Dist, class _TypeT>
|
|
_BidirIter __stable_partition_adaptive (_BidirIter __first, _BidirIter __last,
|
|
_Predicate __pred, _Dist __dist,
|
|
_Pointer __buf,
|
|
_Dist __buf_size,
|
|
_Dist& __fill_pointer, _TypeT*)
|
|
{
|
|
_RWSTD_ASSERT_RANGE (__first, __last);
|
|
|
|
if (__dist <= __buf_size)
|
|
{
|
|
__dist = 0;
|
|
_BidirIter __res1 = __first;
|
|
_Pointer __res2 = __buf;
|
|
for (; !(__first == __last) && __dist < __fill_pointer; ++__first)
|
|
{
|
|
if (!(__pred (*__first) == false)) {
|
|
*__res1 = *__first;
|
|
++__res1;
|
|
}
|
|
else {
|
|
*__res2 = *__first;
|
|
++__res2;
|
|
++__dist;
|
|
}
|
|
}
|
|
if (!(__first == __last))
|
|
{
|
|
raw_storage_iterator<_Pointer, _TypeT> __res3 (__res2);
|
|
for (; !(__first == __last); ++__first)
|
|
{
|
|
if (!(__pred (*__first) == false)) {
|
|
*__res1 = *__first;
|
|
++__res1;
|
|
}
|
|
else {
|
|
*__res3 = *__first;
|
|
++__res3;
|
|
++__dist;
|
|
}
|
|
}
|
|
__fill_pointer = __dist;
|
|
}
|
|
_STD::copy (__buf, __buf + __dist, __res1);
|
|
return __res1;
|
|
}
|
|
_BidirIter __middle = __first;
|
|
_STD::advance (__middle, __dist / 2);
|
|
|
|
// (__dist / 2)'s type may not be the same as that of __dist,
|
|
// hence the seemingly redundant casts below
|
|
_BidirIter __first_cut =
|
|
__stable_partition_adaptive (__first, __middle, __pred,
|
|
_Dist (__dist / 2),
|
|
__buf, __buf_size,
|
|
__fill_pointer, (_TypeT*)0);
|
|
_BidirIter __second_cut =
|
|
__stable_partition_adaptive (__middle, __last, __pred,
|
|
_Dist (__dist - __dist / 2),
|
|
__buf, __buf_size,
|
|
__fill_pointer, (_TypeT*)0);
|
|
|
|
_STD::rotate (__first_cut, __middle, __second_cut);
|
|
__dist = _DISTANCE (__middle, __second_cut, _Dist);
|
|
_STD::advance (__first_cut, __dist);
|
|
return __first_cut;
|
|
}
|
|
|
|
|
|
_EXPORT
|
|
template <class _BidirIter, class _Predicate, class _TypeT, class _Dist>
|
|
_BidirIter __stable_partition (_BidirIter __first, _BidirIter __last,
|
|
_Predicate __pred, _TypeT*, _Dist*)
|
|
{
|
|
_RWSTD_ASSERT_RANGE (__first, __last);
|
|
|
|
const _Dist __dist = _DISTANCE (__first, __last, _Dist);
|
|
|
|
if (!__dist)
|
|
return __last;
|
|
|
|
// call an extension of get_temporary_buffer<>() in case partial class
|
|
// specialization (and iterator_traits<>) isn't supported by compiler
|
|
pair<_TypeT*, _Dist> __pair =
|
|
_STD::get_temporary_buffer (__dist, (_TypeT*)0);
|
|
|
|
if (__pair.first == 0)
|
|
return __inplace_stable_partition (__first, __last, __pred, __dist);
|
|
|
|
_Dist __fill = 0;
|
|
|
|
const _BidirIter __res =
|
|
__stable_partition_adaptive (__first, __last, __pred, __dist,
|
|
__pair.first, __pair.second,
|
|
__fill, (_TypeT*)0);
|
|
|
|
for (_TypeT *__ptr = __pair.first + __fill; !(__pair.first == __ptr--); )
|
|
(*__ptr).~_TypeT ();
|
|
|
|
_STD::return_temporary_buffer (__pair.first);
|
|
|
|
return __res;
|
|
}
|
|
|
|
//
|
|
// Sorting and related operations.
|
|
//
|
|
|
|
template <class _RandomAccessIter, class _TypeT, class _Compare>
|
|
_RandomAccessIter __unguarded_partition (_RandomAccessIter __first,
|
|
_RandomAccessIter __last,
|
|
_TypeT __pivot, _Compare __comp)
|
|
{
|
|
_RWSTD_ASSERT_RANGE (__first, __last);
|
|
|
|
for ( ; ; ++__first) {
|
|
for (; __comp (*__first, __pivot); ++__first);
|
|
|
|
while (__comp (__pivot, *--__last));
|
|
|
|
if (!(__first < __last))
|
|
return __first;
|
|
|
|
_STD::iter_swap (__first, __last);
|
|
}
|
|
}
|
|
|
|
|
|
template <class _TypeT, class _Compare>
|
|
inline const _TypeT& __median (const _TypeT& __a, const _TypeT& __b,
|
|
const _TypeT& __c, _Compare __comp)
|
|
{
|
|
return __comp (__a, __b)
|
|
? __comp (__b, __c) ? __b : __comp (__a, __c) ? __c : __a
|
|
: __comp (__a, __c) ? __a : __comp (__b, __c) ? __c : __b;
|
|
}
|
|
|
|
|
|
enum { __rw_threshold = 16 };
|
|
|
|
template <class _RandomAccessIter, class _TypeT, class _Compare>
|
|
void __quick_sort_loop_aux (_RandomAccessIter __first,
|
|
_RandomAccessIter __last, _TypeT*,
|
|
_Compare __comp)
|
|
{
|
|
_RWSTD_ASSERT_RANGE (__first, __last);
|
|
|
|
while (__last - __first > __rw_threshold) {
|
|
_RandomAccessIter __cut =
|
|
__unguarded_partition (__first, __last,
|
|
_TypeT (__median (*__first,
|
|
* (__first +
|
|
(__last - __first)/2),
|
|
* (__last - 1),
|
|
__comp)),
|
|
__comp);
|
|
if (__cut - __first >= __last - __cut) {
|
|
__quick_sort_loop_aux (__cut, __last,
|
|
_RWSTD_VALUE_TYPE (_RandomAccessIter),
|
|
__comp);
|
|
__last = __cut;
|
|
}
|
|
else {
|
|
__quick_sort_loop_aux (__first, __cut,
|
|
_RWSTD_VALUE_TYPE (_RandomAccessIter),
|
|
__comp);
|
|
__first = __cut;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
template <class _RandomAccessIter, class _TypeT>
|
|
inline void __linear_insert (_RandomAccessIter __first,
|
|
_RandomAccessIter __last, _TypeT*)
|
|
{
|
|
const _TypeT __val = *__last;
|
|
|
|
if (__val < *__first) {
|
|
_STD::copy_backward (__first, __last, __last + 1);
|
|
*__first = __val;
|
|
}
|
|
else
|
|
__unguarded_linear_insert (__last, __val);
|
|
}
|
|
|
|
|
|
template <class _RandomAccessIter, class _TypeT, class _Compare>
|
|
inline void
|
|
__linear_insert (_RandomAccessIter __first, _RandomAccessIter __last, _TypeT*,
|
|
_Compare __comp)
|
|
{
|
|
const _TypeT __val = *__last;
|
|
|
|
if (__comp (__val, *__first)) {
|
|
_STD::copy_backward (__first, __last, __last + 1);
|
|
*__first = __val;
|
|
}
|
|
else
|
|
__unguarded_linear_insert (__last, __val, __comp);
|
|
}
|
|
|
|
|
|
_EXPORT
|
|
template <class _RandomAccessIter, class _Compare>
|
|
void __insertion_sort (_RandomAccessIter __first,
|
|
_RandomAccessIter __last, _Compare __comp)
|
|
{
|
|
_RWSTD_ASSERT_RANGE (__first, __last);
|
|
|
|
if (! (__first == __last))
|
|
for (_RandomAccessIter __i = __first + 1; !(__i == __last); ++__i)
|
|
__linear_insert (__first, __i,
|
|
_RWSTD_VALUE_TYPE (_RandomAccessIter), __comp);
|
|
}
|
|
|
|
_EXPORT
|
|
template <class _RandomAccessIter, class _TypeT, class _Compare>
|
|
void __unguarded_linear_insert (_RandomAccessIter __last, _TypeT __val,
|
|
_Compare __comp)
|
|
{
|
|
for (_RandomAccessIter __next = __last; __comp (__val, *--__next); ) {
|
|
*__last = *__next;
|
|
__last = __next;
|
|
}
|
|
*__last = __val;
|
|
}
|
|
|
|
|
|
_EXPORT
|
|
template <class _RandomAccessIter, class _Compare>
|
|
void __final_insertion_sort (_RandomAccessIter __first,
|
|
_RandomAccessIter __last, _Compare __comp)
|
|
{
|
|
_RWSTD_ASSERT_RANGE (__first, __last);
|
|
|
|
if (__last - __first > __rw_threshold) {
|
|
__insertion_sort (__first, __first + __rw_threshold, __comp);
|
|
__unguarded_insertion_sort (__first + __rw_threshold, __last, __comp);
|
|
}
|
|
else
|
|
__insertion_sort (__first, __last, __comp);
|
|
}
|
|
|
|
|
|
template <class _RandomAccessIter1, class _RandomAccessIter2,
|
|
class _Dist, class _Compare>
|
|
void __merge_sort_loop (_RandomAccessIter1 __first,
|
|
_RandomAccessIter1 __last,
|
|
_RandomAccessIter2 __res, _Dist __step,
|
|
_Compare __comp)
|
|
{
|
|
_RWSTD_ASSERT_RANGE (__first, __last);
|
|
|
|
const _Dist __two_step = 2 * __step;
|
|
|
|
while (__last - __first >= __two_step) {
|
|
__res = _STD::merge (__first, __first + __step,
|
|
__first + __step, __first + __two_step, __res,
|
|
__comp);
|
|
__first += __two_step;
|
|
}
|
|
__step = (_STD::min)(_Dist (__last - __first), __step);
|
|
|
|
_STD::merge (__first, __first + __step, __first + __step, __last,
|
|
__res, __comp);
|
|
}
|
|
|
|
|
|
template <class _RandomAccessIter, class _Dist, class _Compare>
|
|
void __chunk_insertion_sort (_RandomAccessIter __first,
|
|
_RandomAccessIter __last,
|
|
_Dist __chunk_size, _Compare __comp)
|
|
{
|
|
_RWSTD_ASSERT_RANGE (__first, __last);
|
|
|
|
while (__last - __first >= __chunk_size)
|
|
{
|
|
__insertion_sort (__first, __first + __chunk_size, __comp);
|
|
__first += __chunk_size;
|
|
}
|
|
__insertion_sort (__first, __last, __comp);
|
|
}
|
|
|
|
|
|
_EXPORT
|
|
template <class _RandomAccessIter, class _Pointer, class _Dist,
|
|
class _Compare>
|
|
void __merge_sort_with_buffer (_RandomAccessIter __first,
|
|
_RandomAccessIter __last, _Pointer __buf,
|
|
_Dist*, _Compare __comp)
|
|
{
|
|
_RWSTD_ASSERT_RANGE (__first, __last);
|
|
|
|
const _Dist __dist = __last - __first;
|
|
const _Pointer __bufend = __buf + __dist;
|
|
|
|
_Dist __step = 7; // STL chunk size
|
|
|
|
__chunk_insertion_sort (__first, __last, __step, __comp);
|
|
|
|
while (__step < __dist) {
|
|
__merge_sort_loop (__first, __last, __buf, __step, __comp);
|
|
__step *= 2;
|
|
__merge_sort_loop (__buf, __bufend, __first, __step, __comp);
|
|
__step *= 2;
|
|
}
|
|
}
|
|
|
|
|
|
template <class _BidirIter, class _Dist, class _Pointer, class _Compare>
|
|
void __merge_adaptive (_BidirIter, _BidirIter, _BidirIter,
|
|
_Dist, _Dist, _Pointer, _Dist, _Compare);
|
|
|
|
_EXPORT
|
|
template <class _RandomAccessIter, class _Pointer, class _Dist,
|
|
class _TypeT, class _Compare>
|
|
void __stable_sort_adaptive (_RandomAccessIter __first,
|
|
_RandomAccessIter __last, _Pointer __buf,
|
|
_Dist __buf_size, _TypeT*,
|
|
_Compare __comp)
|
|
{
|
|
_RWSTD_ASSERT_RANGE (__first, __last);
|
|
|
|
const _Dist __dist = (__last - __first + 1) / 2;
|
|
const _RandomAccessIter __middle = __first + __dist;
|
|
|
|
if (__dist > __buf_size) {
|
|
__stable_sort_adaptive (__first, __middle, __buf, __buf_size,
|
|
(_TypeT*)0, __comp);
|
|
__stable_sort_adaptive (__middle, __last, __buf, __buf_size,
|
|
(_TypeT*)0, __comp);
|
|
}
|
|
else {
|
|
__merge_sort_with_buffer (__first, __middle, __buf,
|
|
(_Dist*)0, __comp);
|
|
__merge_sort_with_buffer (__middle, __last, __buf,
|
|
(_Dist*)0, __comp);
|
|
}
|
|
__merge_adaptive (__first, __middle, __last,
|
|
_Dist (__middle - __first),
|
|
_Dist (__last - __middle), __buf, __buf_size, __comp);
|
|
}
|
|
|
|
|
|
_EXPORT
|
|
template <class _RandomAccessIter, class _TypeT, class _Dist, class _Compare>
|
|
void
|
|
__stable_sort (_RandomAccessIter __first, _RandomAccessIter __last,
|
|
_TypeT*, _Dist*, _Compare __comp)
|
|
{
|
|
// call an extension of get_temporary_buffer<>() in case partial class
|
|
// specialization (and iterator_traits<>) isn't supported by compiler
|
|
pair<_TypeT*, _Dist> __p =
|
|
_STD::get_temporary_buffer (_Dist (__last - __first), (_TypeT*)0);
|
|
|
|
if (__p.first == 0)
|
|
__inplace_stable_sort (__first, __last, __comp);
|
|
else {
|
|
_Dist __len = (_STD::min)(_Dist (__p.second),
|
|
_Dist (__last - __first));
|
|
_STD::copy (__first, __first + __len,
|
|
raw_storage_iterator<_TypeT*, _TypeT>(__p.first));
|
|
|
|
__stable_sort_adaptive (__first, __last, __p.first, __p.second,
|
|
(_TypeT*)0, __comp);
|
|
|
|
for (_TypeT *__ptr = __p.first + __len; !(__p.first == --__ptr); )
|
|
(*__ptr).~_TypeT ();
|
|
|
|
_STD::return_temporary_buffer (__p.first);
|
|
}
|
|
}
|
|
|
|
|
|
_EXPORT
|
|
template <class _RandomAccessIter, class _TypeT, class _Compare>
|
|
void __partial_sort (_RandomAccessIter __first, _RandomAccessIter __middle,
|
|
_RandomAccessIter __last, _TypeT*, _Compare __comp)
|
|
{
|
|
_RWSTD_ASSERT_IN_RANGE (__middle, __first, __last);
|
|
|
|
_STD::make_heap (__first, __middle, __comp);
|
|
|
|
for (_RandomAccessIter __i = __middle; __i < __last; ++__i)
|
|
if (__comp (*__i, *__first))
|
|
__pop_heap (__first, __middle, __i, *__i, __comp,
|
|
_RWSTD_DIFFERENCE_TYPE (_RandomAccessIter));
|
|
|
|
_STD::sort_heap (__first, __middle, __comp);
|
|
}
|
|
|
|
|
|
_EXPORT
|
|
template <class _InputIter, class _RandomAccessIter, class _Compare,
|
|
class _Dist, class _TypeT>
|
|
_RandomAccessIter __partial_sort_copy (_InputIter __first,
|
|
_InputIter __last,
|
|
_RandomAccessIter __first2,
|
|
_RandomAccessIter __last2,
|
|
_Compare __comp,
|
|
_Dist*, _TypeT*)
|
|
{
|
|
_RWSTD_ASSERT_RANGE (__first, __last);
|
|
_RWSTD_ASSERT_RANGE (__first2, __last2);
|
|
|
|
if (__first2 == __last2)
|
|
return __last2;
|
|
|
|
_RandomAccessIter __res = __first2;
|
|
|
|
for (; !(__first == __last) && !(__res == __last2); ++__first, ++__res)
|
|
*__res = *__first;
|
|
|
|
_STD::make_heap (__first2, __res, __comp);
|
|
|
|
for (; !(__first == __last); ++__first) {
|
|
if (__comp (*__first, *__first2))
|
|
__adjust_heap (__first2, _Dist (), _Dist (__res - __first2),
|
|
*__first, __comp);
|
|
}
|
|
|
|
_STD::sort_heap (__first2, __res, __comp);
|
|
|
|
return __res;
|
|
}
|
|
|
|
|
|
// David R. Musser's Introspective Sorting algorithm
|
|
// (see www.cs.rpi.edu/~musser/gp/introsort.ps)
|
|
// O(N * log (N)) worst case complexity
|
|
_EXPORT
|
|
template <class _RandomAccessIter, class _Dist, class _Compare>
|
|
void __introsort_loop (_RandomAccessIter __first, _RandomAccessIter __last,
|
|
_Dist __max_depth, _Compare __comp)
|
|
{
|
|
for ( ; __rw_threshold < __last - __first; ) {
|
|
if (0 == __max_depth) {
|
|
__partial_sort (__first, __last, __last,
|
|
_RWSTD_VALUE_TYPE (_RandomAccessIter), __comp);
|
|
break;
|
|
}
|
|
|
|
_RandomAccessIter __cut =
|
|
__unguarded_partition (__first, __last,
|
|
__median (*__first,
|
|
*(__first + (__last - __first) /2),
|
|
*(__last - 1), __comp), __comp);
|
|
|
|
// limit the depth of the recursion tree to log2 (last - first)
|
|
// where first and last are the initial values passed in from sort()
|
|
__introsort_loop (__cut, __last, __max_depth /= 2, __comp);
|
|
__last = __cut;
|
|
}
|
|
}
|
|
|
|
|
|
_EXPORT
|
|
template <class _RandomAccessIter, class _TypeT, class _Compare>
|
|
void __nth_element (_RandomAccessIter __first, _RandomAccessIter __nth,
|
|
_RandomAccessIter __last, _TypeT*, _Compare __comp)
|
|
{
|
|
_RWSTD_ASSERT_IN_RANGE (__nth, __first, __last);
|
|
|
|
while (__last - __first > 3) {
|
|
const _RandomAccessIter __cut =
|
|
__unguarded_partition (__first, __last,
|
|
_TypeT (__median (*__first,
|
|
* (__first +
|
|
(__last - __first)/2),
|
|
* (__last - 1),
|
|
__comp)),
|
|
__comp);
|
|
if (!(__nth < __cut))
|
|
__first = __cut;
|
|
else
|
|
__last = __cut;
|
|
}
|
|
__insertion_sort (__first, __last, __comp);
|
|
}
|
|
|
|
//
|
|
// Binary search.
|
|
//
|
|
|
|
_EXPORT
|
|
template <class _FwdIter, class _TypeT, class _Compare, class _Dist>
|
|
_FwdIter __lower_bound (_FwdIter __first, _FwdIter __last,
|
|
const _TypeT& __val, _Compare __comp,
|
|
_Dist*, forward_iterator_tag)
|
|
{
|
|
_RWSTD_ASSERT_RANGE (__first, __last);
|
|
|
|
for (_Dist __dist = _DISTANCE (__first, __last, _Dist); __dist; ) {
|
|
|
|
const _Dist __half = __dist / 2;
|
|
_FwdIter __middle = __first;
|
|
|
|
_STD::advance (__middle, __half);
|
|
|
|
if (__comp (*__middle, __val)) {
|
|
__first = __middle;
|
|
++__first;
|
|
__dist = __dist - __half - 1;
|
|
}
|
|
else
|
|
__dist = __half;
|
|
}
|
|
return __first;
|
|
}
|
|
|
|
|
|
_EXPORT
|
|
template <class _RandomAccessIter, class _TypeT, class _Compare,
|
|
class _Dist>
|
|
_RandomAccessIter __lower_bound (_RandomAccessIter __first,
|
|
_RandomAccessIter __last,
|
|
const _TypeT& __val,
|
|
_Compare __comp,
|
|
_Dist*,
|
|
random_access_iterator_tag)
|
|
{
|
|
_RWSTD_ASSERT_RANGE (__first, __last);
|
|
|
|
for (_Dist __dist = __last - __first; __dist > 0; ) {
|
|
|
|
const _Dist __half = __dist / 2;
|
|
const _RandomAccessIter __middle = __first + __half;
|
|
|
|
if (__comp (*__middle, __val)) {
|
|
__first = __middle + 1;
|
|
__dist = __dist - __half - 1;
|
|
}
|
|
else
|
|
__dist = __half;
|
|
}
|
|
|
|
return __first;
|
|
}
|
|
|
|
|
|
_EXPORT
|
|
template <class _FwdIter, class _TypeT, class _Compare, class _Dist>
|
|
_FwdIter __upper_bound (_FwdIter __first, _FwdIter __last,
|
|
const _TypeT& __val, _Compare __comp,
|
|
_Dist*, forward_iterator_tag)
|
|
{
|
|
_RWSTD_ASSERT_RANGE (__first, __last);
|
|
|
|
for (_Dist __dist = _DISTANCE (__first, __last, _Dist); __dist; ) {
|
|
|
|
const _Dist __half = __dist / 2;
|
|
_FwdIter __middle = __first;
|
|
|
|
_STD::advance (__middle, __half);
|
|
|
|
if (__comp (__val, *__middle))
|
|
__dist = __half;
|
|
else {
|
|
__first = __middle;
|
|
++__first;
|
|
__dist = __dist - __half - 1;
|
|
}
|
|
}
|
|
|
|
return __first;
|
|
}
|
|
|
|
|
|
_EXPORT
|
|
template <class _RandomAccessIter, class _TypeT, class _Compare, class _Dist>
|
|
_RandomAccessIter __upper_bound (_RandomAccessIter __first,
|
|
_RandomAccessIter __last,
|
|
const _TypeT& __val,
|
|
_Compare __comp, _Dist*,
|
|
random_access_iterator_tag)
|
|
{
|
|
_RWSTD_ASSERT_RANGE (__first, __last);
|
|
|
|
for (_Dist __dist = __last - __first; __dist; ) {
|
|
|
|
const _Dist __half = __dist / 2;
|
|
const _RandomAccessIter __middle = __first + __half;
|
|
|
|
if (__comp (__val, *__middle))
|
|
__dist = __half;
|
|
else {
|
|
__first = __middle + 1;
|
|
__dist = __dist - __half - 1;
|
|
}
|
|
}
|
|
|
|
return __first;
|
|
}
|
|
|
|
|
|
_EXPORT
|
|
template <class _FwdIter, class _TypeT, class _Compare, class _Dist>
|
|
pair<_FwdIter, _FwdIter>
|
|
__equal_range (_FwdIter __first, _FwdIter __last, const _TypeT& __val,
|
|
_Compare __comp, _Dist*, forward_iterator_tag)
|
|
{
|
|
_RWSTD_ASSERT_RANGE (__first, __last);
|
|
|
|
for (_Dist __dist = _DISTANCE (__first, __last, _Dist); __dist; ) {
|
|
|
|
const _Dist __half = __dist / 2;
|
|
_FwdIter __middle = __first;
|
|
|
|
_STD::advance (__middle, __half);
|
|
|
|
if (__comp (*__middle, __val)) {
|
|
__first = __middle;
|
|
++__first;
|
|
__dist = __dist - __half - 1;
|
|
}
|
|
else if (__comp (__val, *__middle))
|
|
__dist = __half;
|
|
else {
|
|
const _FwdIter __left =
|
|
_STD::lower_bound (__first, __middle, __val, __comp);
|
|
|
|
_STD::advance (__first, __dist);
|
|
|
|
const _FwdIter __right =
|
|
_STD::upper_bound (++__middle, __first, __val, __comp);
|
|
|
|
return pair<_FwdIter, _FwdIter>(__left, __right);
|
|
}
|
|
}
|
|
|
|
return pair<_FwdIter, _FwdIter>(__first, __first);
|
|
}
|
|
|
|
|
|
_EXPORT
|
|
template <class _RandomAccessIter, class _TypeT, class _Compare,
|
|
class _Dist>
|
|
pair<_RandomAccessIter, _RandomAccessIter>
|
|
__equal_range (_RandomAccessIter __first, _RandomAccessIter __last,
|
|
const _TypeT& __val, _Compare __comp, _Dist*,
|
|
random_access_iterator_tag)
|
|
{
|
|
_RWSTD_ASSERT_RANGE (__first, __last);
|
|
|
|
for (_Dist __dist = __last - __first; __dist; ) {
|
|
|
|
const _Dist __half = __dist / 2;
|
|
const _RandomAccessIter __middle = __first + __half;
|
|
|
|
if (__comp (*__middle, __val)) {
|
|
__first = __middle + 1;
|
|
__dist = __dist - __half - 1;
|
|
}
|
|
else if (__comp (__val, *__middle))
|
|
__dist = __half;
|
|
else {
|
|
const _RandomAccessIter __left =
|
|
_STD::lower_bound (__first, __middle, __val, __comp);
|
|
|
|
const _RandomAccessIter __right =
|
|
_STD::upper_bound (__middle + 1, __first + __dist,
|
|
__val, __comp);
|
|
|
|
return pair<_RandomAccessIter, _RandomAccessIter>(__left, __right);
|
|
}
|
|
}
|
|
|
|
return pair<_RandomAccessIter, _RandomAccessIter>(__first, __first);
|
|
}
|
|
|
|
//
|
|
// Merge
|
|
//
|
|
|
|
_EXPORT
|
|
template <class _InputIter1, class _InputIter2, class _OutputIter,
|
|
class _Compare>
|
|
_OutputIter merge (_InputIter1 __first1, _InputIter1 __last1,
|
|
_InputIter2 __first2, _InputIter2 __last2,
|
|
_OutputIter __res, _Compare __comp)
|
|
{
|
|
_RWSTD_ASSERT_RANGE (__first1, __last1);
|
|
_RWSTD_ASSERT_RANGE (__first2, __last2);
|
|
|
|
for (; !(__first1 == __last1) && !(__first2 == __last2); ++__res) {
|
|
if (__comp (*__first2, *__first1)) {
|
|
*__res = *__first2;
|
|
++__first2;
|
|
}
|
|
else {
|
|
*__res = *__first1;
|
|
++__first1;
|
|
}
|
|
}
|
|
return _STD::copy (__first2, __last2, _STD::copy(__first1, __last1, __res));
|
|
}
|
|
|
|
|
|
_EXPORT
|
|
template <class _BidirIter, class _Dist, class _Compare>
|
|
void __merge_without_buffer (_BidirIter __first,
|
|
_BidirIter __middle,
|
|
_BidirIter __last,
|
|
_Dist __dist1, _Dist __dist2,
|
|
_Compare __comp)
|
|
{
|
|
_RWSTD_ASSERT_IN_RANGE (__middle, __first, __last);
|
|
|
|
if (__dist1 == 0 || __dist2 == 0)
|
|
return;
|
|
|
|
if (__dist1 + __dist2 == 2) {
|
|
if (__comp (*__middle, *__first))
|
|
_STD::iter_swap (__first, __middle);
|
|
return;
|
|
}
|
|
|
|
_BidirIter __first_cut = __first;
|
|
_BidirIter __second_cut = __middle;
|
|
_Dist __dist11;
|
|
_Dist __dist22;
|
|
|
|
if (__dist1 > __dist2) {
|
|
__dist11 = __dist1 / 2;
|
|
_STD::advance (__first_cut, __dist11);
|
|
__second_cut = _STD::lower_bound (__middle, __last,
|
|
*__first_cut, __comp);
|
|
__dist22 = _DISTANCE (__middle, __second_cut, _Dist);
|
|
}
|
|
else {
|
|
__dist22 = __dist2 / 2;
|
|
_STD::advance (__second_cut, __dist22);
|
|
__first_cut = _STD::upper_bound (__first, __middle,
|
|
*__second_cut, __comp);
|
|
__dist11 = _DISTANCE (__first, __first_cut, _Dist);
|
|
}
|
|
_STD::rotate (__first_cut, __middle, __second_cut);
|
|
|
|
_BidirIter __middle2 = __first_cut;
|
|
|
|
_STD::advance (__middle2, __dist22);
|
|
|
|
__merge_without_buffer (__first, __first_cut, __middle2,
|
|
__dist11, __dist22, __comp);
|
|
__merge_without_buffer (__middle2, __second_cut, __last,
|
|
__dist1 - __dist11, __dist2 - __dist22, __comp);
|
|
}
|
|
|
|
_EXPORT
|
|
template <class _BidirIter1, class _BidirIter2, class _Dist>
|
|
_BidirIter1 __rotate_adaptive (_BidirIter1 __first,
|
|
_BidirIter1 __middle,
|
|
_BidirIter1 __last,
|
|
_Dist __dist1, _Dist __dist2,
|
|
_BidirIter2 __buf,
|
|
_Dist __buf_size)
|
|
{
|
|
_RWSTD_ASSERT_IN_RANGE (__middle, __first, __last);
|
|
|
|
if (__dist1 > __dist2 && __dist2 <= __buf_size) {
|
|
_BidirIter2 __buf_end = _STD::copy (__middle, __last, __buf);
|
|
_STD::copy_backward (__first, __middle, __last);
|
|
return _STD::copy (__buf, __buf_end, __first);
|
|
}
|
|
|
|
if (__dist1 <= __buf_size) {
|
|
_BidirIter2 __buf_end = _STD::copy (__first, __middle, __buf);
|
|
_STD::copy (__middle, __last, __first);
|
|
return _STD::copy_backward (__buf, __buf_end, __last);
|
|
}
|
|
|
|
_STD::rotate (__first, __middle, __last);
|
|
_STD::advance (__first, __dist2);
|
|
return __first;
|
|
}
|
|
|
|
|
|
template <class _BidirIter1, class _BidirIter2,
|
|
class _BidirIter3>
|
|
_BidirIter3 __merge_backward (_BidirIter1 __first1,
|
|
_BidirIter1 __last1,
|
|
_BidirIter2 __first2,
|
|
_BidirIter2 __last2,
|
|
_BidirIter3 __res)
|
|
{
|
|
_RWSTD_ASSERT_RANGE (__first1, __last1);
|
|
_RWSTD_ASSERT_RANGE (__first2, __last2);
|
|
|
|
if (__first1 == __last1)
|
|
return _STD::copy_backward (__first2, __last2, __res);
|
|
|
|
if (__first2 == __last2)
|
|
return _STD::copy_backward (__first1, __last1, __res);
|
|
|
|
for (--__last1, --__last2; ; ) {
|
|
if (*__last2 < *__last1) {
|
|
*--__res = *__last1;
|
|
if (__first1 == __last1)
|
|
return _STD::copy_backward (__first2, ++__last2, __res);
|
|
--__last1;
|
|
}
|
|
else {
|
|
*--__res = *__last2;
|
|
if (__first2 == __last2)
|
|
return _STD::copy_backward (__first1, ++__last1, __res);
|
|
--__last2;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
_EXPORT
|
|
template <class _BidirIter1, class _BidirIter2,
|
|
class _BidirIter3, class _Compare>
|
|
_BidirIter3 __merge_backward (_BidirIter1 __first1,
|
|
_BidirIter1 __last1,
|
|
_BidirIter2 __first2,
|
|
_BidirIter2 __last2,
|
|
_BidirIter3 __res,
|
|
_Compare __comp)
|
|
{
|
|
_RWSTD_ASSERT_RANGE (__first1, __last1);
|
|
_RWSTD_ASSERT_RANGE (__first2, __last2);
|
|
|
|
if (__first1 == __last1)
|
|
return _STD::copy_backward (__first2, __last2, __res);
|
|
if (__first2 == __last2)
|
|
return _STD::copy_backward (__first1, __last1, __res);
|
|
|
|
for (--__last1, --__last2; ; ) {
|
|
if (__comp (*__last2, *__last1)) {
|
|
*--__res = *__last1;
|
|
if (__first1 == __last1)
|
|
return _STD::copy_backward (__first2, ++__last2, __res);
|
|
--__last1;
|
|
}
|
|
else {
|
|
*--__res = *__last2;
|
|
if (__first2 == __last2)
|
|
return _STD::copy_backward (__first1, ++__last1, __res);
|
|
--__last2;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
template <class _BidirIter, class _Dist, class _Pointer, class _Compare>
|
|
void __merge_adaptive (_BidirIter __first, _BidirIter __middle,
|
|
_BidirIter __last,
|
|
_Dist __dist1, _Dist __dist2,
|
|
_Pointer __buf, _Dist __buf_size,
|
|
_Compare __comp)
|
|
{
|
|
_RWSTD_ASSERT_IN_RANGE (__middle, __first, __last);
|
|
|
|
if (__dist1 <= __dist2 && __dist1 <= __buf_size)
|
|
{
|
|
_Pointer __buf_end = _STD::copy (__first, __middle, __buf);
|
|
_STD::merge (__buf, __buf_end, __middle, __last, __first, __comp);
|
|
}
|
|
else if (__dist2 <= __buf_size)
|
|
{
|
|
_Pointer __buf_end = _STD::copy (__middle, __last, __buf);
|
|
__merge_backward (__first, __middle, __buf, __buf_end, __last,
|
|
__comp);
|
|
}
|
|
else
|
|
{
|
|
_BidirIter __first_cut = __first;
|
|
_BidirIter __second_cut = __middle;
|
|
_Dist __dist11;
|
|
_Dist __dist22;
|
|
if (__dist1 > __dist2)
|
|
{
|
|
__dist11 = __dist1 / 2;
|
|
_STD::advance (__first_cut, __dist11);
|
|
__second_cut = _STD::lower_bound (__middle, __last, *__first_cut,
|
|
__comp);
|
|
__dist22 = _DISTANCE (__middle, __second_cut, _Dist);
|
|
}
|
|
else
|
|
{
|
|
__dist22 = __dist2 / 2;
|
|
_STD::advance (__second_cut, __dist22);
|
|
__first_cut = _STD::upper_bound (__first, __middle, *__second_cut,
|
|
__comp);
|
|
__dist11 = _DISTANCE (__first, __first_cut, _Dist);
|
|
}
|
|
_BidirIter __middle2 =
|
|
__rotate_adaptive (__first_cut, __middle, __second_cut,
|
|
__dist1 - __dist11, __dist22,
|
|
__buf, __buf_size);
|
|
__merge_adaptive (__first, __first_cut, __middle2,
|
|
__dist11, __dist22,
|
|
__buf, __buf_size, __comp);
|
|
__merge_adaptive (__middle2, __second_cut, __last,
|
|
__dist1 - __dist11, __dist2 - __dist22,
|
|
__buf, __buf_size, __comp);
|
|
}
|
|
}
|
|
|
|
|
|
_EXPORT
|
|
template <class _BidirIter, class _Dist, class _TypeT, class _Compare>
|
|
void __inplace_merge (_BidirIter __first, _BidirIter __middle,
|
|
_BidirIter __last, _Dist*, _TypeT*, _Compare __comp)
|
|
{
|
|
_Dist __dist1 = _DISTANCE (__first, __middle, _Dist);
|
|
_Dist __dist2 = _DISTANCE (__middle, __last, _Dist);
|
|
|
|
// call an extension of get_temporary_buffer<>() in case partial class
|
|
// specialization (and iterator_traits<>) isn't supported by compiler
|
|
pair<_TypeT*, _Dist> __pair =
|
|
_STD::get_temporary_buffer (__dist1 + __dist2, (_TypeT*)0);
|
|
|
|
if (__pair.first == 0) {
|
|
__merge_without_buffer (__first, __middle, __last, __dist1, __dist2,
|
|
__comp);
|
|
}
|
|
else {
|
|
_Dist __dist = (_STD::min)(__pair.second, __dist1 + __dist2);
|
|
|
|
_STD::fill_n (raw_storage_iterator<_TypeT*, _TypeT> (__pair.first),
|
|
__dist, *__first);
|
|
__merge_adaptive (__first, __middle, __last, __dist1, __dist2,
|
|
__pair.first, __pair.second, __comp);
|
|
|
|
for (_TypeT *__ptr = __pair.first + __dist;
|
|
!(__pair.first == --__ptr); )
|
|
(*__ptr).~_TypeT ();
|
|
|
|
_STD::return_temporary_buffer (__pair.first);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Set operations. Assume sorted sequences.
|
|
//
|
|
|
|
|
|
// 25.3.5.1 - returns true iff every (not necessarily distinct) element
|
|
// in [first2, last2) occurs (at least as many times) in [first1, last1)
|
|
_EXPORT
|
|
template <class _InputIter1, class _InputIter2, class _Compare>
|
|
bool includes (_InputIter1 __first1, _InputIter1 __last1,
|
|
_InputIter2 __first2, _InputIter2 __last2,
|
|
_Compare __comp)
|
|
{
|
|
_RWSTD_ASSERT_RANGE (__first1, __last1);
|
|
_RWSTD_ASSERT_RANGE (__first2, __last2);
|
|
|
|
for (; !(__first1 == __last1) && !(__first2 == __last2); ++__first1) {
|
|
if (__comp (*__first2, *__first1))
|
|
return false;
|
|
|
|
if (__comp (*__first1, *__first2) == false)
|
|
++__first2;
|
|
}
|
|
|
|
return __first2 == __last2;
|
|
}
|
|
|
|
|
|
_EXPORT
|
|
template <class _InputIter1, class _InputIter2, class _OutputIter,
|
|
class _Compare>
|
|
_OutputIter set_union (_InputIter1 __first1, _InputIter1 __last1,
|
|
_InputIter2 __first2, _InputIter2 __last2,
|
|
_OutputIter __res, _Compare __comp)
|
|
{
|
|
_RWSTD_ASSERT_RANGE (__first1, __last1);
|
|
_RWSTD_ASSERT_RANGE (__first2, __last2);
|
|
|
|
for (; !(__first1 == __last1) && !(__first2 == __last2); ++__res) {
|
|
if (__comp (*__first1, *__first2)) {
|
|
*__res = *__first1;
|
|
++__first1;
|
|
}
|
|
else if (__comp (*__first2, *__first1)) {
|
|
*__res = *__first2;
|
|
++__first2;
|
|
}
|
|
else {
|
|
*__res = *__first1;
|
|
++__first1;
|
|
++__first2;
|
|
}
|
|
}
|
|
return _STD::copy (__first2, __last2,
|
|
_STD::copy (__first1, __last1, __res));
|
|
}
|
|
|
|
|
|
_EXPORT
|
|
template <class _InputIter1, class _InputIter2, class _OutputIter,
|
|
class _Compare>
|
|
_OutputIter set_intersection (_InputIter1 __first1, _InputIter1 __last1,
|
|
_InputIter2 __first2, _InputIter2 __last2,
|
|
_OutputIter __res, _Compare __comp)
|
|
{
|
|
_RWSTD_ASSERT_RANGE (__first1, __last1);
|
|
_RWSTD_ASSERT_RANGE (__first2, __last2);
|
|
|
|
while (!(__first1 == __last1) && !(__first2 == __last2)) {
|
|
if (__comp (*__first1, *__first2))
|
|
++__first1;
|
|
else if (__comp (*__first2, *__first1))
|
|
++__first2;
|
|
else {
|
|
*__res = *__first1;
|
|
++__res;
|
|
++__first1;
|
|
++__first2;
|
|
}
|
|
}
|
|
|
|
return __res;
|
|
}
|
|
|
|
|
|
_EXPORT
|
|
template <class _InputIter1, class _InputIter2, class _OutputIter,
|
|
class _Compare>
|
|
_OutputIter set_difference (_InputIter1 __first1, _InputIter1 __last1,
|
|
_InputIter2 __first2, _InputIter2 __last2,
|
|
_OutputIter __res, _Compare __comp)
|
|
{
|
|
_RWSTD_ASSERT_RANGE (__first1, __last1);
|
|
_RWSTD_ASSERT_RANGE (__first2, __last2);
|
|
|
|
while (!(__first1 == __last1) && !(__first2 == __last2)) {
|
|
if (__comp (*__first1, *__first2)) {
|
|
*__res = *__first1;
|
|
++__res;
|
|
++__first1;
|
|
}
|
|
else if (__comp (*__first2, *__first1))
|
|
++__first2;
|
|
else {
|
|
++__first1;
|
|
++__first2;
|
|
}
|
|
}
|
|
|
|
return _STD::copy (__first1, __last1, __res);
|
|
}
|
|
|
|
|
|
_EXPORT
|
|
template <class _InputIter1, class _InputIter2, class _OutputIter,
|
|
class _Compare>
|
|
_OutputIter set_symmetric_difference (_InputIter1 __first1,
|
|
_InputIter1 __last1,
|
|
_InputIter2 __first2,
|
|
_InputIter2 __last2,
|
|
_OutputIter __res,
|
|
_Compare __comp)
|
|
{
|
|
_RWSTD_ASSERT_RANGE (__first1, __last1);
|
|
_RWSTD_ASSERT_RANGE (__first2, __last2);
|
|
|
|
while (!(__first1 == __last1) && !(__first2 == __last2)) {
|
|
if (__comp (*__first1, *__first2)) {
|
|
*__res = *__first1;
|
|
++__res;
|
|
++__first1;
|
|
}
|
|
else if (__comp (*__first2, *__first1)) {
|
|
*__res = *__first2;
|
|
++__res;
|
|
++__first2;
|
|
}
|
|
else {
|
|
++__first1;
|
|
++__first2;
|
|
}
|
|
}
|
|
|
|
return _STD::copy (__first2, __last2, _STD::copy(__first1, __last1, __res));
|
|
}
|
|
|
|
//
|
|
// Minimum and maximum.
|
|
//
|
|
|
|
|
|
_EXPORT
|
|
template <class _FwdIter, class _Compare>
|
|
_FwdIter min_element (_FwdIter __first, _FwdIter __last, _Compare __comp)
|
|
{
|
|
_RWSTD_ASSERT_RANGE (__first, __last);
|
|
|
|
_FwdIter __res = __first;
|
|
|
|
if (!(__first == __last)) {
|
|
while (!(++__first == __last)) {
|
|
if (__comp (*__first, *__res))
|
|
__res = __first;
|
|
}
|
|
}
|
|
|
|
return __res;
|
|
}
|
|
|
|
|
|
_EXPORT
|
|
template <class _FwdIter, class _Compare>
|
|
_FwdIter max_element (_FwdIter __first, _FwdIter __last, _Compare __comp)
|
|
{
|
|
_RWSTD_ASSERT_RANGE (__first, __last);
|
|
|
|
_FwdIter __res = __first;
|
|
|
|
if (!(__first == __last)) {
|
|
while (!(++__first == __last)) {
|
|
if (__comp (*__res, *__first))
|
|
__res = __first;
|
|
}
|
|
}
|
|
|
|
return __res;
|
|
}
|
|
|
|
//
|
|
// Permutations.
|
|
//
|
|
|
|
_EXPORT
|
|
template <class _BidirIter, class _Compare>
|
|
bool next_permutation (_BidirIter __first, _BidirIter __last, _Compare __comp)
|
|
{
|
|
_RWSTD_ASSERT_RANGE (__first, __last);
|
|
|
|
if (__first == __last)
|
|
return false;
|
|
|
|
_BidirIter __i = __first;
|
|
|
|
if (++__i == __last)
|
|
return false;
|
|
|
|
bool __res;
|
|
|
|
for (__i = __last, --__i; ; ) {
|
|
const _BidirIter __ii = __i;
|
|
|
|
if (__comp (*--__i, *__ii)) {
|
|
|
|
_BidirIter __j = __last;
|
|
|
|
while (__comp (*__i, *--__j) == false);
|
|
|
|
_STD::iter_swap (__i, __j);
|
|
|
|
__first = __ii;
|
|
__res = true;
|
|
break;
|
|
}
|
|
|
|
if (__i == __first) {
|
|
__res = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
_STD::reverse (__first, __last);
|
|
|
|
return __res;
|
|
}
|
|
|
|
|
|
_EXPORT
|
|
template <class _BidirIter, class _Compare>
|
|
bool prev_permutation (_BidirIter __first, _BidirIter __last, _Compare __comp)
|
|
{
|
|
_RWSTD_ASSERT_RANGE (__first, __last);
|
|
|
|
if (__first == __last)
|
|
return false;
|
|
|
|
_BidirIter __i = __first;
|
|
|
|
if (++__i == __last)
|
|
return false;
|
|
|
|
bool __res;
|
|
|
|
for (__i = __last, --__i; ; ) {
|
|
const _BidirIter __ii = __i;
|
|
|
|
if (__comp (*__ii, *--__i)) {
|
|
|
|
_BidirIter __j = __last;
|
|
|
|
while (__comp (*--__j, *__i) == false);
|
|
|
|
_STD::iter_swap (__i, __j);
|
|
|
|
__first = __ii;
|
|
__res = true;
|
|
break;
|
|
}
|
|
|
|
if (__i == __first) {
|
|
__res = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
_STD::reverse (__first, __last);
|
|
|
|
return __res;
|
|
}
|
|
|
|
|
|
} // namespace std
|