/*  Metrowerks Standard Library  Version 4.0  1998 August 10  */

/*  $Date: 1998/12/04 23:58:20 $ 
 *  $Revision: 1.2 $ 
 *  $NoKeywords: $ 
 *
 *		Portions Copyright  1995-1998 Metrowerks, Inc.
 *		All rights reserved.
 */

/**
 **   algorithm        hh 971221  filename changed from algorithm.h
 **
 **  Lib++  : The Modena C++ Standard Library,
 **           Version 2.4, October 1997
 **
 **  Copyright (c) 1995-1997 Modena Software Inc.
 **/

#ifndef _ALGORITHM      // hh 971221  include guards given standard compliant name
#define _ALGORITHM

#include <mcompile.h>

#include <algobase.h>    // hh 971220 fixed MOD_INCLUDE
#include <heap.h>        // hh 971220 fixed MOD_INCLUDE
#include <memory>        // hh 971220 fixed MOD_INCLUDE
#include <mutex.h>       // hh 971220 fixed MOD_INCLUDE

#ifndef RC_INVOKED // hh 971230

#pragma options align=native  // hh 971221 added align and import pragmas
#if defined(__CFM68K__) && !defined(__USING_STATIC_LIBS__)
	#pragma import on
#endif

#ifdef MSIPL_USING_NAMESPACE   // hh 971221 expanded namespace macro
	namespace std {
#endif

// Subclause 25.1 -- Non-modifying sequence operations

// Section 25.1.1 -- For each

template <class InputIterator, class Function>
inline
Function
for_each(InputIterator first, InputIterator last, Function f)
{
	for (; first != last; ++first)
		f(*first);
	return f;
}

// hh 980519  Made sweep through code changing != to ==.  This is more in line
//            with what the standard calls EqualityComparable.

// Section 25.1.2 -- Find

template <class InputIterator, class T>
inline
InputIterator
find(InputIterator first, InputIterator last, const T& value)
{
	while (first != last && !(*first == value))
		++first;
	return first;
}

template <class InputIterator, class Predicate>
inline
InputIterator find_if (InputIterator first, InputIterator last,
                       Predicate pred)
{
	while (first != last && !pred(*first))
		++first;
	return first;
}

// Section 25.1.3  Find End

// hh 980519 rewrote
template <class ForwardIterator1, class ForwardIterator2>
ForwardIterator1 
find_end(ForwardIterator1 first1, ForwardIterator1 last1, 
         ForwardIterator2 first2, ForwardIterator2 last2)
{
	ForwardIterator1 current1 = first1;
	ForwardIterator1 iter_save = last1;
	while ((current1 = search(first1, last1, first2, last2)) != last1)
	{
		iter_save =  current1;
		first1 = iter_save;
		++first1;  // hh 980519 was advance(first1, d2)
	}
	return iter_save;
}

template <class ForwardIterator1, class ForwardIterator2, class BinaryPredicate>
ForwardIterator1 
find_end(ForwardIterator1 first1, ForwardIterator1 last1, 
         ForwardIterator2 first2, ForwardIterator2 last2, 
         BinaryPredicate binary_pred)
{
	ForwardIterator1 current1 = first1;
	ForwardIterator1 iter_save = last1;
	while ((current1 = search(first1, last1, first2, last2, binary_pred)) != last1)
	{
		iter_save =  current1;
		first1 = iter_save;
		++first1;  // hh 980519 was advance(first1, d2)
	}
	return iter_save;
}

// Section 25.1.4 -- Find First

template <class ForwardIterator1, class ForwardIterator2>
//inline  // hh 980124
ForwardIterator1
find_first_of(ForwardIterator1 first1, ForwardIterator2 last1,
              ForwardIterator2 first2, ForwardIterator2 last2)
{
	ForwardIterator1   current1 = first1;
	ForwardIterator2   current2 = first2;
	while (current1 != last1)
	{
		while (current2 != last2)
			if (*current1 == *current2)
				return current1;
			else
				++current2;
		++current1;
		current2 = first2;
	}
	return last1;
}

template <class ForwardIterator1, class ForwardIterator2, class BinaryPredicate>
//inline  // hh 980124
ForwardIterator1
find_first_of(ForwardIterator1 first1, ForwardIterator2 last1,
              ForwardIterator2 first2, ForwardIterator2 last2,
              BinaryPredicate binary_pred)
{
	ForwardIterator1   current1 = first1;
	ForwardIterator2   current2 = first2;
	while (current1 != last1)
	{
		while (current2 != last2)
			if (binary_pred(*current1, *current2))
				return current1;
			else
				++current2;
		++current1;
		current2 = first2;
	}
	return last1;
}

// Section 25.1.5 -- Adjacent find

template <class ForwardIterator>
ForwardIterator
adjacent_find(ForwardIterator first, ForwardIterator last)
{
	if (first == last)
		return last;
	ForwardIterator next = first;
	while (++next != last)
	{
		if (*first == *next)
			return first;
		first = next;
	}
	return last;
}

template <class ForwardIterator, class BinaryPredicate>
ForwardIterator
adjacent_find(ForwardIterator first, ForwardIterator last, BinaryPredicate binary_pred)
{
	if (first == last)
		return last;
	ForwardIterator next = first;
	while (++next != last)
	{
		if (binary_pred(*first, *next))
			return first;
		first = next;
	}
	return last;
}

// Section 25.1.6 -- Count

template <class InputIterator, class T>
typename iterator_traits<InputIterator>::difference_type
count(InputIterator first, InputIterator last, const T& value)
{
	iterator_traits<InputIterator>::difference_type n = 0;
	for (; first != last; ++first) 
		if (*first == value)
			++n;
	return n;
}

template <class InputIterator, class Predicate>
typename iterator_traits <InputIterator>::difference_type
count_if(InputIterator first, InputIterator last, Predicate pred)
{
	iterator_traits<InputIterator>::difference_type n = 0;
	for (; first != last; ++first) 
		if (pred(*first))
			++n;
	return n;
}

// Section 25.1.7 -- Mismatch -- in algobase.h
// Section 25.1.8 -- Equal -- in algobase.h

// Section 25.1.9 -- Search

// hh 980509 rewrote
template <class ForwardIterator1, class ForwardIterator2>
ForwardIterator1
search(ForwardIterator1 first1, ForwardIterator1 last1,
       ForwardIterator2 first2, ForwardIterator2 last2)
{
	typedef typename iterator_traits<ForwardIterator1>::difference_type Distance1;
	typedef typename iterator_traits<ForwardIterator2>::difference_type Distance2;
	Distance1 d1 = distance(first1, last1);
	Distance2 d2 = distance(first2, last2);
	if (d1 < d2)
		return last1;
	ForwardIterator1 current1 = first1;
	ForwardIterator2 current2 = first2;
	while (current2 != last2)
	{
		if (*current1 == *current2)
		{
			++current1;
			++current2;
			continue;
		}
		--d1;
		current1 = ++first1;
		current2 = first2;
		if (d1 < d2)
			return last1;
	}
	return first1;
}

// hh 980509 rewrote
template <class ForwardIterator1, class ForwardIterator2,
          class BinaryPredicate>
ForwardIterator1
search(ForwardIterator1 first1, ForwardIterator1 last1,
       ForwardIterator2 first2, ForwardIterator2 last2,
       BinaryPredicate binary_pred) 
{
	typedef typename iterator_traits<ForwardIterator1>::difference_type Distance1;
	typedef typename iterator_traits<ForwardIterator2>::difference_type Distance2;
	Distance1 d1 = distance(first1, last1);
	Distance2 d2 = distance(first2, last2);
	if (d1 < d2)
		return last1;
	ForwardIterator1 current1 = first1;
	ForwardIterator2 current2 = first2;
	while (current2 != last2)
	{
		if (binary_pred(*current1, *current2))
		{
			++current1;
			++current2;
			continue;
		}
		--d1;
		current1 = ++first1;
		current2 = first2;
		if (d1 < d2)
			return last1;
	}
	return first1;
}

template <class ForwardIterator, class Size, class T>
ForwardIterator
search_n(ForwardIterator first, ForwardIterator last, Size sz, const T& value)
{
	typedef typename iterator_traits<ForwardIterator>::difference_type Difference;
	Difference d = distance(first, last);
	ForwardIterator found = first;
	Size sz_cur = sz;
	for (; first != last && d >= sz_cur && sz_cur > 0; ++first, --d)
		if (!(*first == value))
			sz_cur = sz;
		else if (sz == sz_cur--)
			found = first;
	return (sz_cur) ? last : found;
}

template <class ForwardIterator, class Size, class T, class BinaryPredicate>
ForwardIterator
search_n(ForwardIterator first, ForwardIterator last, Size sz, const T& value,
         BinaryPredicate b_pred)
{
	typedef typename iterator_traits<ForwardIterator>::difference_type Difference;
	Difference d = distance(first, last);
	ForwardIterator found = first;
	Size sz_cur = sz;
	for (; first != last && d >= sz_cur && sz_cur > 0; ++first, --d)
		if (!b_pred(*first, value))
			sz_cur = sz;
		else if (sz == sz_cur--)
			found = first;
	return (sz_cur) ? last : found;
}

// Subclause 25.2 -- Mutating sequence operations

// Section 25.2.1.1 -- Copy -- in algobase.h
// Section 25.2.1.2 -- Copy backward -- in algobase.h
// Section 25.2.2.1 -- Swap -- in algobase.h

// Section 25.2.2.2 -- Swap ranges

template <class ForwardIterator1, class ForwardIterator2>
ForwardIterator2
swap_ranges(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2) 
{
	for (; first1 != last1; ++first1, ++first2)
		iter_swap(first1, first2);
	return first2;
}

// Section 25.2.3 -- Transform

template <class InputIterator, class OutputIterator, class UnaryOperation>
OutputIterator
transform(InputIterator first, InputIterator last,
                               OutputIterator result, UnaryOperation op)
{
	for (; first != last; ++first, ++result)
		*result = op(*first);
	return result;
}

template <class InputIterator1, class InputIterator2, class OutputIterator, class BinaryOperation>
OutputIterator
transform(InputIterator1 first1, InputIterator1 last1,
          InputIterator2 first2, OutputIterator result, BinaryOperation binary_op)
{
	for (; first1 != last1; ++first1, ++first2, ++result)
		*result = binary_op(*first1, *first2);
	return result;
}

// Section 25.2.4.1 -- Replace

template <class ForwardIterator, class T>
void
replace(ForwardIterator first, ForwardIterator last, const T& old_value, const T& new_value)
{
	while (first != last)
	{
		if (*first == old_value)
			*first = new_value;
		++first;
	}
}

template <class ForwardIterator, class Predicate, class T>
void
replace_if(ForwardIterator first, ForwardIterator last, Predicate pred, const T& new_value)
{
	while (first != last)
	{
		if (pred(*first))
			*first = new_value;
		++first;
	}
}

// Section 25.2.4.2 -- Replace copy

template <class InputIterator, class OutputIterator, class T>
OutputIterator
replace_copy(InputIterator first, InputIterator last, OutputIterator result,
             const T& old_value, const T& new_value)
{
	while (first != last)
	{
		*result = *first == old_value ? new_value : *first;
		++result;
		++first;
	}
	return result;
}

template <class Iterator, class OutputIterator, class Predicate, class T>
OutputIterator
replace_copy_if(Iterator first, Iterator last, OutputIterator result,
                Predicate pred, const T& new_value)
{
	while (first != last)
	{
		*result = pred(*first) ? new_value : *first;
		++result;
		++first;
	}
	return result;
}

// Section 25.2.5 -- Fill -- in algobase.h

// Section 25.2.6 -- Generate

template <class ForwardIterator, class Generator>
void
generate(ForwardIterator first, ForwardIterator last, Generator gen)
{
	for (; first != last; ++first)
		*first = gen();
}

template <class OutputIterator, class Size, class Generator>
void
generate_n(OutputIterator first, Size n, Generator gen)
{
	for (; n > 0; --n, ++first)
		*first = gen();
}

// Section 25.2.7.2 -- Remove copy

template <class InputIterator, class OutputIterator, class T>
// inline  // hh 980508 uninlined
OutputIterator
remove_copy(InputIterator first, InputIterator last, OutputIterator result, const T& value)
{
	while (first != last)
	{
		if (!(*first == value))
		{
			*result = *first;
			++result;
		}
		++first;
	}
	return result;
}

template <class InputIterator, class OutputIterator, class Predicate>
// inline  // hh 980508 uninlined
OutputIterator
remove_copy_if(InputIterator first, InputIterator last, OutputIterator result, Predicate pred)
{
	while (first != last)
	{
		if (!pred(*first))
		{
			*result = *first;
			++result;
		}
		++first;
	}
	return result;
}

// Section 25.2.7.1 -- Remove

template <class ForwardIterator, class T>
inline
ForwardIterator
remove(ForwardIterator first, ForwardIterator last, const T& value)
{
	first = find(first, last, value);
	ForwardIterator next = first;
	return first == last ? first : remove_copy(++next, last, first, value);
}

template <class ForwardIterator, class Predicate>
inline
ForwardIterator
remove_if(ForwardIterator first, ForwardIterator last, Predicate pred)
{
	first = find_if(first, last, pred);
	ForwardIterator next = first;
	return first == last ? first : remove_copy_if(++next, last, first, pred);
}

// Section 25.2.8.2 -- Unique copy

template <class InputIterator, class OutputIterator>
OutputIterator
__unique_copy(InputIterator first, InputIterator last, OutputIterator result,
	output_iterator_tag)
{
	if (first == last)
		return result;
	typedef typename iterator_traits<InputIterator>::value_type Value; // hh 980911
	Value tmp = *first;
	*result = tmp;
	while (++first != last)
	{
		if (!(tmp == *first))
		{
			tmp = *first;
			*++result = tmp;
		}
	}
	return ++result;
}

// hh 980911
template <class InputIterator, class ForwardIterator>
ForwardIterator
__unique_copy(InputIterator first, InputIterator last, ForwardIterator result,
	forward_iterator_tag)
{
	if (first == last)
		return result;
	*result = *first;
	while (++first != last)
	{
		if (!(*result == *first))
			*++result = *first;
	}
	return ++result;
}

template <class InputIterator, class OutputIterator>
inline
OutputIterator
unique_copy(InputIterator first, InputIterator last, OutputIterator result)
{
	typedef typename iterator_traits<OutputIterator>::iterator_category Category;
	return __unique_copy(first, last, result, Category());
}

template <class InputIterator, class OutputIterator, class BinaryPredicate>
OutputIterator
__unique_copy(InputIterator first, InputIterator last, OutputIterator result,
            BinaryPredicate pred, output_iterator_tag)
{
	if (first == last)
		return result;
	typedef typename iterator_traits<InputIterator>::value_type Value; // hh 980911
	Value tmp = *first;
	*result = tmp;
	while (++first != last)
	{
		if (!pred(tmp, *first))
		{
			tmp = *first;
			*++result = tmp;
		}
	}
	return ++result;
}

// hh 980911
template <class InputIterator, class ForwardIterator, class BinaryPredicate>
ForwardIterator
__unique_copy(InputIterator first, InputIterator last, ForwardIterator result,
            BinaryPredicate pred, forward_iterator_tag)
{
	if (first == last)
		return result;
	*result = *first;
	while (++first != last)
	{
		if (!pred(*result, *first))
			*++result = *first;
	}
	return ++result;
}

template <class InputIterator, class OutputIterator, class BinaryPredicate>
inline
OutputIterator
unique_copy(InputIterator first, InputIterator last, OutputIterator result,
	BinaryPredicate pred)
{
	typedef typename iterator_traits<OutputIterator>::iterator_category Category;
	return __unique_copy(first, last, result, pred, Category());
}

// Section 25.2.8.1 -- Unique 

template <class ForwardIterator>
inline
ForwardIterator
unique(ForwardIterator first, ForwardIterator last)
{
	first = adjacent_find(first, last);
	return unique_copy(first, last, first);
}

template <class ForwardIterator, class BinaryPredicate>
inline
ForwardIterator
unique(ForwardIterator first, ForwardIterator last, BinaryPredicate pred)
{
	first = adjacent_find(first, last, pred);
	return unique_copy(first, last, first, pred);
}

// Section 25.2.9.1 -- Reverse

template <class BidirectionalIterator>
void
reverse(BidirectionalIterator first, BidirectionalIterator last)
{
	typename iterator_traits<BidirectionalIterator>::difference_type n =
		distance(first, last);
	--n;
	while(n > 0)
	{
		typename iterator_traits<BidirectionalIterator>::value_type tmp = *first;
		*first = *--last;
		++first;
		*last = tmp;
		n -= 2;
	}
}

// Section 25.2.9.2 -- Reverse copy

template <class BidirectionalIterator, class OutputIterator>
OutputIterator
reverse_copy(BidirectionalIterator first, BidirectionalIterator last, OutputIterator result)
{
	for (; first != last; ++result)
		*result = *--last;
	return result;
}

// Section 25.2.10.1 -- Rotate

// hh 980520  Did analysis of the 3 rotate algorithms (forward, bidirect, and randomAccess)
//            The forward and rand access iterator versions have the same efficiency.
//            The bidirectional version is more expensive.
//            Simplifying the whole thing down to forward iterators.

template <class ForwardIterator>
void
rotate(ForwardIterator first, ForwardIterator middle, ForwardIterator last)
{
	if (first == middle || middle == last)
		return;
	ForwardIterator i = middle;
	while (true)
	{
		iter_swap(first, i);
		if (++first == middle)
		{
			if (++i == last)
				break;
			middle = i;
		} else if (++i == last)
			i = middle;
	}
}

// Section 25.2.10.2 -- Rotate copy

template <class ForwardIterator, class OutputIterator>
inline
OutputIterator
rotate_copy(ForwardIterator first, ForwardIterator middle,
            ForwardIterator last, OutputIterator result)
{
	return copy(first, middle, copy(middle, last, result));
}

// inlined code for the function "long_random"
// speeds up compilation times significantly on UNIX machines
 
// Section 25.2.11 -- Random Shuffle
 
class __random_generator {
protected:
    unsigned long table[55];
    size_t index1;
    size_t index2;
    DEC_MUTEX(_mutex)
public:
    unsigned long operator () (unsigned long limit)
    {
        LOCK(mut_block, _mutex);
        index1 = (index1 + 1) % 55;
        index2 = (index2 + 1) % 55;
        table[index1] = table[index1] - table[index2];
        return table[index1] % limit;
    }
    void seed (unsigned long j);
    __random_generator (unsigned long j) { seed (j); }

    ~__random_generator() { }
};
 
// #define MSIPL_SEED_RANDOM 161803398
extern __random_generator __msipl_rd;

inline unsigned long
__long_random (unsigned long limit)
{
    return __msipl_rd (limit);
}

template <class RandomAccessIterator>
//inline // hh 980521
void __random_shuffle (RandomAccessIterator first,
                       RandomAccessIterator last)
{
    typedef  typename iterator_traits<RandomAccessIterator>::difference_type
                       Difference;
    if (first == last) return;
    for (RandomAccessIterator i = first + 1; i != last; ++i)
        iter_swap (i, first + Difference (__long_random ((unsigned long)((i - first) + 1))));
}

template <class RandomAccessIterator>
inline void random_shuffle (RandomAccessIterator first,
                            RandomAccessIterator last)
{
    __random_shuffle (first, last);
}

template <class RandomAccessIterator, class RandomNumberGenerator>
// inline // hh 980521
void
random_shuffle(RandomAccessIterator first, RandomAccessIterator last,
               RandomNumberGenerator& rand)
{
	if (first == last)
		return;
	for (RandomAccessIterator i = first + 1; i != last; ++i)
		iter_swap(i, first + rand((i - first) + 1));
}

// Section 25.2.12.1 -- partition

template <class BidirectionalIterator, class Predicate>
//inline  // hh 980124
BidirectionalIterator
__partition(BidirectionalIterator first, BidirectionalIterator last, Predicate pred,
            bidirectional_iterator_tag)
{
	while (true)
	{
		while (true)
			if (first == last)
				return first;
			else if (pred(*first))
				++first;
			else
				break;
		--last;
		while (true)
			if (first == last)
				return first;
			else if (!pred(*last))
				--last;
			else
				break;
		iter_swap(first, last);
		++first;
	}
}

template <class RandomAccessIterator, class Predicate>
RandomAccessIterator
__partition(RandomAccessIterator first, RandomAccessIterator last, Predicate pred,
            random_access_iterator_tag)
{
	RandomAccessIterator i = first;
	RandomAccessIterator j = last - 1;
	while (i <= j)
	{
		while (i < last && pred(*i))
			++i;
		while (first < j && !pred(*j))
			--j;
		if (i >= j)
			break;
		iter_swap(i, j);
		++i;
		--j;
	}
	return i;
}

template <class BidirectionalIterator, class Predicate>
inline
BidirectionalIterator
partition(BidirectionalIterator first, BidirectionalIterator last, Predicate pred)
{
	return __partition(first, last, pred,
		iterator_traits<BidirectionalIterator>::iterator_category());
}

// Section 25.2.12.2 -- stable partition

// hh 980522  Kept the same algorithms, but simplified things up a bit.
//            Optimized the __inplace_stable_partition just a tad.
//            Also, the standard calls for BidirectionalIterators here.  I can't
//            see any reason not to allow ForwardIterators, so I'm leaving this
//            non-standard.

template <class ForwardIterator, class Predicate, class Difference>
ForwardIterator
__stable_partition(ForwardIterator first, ForwardIterator last,
                   Predicate pred, Difference len)
{
	switch (len)
	{
	case 1:
		return pred(*first) ? last : first;
	case 2:
		if (pred(*first))
		{
			++first;
			if (pred(*first))
				return last;
			return first;
		}
		else {
			last = first;
			++last;
			if (pred(*last))
			{
				iter_swap(first, last);
				return last;
			}
			return first;
		}
	}
	ForwardIterator middle = first;
	Difference len1 = len / 2;
	advance(middle, len1);
	ForwardIterator first_cut  = __stable_partition(first, middle, pred, len1);
	ForwardIterator second_cut = __stable_partition(middle, last, pred, len - len1);
	rotate(first_cut, middle, second_cut);
	len = distance(middle, second_cut);
	advance(first_cut, len);
	return first_cut;
}

template <class ForwardIterator, class Pointer, class Predicate, class Difference>
ForwardIterator
__stable_partition(ForwardIterator first, ForwardIterator last,
                   Predicate pred, Difference len, Pointer buffer,
                   Difference buffer_size, Difference& fill_pointer)
{
	if (len == 1)
		return pred(*first) ? last : first;
	if (len <= buffer_size)
	{
		len = 0;
		ForwardIterator result1 = first;
		Pointer result2 = buffer;
		for (; first != last && len < fill_pointer; ++first)
		{
			if (pred(*first))
			{
				*result1 = *first;
				++result1;
			}
			else {
				*result2 = *first;
				++len;
				++result2;
			}
		}
		if (first != last)
		{
			typedef typename iterator_traits<ForwardIterator>::value_type value_type;
			raw_storage_iterator<Pointer, value_type> result3(result2);
			while (first != last)
			{
				if (pred(*first))
				{
					*result1 = *first;
					++first;
					++result1;
				}
				else {
					*result3 = *first;
					++len;
					++first;
					++result3;
				}
			}
			fill_pointer = len;
		}
		copy(buffer, buffer + len, result1);
		return result1;
	}
	ForwardIterator middle = first;
	Difference len1 = len / 2;
	advance(middle, len1);
	ForwardIterator first_cut  = __stable_partition(first, middle, pred, len1,
		buffer, buffer_size, fill_pointer);
	ForwardIterator second_cut = __stable_partition(middle, last, pred, len - len1,
		buffer, buffer_size, fill_pointer);
	rotate(first_cut, middle, second_cut);
	len = distance(middle, second_cut);
	advance(first_cut, len);
	return first_cut;
}

template <class ForwardIterator, class Predicate>
ForwardIterator
stable_partition(ForwardIterator first, ForwardIterator last, Predicate pred)
{
	if (first == last)
		return first;
	typedef typename iterator_traits<ForwardIterator>::value_type Value;
	typedef typename iterator_traits<ForwardIterator>::difference_type Difference;
	Difference len = distance(first, last);
	pair<Value*, ptrdiff_t> p = get_temporary_buffer<Value>(len);
	if (p.first == 0)
		return __stable_partition(first, last, pred, len);
	Difference fill_pointer = 0;
	ForwardIterator result;
	MSIPL_TRY 
	{
		result = __stable_partition(first, last, pred, len, p.first, Difference(p.second),
		                            fill_pointer);
	}
	#ifdef MSIPL_EXCEPT // hh 980902 added
	MSIPL_CATCH
	{
		destroy(p.first, p.first + fill_pointer);
		return_temporary_buffer(p.first);
		throw;
	}
	#endif
	destroy(p.first, p.first + fill_pointer);
	return_temporary_buffer(p.first);
	return result;
}

// Subclause 25.3 -- Sorting and related algorithms

template<class T>
void
__sort3(T& a1, T& a2, T& a3)
{
	if (a2 < a1)
		swap(a1, a2);
	if (a3 < a2)
	{
		T tmp = a3;
		a3 = a2;
		if (tmp < a1)
		{
			a2 = a1;
			a1 = tmp;
		}
		else {
			a2 = tmp;
		}
	}
}

template<class T, class Compare>
void
__sort3(T& a1, T& a2, T& a3, Compare comp)
{
	if (comp(a2, a1))
		swap(a1, a2);
	if (comp(a3, a2))
	{
		T tmp = a3;
		a3 = a2;
		if (comp(tmp, a1))
		{
			a2 = a1;
			a1 = tmp;
		}
		else {
			a2 = tmp;
		}
	}
}

template<class RandomAccessIterator>
void
__insertion_sort(RandomAccessIterator first, RandomAccessIterator last)
{
	typedef typename iterator_traits<RandomAccessIterator>::value_type Value;
	RandomAccessIterator i = first;
	for (++i; i < last; ++i)
	{
		Value tmp = *i;
		RandomAccessIterator j = i;
		RandomAccessIterator k = j;
		--j;
		while (first < k && tmp < *j)
		{
			*k = *j;
			--k;
			--j;
		}
		*k = tmp;
	}
}

template<class RandomAccessIterator, class Compare>
void
__insertion_sort(RandomAccessIterator first, RandomAccessIterator last, Compare comp)
{
	typedef typename iterator_traits<RandomAccessIterator>::value_type Value;
	RandomAccessIterator i = first;
	for (++i; i < last; ++i)
	{
		Value tmp = *i;
		RandomAccessIterator j = i;
		RandomAccessIterator k = j;
		--j;
		while (first < k && comp(tmp, *j))
		{
			*k = *j;
			--k;
			--j;
		}
		*k = tmp;
	}
}

template<class RandomAccessIterator>
void
sort(RandomAccessIterator first, RandomAccessIterator last)
{
	typedef typename iterator_traits<RandomAccessIterator>::difference_type Difference;
	typedef typename iterator_traits<RandomAccessIterator>::value_type Value;
	Difference len = last - first;
	if (len <= 1)
		return;
	if (len <= 20)
	{
		__insertion_sort(first, last);
		return;
	}
	RandomAccessIterator m = first + len / 2;
	RandomAccessIterator j = last - 1;
	__sort3(*first, *m, *j);
	Value part(*m);
	RandomAccessIterator i = first + 1;
	--j;
	while (true)
	{
		while (*i < part)
			++i;
		while (part < *j)
			--j;
		if (i >= j)
			break;
		iter_swap(i, j);
		++i;
		--j;
	}
	sort(first, i);
	sort(i, last);
}

template<class RandomAccessIterator, class Compare>
void
sort(RandomAccessIterator first, RandomAccessIterator last, Compare comp)
{
	typedef typename iterator_traits<RandomAccessIterator>::difference_type Difference;
	typedef typename iterator_traits<RandomAccessIterator>::value_type Value;
	Difference len = last - first;
	if (len <= 1)
		return;
	if (len <= 20)
	{
		__insertion_sort(first, last, comp);
		return;
	}
	RandomAccessIterator m = first + len / 2;
	RandomAccessIterator j = last - 1;
	__sort3(*first, *m, *j, comp);
	Value part(*m);
	RandomAccessIterator i = first + 1;
	--j;
	while (true)
	{
		while (comp(*i, part))
			++i;
		while (comp(part, *j))
			--j;
		if (i >= j)
			break;
		iter_swap(i, j);
		++i;
		--j;
	}
	sort(first, i, comp);
	sort(i, last, comp);
}

// Section 25.3.1.2 -- stable sort

// hh 980603 Rewrote stable_sort.  Was giving incorrect results.  New version is correct,
//           relatively efficient, easier to read, and exception-safe.

template <class RandomAccessIterator>
void
__stable_sort(RandomAccessIterator first, RandomAccessIterator last)
{
	typedef typename iterator_traits<RandomAccessIterator>::difference_type Difference;
	Difference len = last - first;
	if (len <= 1)
		return;
	if (len == 2)
	{
		--last;
		if (*last < *first)
			iter_swap(first, last);
		return;
	}
	if (len <= 20)
	{
		__insertion_sort(first, last);
		return;
	}
	RandomAccessIterator middle = first + len / 2;
	__stable_sort(first, middle);
	__stable_sort(middle, last);
	__inplace_merge(first, middle, last, middle - first, last - middle);
}

template <class RandomAccessIterator, class Compare>
void
__stable_sort(RandomAccessIterator first, RandomAccessIterator last, Compare comp)
{
	typedef typename iterator_traits<RandomAccessIterator>::difference_type Difference;
	Difference len = last - first;
	if (len <= 1)
		return;
	if (len == 2)
	{
		--last;
		if (comp(*last, *first))
			iter_swap(first, last);
		return;
	}
	if (len <= 20)
	{
		__insertion_sort(first, last, comp);
		return;
	}
	RandomAccessIterator middle = first + len / 2;
	__stable_sort(first, middle, comp);
	__stable_sort(middle, last, comp);
	__inplace_merge(first, middle, last, middle - first, last - middle, comp);
}

template <class RandomAccessIterator1, class RandomAccessIterator2>
void
__stable_sort_copy(RandomAccessIterator1 first1, RandomAccessIterator1 last1,
                   RandomAccessIterator2 first2)
{
	typedef typename iterator_traits<RandomAccessIterator1>::difference_type Difference;
	Difference len = last1 - first1;
	if (len <= 0)
		return;
	if (len == 1)
	{
		*first2 = *first1;
		return;
	}
	if (len == 2)
	{
		--last1;
		if (*last1 < *first1)
			reverse_copy(first1, last1, first2);
		else
			copy(first1, last1, first2);
		return;
	}
	if (len <= 20)
	{
		__insertion_sort(first1, last1);
		copy(first1, last1, first2);
		return;
	}
	Difference len2 = len / 2;
	RandomAccessIterator1 middle = first1 + len2;
	__stable_sort(first1, middle, first2, len2);
	__stable_sort(middle, last1, first2+len2, len-len2);
	merge(first1, first1+len2, first1+len2, first1+len, first2);
}

template <class RandomAccessIterator1, class RandomAccessIterator2, class Compare>
void
__stable_sort_copy(RandomAccessIterator1 first1, RandomAccessIterator1 last1,
                   RandomAccessIterator2 first2, Compare comp)
{
	typedef typename iterator_traits<RandomAccessIterator1>::difference_type Difference;
	Difference len = last1 - first1;
	if (len <= 0)
		return;
	if (len == 1)
	{
		*first2 = *first1;
		return;
	}
	if (len == 2)
	{
		--last1;
		if (comp(*last1, *first1))
			reverse_copy(first1, last1, first2);
		else
			copy(first1, last1, first2);
		return;
	}
	if (len <= 20)
	{
		__insertion_sort(first1, last1, comp);
		copy(first1, last1, first2);
		return;
	}
	Difference len2 = len / 2;
	RandomAccessIterator1 middle = first1 + len2;
	__stable_sort(first1, middle, first2, len2, comp);
	__stable_sort(middle, last1, first2+len2, len-len2, comp);
	merge(first1, first1+len2, first1+len2, first1+len, first2, comp);
}

template <class RandomAccessIterator, class Pointer>
void
__stable_sort(RandomAccessIterator first, RandomAccessIterator last,
              Pointer buffer, ptrdiff_t buffer_size)
{
	typedef typename iterator_traits<RandomAccessIterator>::difference_type Difference;
	Difference len = last - first;
	if (len <= 1)
		return;
	if (len == 2)
	{
		--last;
		if (*last < *first)
			iter_swap(first, last);
		return;
	}
	if (len <= 20)
	{
		__insertion_sort(first, last);
		return;
	}
	RandomAccessIterator middle = first + len / 2;
	if (len > Difference(buffer_size))
	{
		__stable_sort(first, middle, buffer, buffer_size);
		__stable_sort(middle, last, buffer, buffer_size);
		__inplace_merge(first, middle, last, middle - first, last - middle, buffer, buffer_size);
	}
	else {
		__stable_sort_copy(first, middle, buffer);
		__stable_sort_copy(middle, last, buffer+len/2);
		merge(buffer, buffer+len/2, buffer+len/2, buffer+len, first);
	}
}

template <class RandomAccessIterator, class Pointer, class Compare>
void
__stable_sort(RandomAccessIterator first, RandomAccessIterator last,
              Pointer buffer, ptrdiff_t buffer_size, Compare comp)
{
	typedef typename iterator_traits<RandomAccessIterator>::difference_type Difference;
	Difference len = last - first;
	if (len <= 1)
		return;
	if (len == 2)
	{
		--last;
		if (comp(*last, *first))
			iter_swap(first, last);
		return;
	}
	if (len <= 20)
	{
		__insertion_sort(first, last, comp);
		return;
	}
	RandomAccessIterator middle = first + len / 2;
	if (len > Difference(buffer_size))
	{
		__stable_sort(first, middle, buffer, buffer_size, comp);
		__stable_sort(middle, last, buffer, buffer_size, comp);
		__inplace_merge(first, middle, last, middle - first, last - middle, buffer,
			buffer_size, comp);
	}
	else {
		__stable_sort_copy(first, middle, buffer, comp);
		__stable_sort_copy(middle, last, buffer+len/2, comp);
		merge(buffer, buffer+len/2, buffer+len/2, buffer+len, first, comp);
	}
}

template <class RandomAccessIterator>
void
stable_sort(RandomAccessIterator first, RandomAccessIterator last)
{
	typedef typename iterator_traits<RandomAccessIterator>::difference_type Difference;
	Difference len = last - first;
	if (len <= 1)
		return;
	if (len == 2)
	{
		--last;
		if (*last < *first)
			iter_swap(first, last);
		return;
	}
	if (len <= 20)
	{
		__insertion_sort(first, last);
		return;
	}
	typedef typename iterator_traits<RandomAccessIterator>::value_type Value;
	_TempVec<Value> buf(last-first, *first);
	if (buf.size() == 0)
		__stable_sort(first, last);
	else
		__stable_sort(first, last, buf.begin(), buf.size());
}

template <class RandomAccessIterator, class Compare>
void
stable_sort(RandomAccessIterator first, RandomAccessIterator last, Compare comp)
{
	typedef typename iterator_traits<RandomAccessIterator>::difference_type Difference;
	Difference len = last - first;
	if (len <= 1)
		return;
	if (len == 2)
	{
		--last;
		if (comp(*last, *first))
			iter_swap(first, last);
		return;
	}
	if (len <= 20)
	{
		__insertion_sort(first, last, comp);
		return;
	}
	typedef typename iterator_traits<RandomAccessIterator>::value_type Value;
	_TempVec<Value> buf(last-first, *first);
	if (buf.size() == 0)
		__stable_sort(first, last, comp);
	else
		__stable_sort(first, last, buf.begin(), buf.size(), comp);
}

// Section 25.3.1.3 -- partial sort

template <class RandomAccessIterator>
void
partial_sort(RandomAccessIterator first, RandomAccessIterator middle,
             RandomAccessIterator last)
{
	make_heap(first, middle);
	for (RandomAccessIterator i = middle; i < last; ++i)
	{
		if (*i < *first)
			__replace_heap(first, middle, i);
	}
	sort_heap(first, middle);
}

template <class RandomAccessIterator, class Compare>
void
partial_sort(RandomAccessIterator first, RandomAccessIterator middle,
             RandomAccessIterator last, Compare comp)
{
	typedef typename iterator_traits<RandomAccessIterator>::value_type Value;
	typedef typename iterator_traits<RandomAccessIterator>::difference_type Difference;
	make_heap(first, middle, comp);
	for (RandomAccessIterator i = middle; i < last; ++i)
	{
		if (comp(*i, *first))
			__replace_heap(first, middle, i, comp);
	}
	sort_heap(first, middle, comp);
}

// Section 25.3.1.4 -- partial sort copy

template <class InputIterator, class RandomAccessIterator>
RandomAccessIterator
partial_sort_copy(InputIterator first, InputIterator last,
                  RandomAccessIterator result_first, RandomAccessIterator result_last)
{
	typedef typename iterator_traits<RandomAccessIterator>::value_type Value;
	typedef typename iterator_traits<RandomAccessIterator>::difference_type Difference;
	if (result_first == result_last || first == last)
		return result_first;
	RandomAccessIterator result_real_last = result_first;
	for (; first != last && result_real_last != result_last; ++result_real_last, ++first)
		*result_real_last = *first;
	make_heap(result_first, result_real_last);
	while (first != last)
	{
		if (*first < *result_first) 
			__replace_heap_copy(result_first, result_real_last, *first);
		++first;
	}
	sort_heap(result_first, result_real_last);
	return result_real_last;
}

template <class InputIterator, class RandomAccessIterator, class Compare>
RandomAccessIterator
partial_sort_copy(InputIterator first, InputIterator last,
                  RandomAccessIterator result_first, RandomAccessIterator result_last,
                  Compare comp)
{
	typedef typename iterator_traits<RandomAccessIterator>::value_type Value;
	typedef typename iterator_traits<RandomAccessIterator>::difference_type Difference;
	if (result_first == result_last || first == last)
		return result_first;
	RandomAccessIterator result_real_last = result_first;
	for (; first != last && result_real_last != result_last; ++result_real_last, ++first)
		*result_real_last = *first;
	make_heap(result_first, result_real_last, comp);
	while (first != last)
	{
		if (comp(*first, *result_first)) 
			__replace_heap_copy(result_first, result_real_last, *first, comp);
		++first;
	}
	sort_heap(result_first, result_real_last, comp);
	return result_real_last;
}

// Section 25.3.2 -- Nth element

template <class RandomAccessIterator>
void
nth_element(RandomAccessIterator first, RandomAccessIterator nth, RandomAccessIterator last)
{
	typedef typename iterator_traits<RandomAccessIterator>::difference_type Difference;
	typedef typename iterator_traits<RandomAccessIterator>::value_type Value;
	Difference len = last - first;
	while (len > 3)
	{
		if (nth == first)
		{
			iter_swap(first, min_element(first, last));
			return;
		}
		RandomAccessIterator j = last - 1;
		if (nth == j)
		{
			iter_swap(j, max_element(first, last));
			return;
		}
		RandomAccessIterator m = first + len / 2;
		__sort3(*first, *m, *j);
		Value part(*m);
		RandomAccessIterator i = first + 1;
		--j;
		while (true)
		{
			while (*i < part)
				++i;
			while (part < *j)
				--j;
			if (i >= j)
				break;
			iter_swap(i, j);
			++i;
			--j;
		}
		if (nth < i)
			last = i;
		else
			first = i;
		len = last - first;
	}
	__insertion_sort(first, last);
}

template <class RandomAccessIterator, class Compare>
void
nth_element(RandomAccessIterator first, RandomAccessIterator nth, RandomAccessIterator last,
            Compare comp)
{
	typedef typename iterator_traits<RandomAccessIterator>::difference_type Difference;
	typedef typename iterator_traits<RandomAccessIterator>::value_type Value;
	Difference len = last - first;
	while (len > 3)
	{
		if (nth == first)
		{
			iter_swap(first, min_element(first, last, comp));
			return;
		}
		RandomAccessIterator j = last - 1;
		if (nth == j)
		{
			iter_swap(j, max_element(first, last, comp));
			return;
		}
		RandomAccessIterator m = first + len / 2;
		__sort3(*first, *m, *j, comp);
		Value part(*m);
		RandomAccessIterator i = first + 1;
		--j;
		while (true)
		{
			while (comp(*i, part))
				++i;
			while (comp(part, *j))
				--j;
			if (i >= j)
				break;
			iter_swap(i, j);
			++i;
			--j;
		}
		if (nth < i)
			last = i;
		else
			first = i;
		len = last - first;
	}
	__insertion_sort(first, last, comp);
}

// Section 25.3.3 -- Binary search

// Section 25.3.3.1 -- lower_bound

// hh 980601  No substantial difference between random access & forward versions
//            Deleted random access version.

template <class ForwardIterator, class T>
ForwardIterator
lower_bound(ForwardIterator first, ForwardIterator last, const T& value)
{
	typedef typename iterator_traits<ForwardIterator>::difference_type Difference;
	Difference len = distance(first, last);
	Difference half;
	ForwardIterator middle;
	while (len > 0)
	{
		half = len / 2;
		middle = first;
		advance(middle, half);
		if (*middle < value)
		{
			first = middle;
			++first;
			len = len - half - 1;
		}
		else
			len = half;
	}
	return first;
}

template <class ForwardIterator, class T, class Compare>
ForwardIterator
lower_bound(ForwardIterator first, ForwardIterator last, const T& value, Compare comp)
{
	typedef typename iterator_traits<ForwardIterator>::difference_type Difference;
	Difference len = distance(first, last);
	Difference half;
	ForwardIterator middle;
	while (len > 0)
	{
		half = len / 2;
		middle = first;
		advance(middle, half);
		if (comp(*middle, value))
		{
			first = middle;
			++first;
			len = len - half - 1;
		}
		else
			len = half;
	}
	return first;
}

// Section 25.3.3.2 -- upper_bound

// hh 980601  No substantial difference between random access & forward versions
//            Deleted random access version.

template <class ForwardIterator, class T>
ForwardIterator
upper_bound(ForwardIterator first, ForwardIterator last, const T& value)
{
	typedef typename iterator_traits<ForwardIterator>::difference_type Difference;
	Difference len = distance(first, last);
	Difference half;
	ForwardIterator middle;
	while (len > 0)
	{
		half = len / 2;
		middle = first;
		advance(middle, half);
		if (value < *middle)
			len = half;
		else
		{
			first = middle;
			++first;
			len = len - half - 1;
		}
	}
	return first;
}

template <class ForwardIterator, class T, class Compare>
ForwardIterator
upper_bound(ForwardIterator first, ForwardIterator last, const T& value, Compare comp)
{
	typedef typename iterator_traits<ForwardIterator>::difference_type Difference;
	Difference len = distance(first, last);
	Difference half;
	ForwardIterator middle;
	while (len > 0)
	{
		half = len / 2;
		middle = first;
		advance(middle, half);
		if (comp(value, *middle))
			len = half;
		else
		{
			first = middle;
			++first;
			len = len - half - 1;
		}
	}
	return first;
}

//  Section 25.3.3.3 -- equal range

template <class ForwardIterator, class T>
pair<ForwardIterator, ForwardIterator>
__equal_range(ForwardIterator first, ForwardIterator last, const T& value,
              forward_iterator_tag)
{
	typedef typename iterator_traits<ForwardIterator>::difference_type Difference;
	Difference len = distance(first, last);
	Difference half;
	ForwardIterator middle, left, right;
	while (len > 0)
	{
		half = len / 2;
		middle = first;
		advance(middle, half);
		if (*middle < value)
		{
			first = middle;
			++first;
			len = len - half - 1;
		} else if (value < *middle)
			len = half;
		else
		{
			left = lower_bound(first, middle, value);
			advance(first, len);
			right = upper_bound(++middle, first, value);
			return pair<ForwardIterator, ForwardIterator>(left, right);
		}
	}
	return pair<ForwardIterator, ForwardIterator>(first, first);
}

template <class RandomAccessIterator, class T>
pair<RandomAccessIterator, RandomAccessIterator>
__equal_range(RandomAccessIterator first, RandomAccessIterator last, const T& value,
              random_access_iterator_tag)
{
	typedef typename iterator_traits<RandomAccessIterator>::difference_type Difference;
	Difference len = last - first;
	Difference half;
	RandomAccessIterator middle, left, right;
	while (len > 0)
	{
		half = len / 2;
		middle = first + half;
		if (*middle < value)
		{
			first = middle + 1;
			len = len - half - 1;
		} else if (value < *middle)
			len = half;
		else
		{
			left = lower_bound(first, middle, value);
			right = upper_bound(++middle, first + len, value);
			return pair<RandomAccessIterator, RandomAccessIterator>(left, right);
		}
	}
	return pair<RandomAccessIterator, RandomAccessIterator>(first, first);
}

template <class ForwardIterator, class T>
inline
pair<ForwardIterator, ForwardIterator>
equal_range(ForwardIterator first, ForwardIterator last, const T& value)
{
	typedef typename iterator_traits<ForwardIterator>::iterator_category Category;
	return __equal_range(first, last, value, Category());
}

template <class ForwardIterator, class T, class Compare>
pair<ForwardIterator, ForwardIterator>
__equal_range (ForwardIterator first, ForwardIterator last, const T& value,
               Compare comp, forward_iterator_tag)
{
	typedef typename iterator_traits<ForwardIterator>::difference_type Difference;
	Difference len = distance(first, last);
	Difference half;
	ForwardIterator middle, left, right;
	while (len > 0)
	{
		half = len / 2;
		middle = first;
		advance(middle, half);
		if (comp(*middle, value))
		{
			first = middle;
			++first;
			len = len - half - 1;
		} else if (comp(value, *middle))
			len = half;
		else
		{
			left = lower_bound(first, middle, value, comp);
			advance(first, len);
			right = upper_bound(++middle, first, value, comp);
			return pair<ForwardIterator, ForwardIterator>(left, right);
		}
	}
	return pair<ForwardIterator, ForwardIterator> (first, first);
}           

template <class RandomAccessIterator, class T, class Compare>
pair<RandomAccessIterator, RandomAccessIterator>
__equal_range(RandomAccessIterator first, RandomAccessIterator last, const T& value,
              Compare comp, random_access_iterator_tag)
{
	typedef typename iterator_traits<RandomAccessIterator>::difference_type Difference;
	Difference len = last - first;
	Difference half;
	RandomAccessIterator middle, left, right;
	while (len > 0)
	{
		half = len / 2;
		middle = first + half;
		if (comp(*middle, value))
		{
			first = middle + 1;
			len = len - half - 1;
		} else if (comp(value, *middle))
			len = half;
		else
		{
			left = lower_bound(first, middle, value, comp);
			right = upper_bound(++middle, first + len, value, comp);
			return pair<RandomAccessIterator, RandomAccessIterator>(left, right);
		}
	}
	return pair<RandomAccessIterator, RandomAccessIterator>(first, first);
}           

template <class ForwardIterator, class T, class Compare>
inline
pair<ForwardIterator, ForwardIterator>
equal_range(ForwardIterator first, ForwardIterator last, const T& value, Compare comp)
{
	typedef typename iterator_traits<ForwardIterator>::iterator_category Category;
	return __equal_range(first, last, value, comp, Category());
}    

//  Section 25.3.3.4 -- binary search

template <class ForwardIterator, class T>
inline
bool
binary_search(ForwardIterator first, ForwardIterator last, const T& value)
{
	ForwardIterator i = lower_bound(first, last, value);
	return i != last && !(value < *i);
}

template <class ForwardIterator, class T, class Compare>
inline
bool
binary_search(ForwardIterator first, ForwardIterator last, const T& value, Compare comp)
{
	ForwardIterator i = lower_bound(first, last, value, comp);
	return i != last && !comp(value, *i);
}

// Section 25.3.4 -- Merge

// Section 25.3.4.1 -- merge

template <class InputIterator1, class InputIterator2, class OutputIterator>
OutputIterator
merge(InputIterator1 first1, InputIterator1 last1,
      InputIterator2 first2, InputIterator2 last2,
      OutputIterator result)
{
	for (; first1 != last1 && first2 != last2; ++result)
	{
		if (*first2 < *first1)
		{
			*result = *first2;
			++first2;
		}
		else
		{
			*result = *first1;
			++first1;
		}
	}
	if (first1 == last1)
		return copy(first2, last2, result);
	return copy(first1, last1, result);
}

template <class InputIterator1, class InputIterator2, class OutputIterator,
          class Compare>
OutputIterator
merge(InputIterator1 first1, InputIterator1 last1,
      InputIterator2 first2, InputIterator2 last2,
      OutputIterator result, Compare comp)
{
	for (; first1 != last1 && first2 != last2; ++result)
	{
		if (comp(*first2, *first1))
		{
			*result = *first2;
			++first2;
		}
		else
		{
			*result = *first1;
			++first1;
		}
	}
	if (first1 == last1)
		return copy(first2, last2, result);
	return copy(first1, last1, result);
}

// Section 25.3.4.2 -- inplace_merge

// hh 980602 Kept same algorithms, but simplified the front end to the main algorithms
//           Also, made exception-safe.

template <class BidirectionalIterator, class Difference>
void
__inplace_merge(BidirectionalIterator first, BidirectionalIterator middle,
                BidirectionalIterator last, Difference len1, Difference len2)
{
	if (len1 == 0 || len2 == 0)
		return;
	if (len1 + len2 == 2)
	{
		if (*middle < *first)
			iter_swap(first, middle);
		return;
	}
	BidirectionalIterator first_cut = first;
	BidirectionalIterator second_cut = middle;
	Difference len11;
	Difference len22;
	if (len1 > len2)
	{
		len11 = len1 / 2;
		advance(first_cut, len11);
		second_cut = lower_bound(middle, last, *first_cut);
		len22 = distance(middle, second_cut);
	}
	else
	{
		len22 = len2 / 2;
		advance(second_cut, len22);
		first_cut = upper_bound(first, middle, *second_cut);
		len11 = distance(first, first_cut);
	}
	rotate(first_cut, middle, second_cut);
	BidirectionalIterator new_middle = first_cut;
	advance(new_middle, len22);
	__inplace_merge(first, first_cut, new_middle, len11, len22);
	__inplace_merge(new_middle, second_cut, last, len1 - len11, len2 - len22);
}

template <class BidirectionalIterator, class Difference, class Compare>
void
__inplace_merge(BidirectionalIterator first, BidirectionalIterator middle,
                BidirectionalIterator last, Difference len1, Difference len2, Compare comp)
{
	if (len1 == 0 || len2 == 0)
		return;
	if (len1 + len2 == 2)
	{
		if (comp(*middle, *first))
			iter_swap(first, middle);
		return;
	}
	BidirectionalIterator first_cut = first;
	BidirectionalIterator second_cut = middle;
	Difference len11;
	Difference len22;
	if (len1 > len2)
	{
		len11 = len1 / 2;
		advance(first_cut, len11);
		second_cut = lower_bound(middle, last, *first_cut, comp);
		len22 = distance(middle, second_cut);
	}
	else
	{
		len22 = len2 / 2;
		advance(second_cut, len22);
		first_cut = upper_bound(first, middle, *second_cut, comp);
		len11 = distance(first, first_cut);
	}
	rotate(first_cut, middle, second_cut);
	BidirectionalIterator new_middle = first_cut;
	advance(new_middle, len22);
	__inplace_merge(first, first_cut, new_middle, len11, len22, comp);
	__inplace_merge(new_middle, second_cut, last, len1 - len11, len2 - len22, comp);
}

template <class BidirectionalIterator1, class BidirectionalIterator2, class Difference>
BidirectionalIterator1
__rotate_adaptive(BidirectionalIterator1 first, BidirectionalIterator1 middle,
                  BidirectionalIterator1 last, Difference len1, Difference len2,
                  BidirectionalIterator2 buffer, Difference buffer_size)
{
	BidirectionalIterator2 buffer_end;
	if (len1 > len2 && len2 <= buffer_size)
	{
		buffer_end = copy(middle, last, buffer);
		copy_backward(first, middle, last);
		return copy(buffer, buffer_end, first);
	} else if (len1 <= buffer_size)
	{
		buffer_end = copy(first, middle, buffer);
		copy(middle, last, first);
		return copy_backward(buffer, buffer_end, last);
	}
	rotate(first, middle, last);
	advance(first, len2);
	return first;
}

template <class BidirectionalIterator1, class BidirectionalIterator2,
          class BidirectionalIterator3>
BidirectionalIterator3
__merge_backward(BidirectionalIterator1 first1, BidirectionalIterator1 last1,
                 BidirectionalIterator2 first2, BidirectionalIterator2 last2,
                 BidirectionalIterator3 result)
{
	if (first1 == last1)
		return copy_backward(first2, last2, result);
	if (first2 == last2)
		return copy_backward(first1, last1, result);
	--last1;
	--last2;
	while (true)
	{
		if (*last2 < *last1)
		{
			*--result = *last1;
			if (first1 == last1)
				return copy_backward(first2, ++last2, result);
			--last1;
		} else
		{
			*--result = *last2;
			if (first2 == last2)
				return copy_backward(first1, ++last1, result);
			--last2;
		}
	}
}

template <class BidirectionalIterator1, class BidirectionalIterator2,
          class BidirectionalIterator3, class Compare>
BidirectionalIterator3
__merge_backward(BidirectionalIterator1 first1, BidirectionalIterator1 last1,
                 BidirectionalIterator2 first2, BidirectionalIterator2 last2,
                 BidirectionalIterator3 result, Compare comp)
{
	if (first1 == last1)
		return copy_backward(first2, last2, result);
	if (first2 == last2)
		return copy_backward(first1, last1, result);
	--last1;
	--last2;
	while (true)
	{
		if (comp(*last2, *last1))
		{
			*--result = *last1;
			if (first1 == last1)
				return copy_backward(first2, ++last2, result);
			--last1;
		} else
		{
			*--result = *last2;
			if (first2 == last2)
				return copy_backward(first1, ++last1, result);
			--last2;
		}
	}
}

template <class BidirectionalIterator, class Difference, class Pointer>
void
__inplace_merge(BidirectionalIterator first, BidirectionalIterator middle,
                BidirectionalIterator last, Difference len1, Difference len2,
                Pointer buffer, Difference buffer_size)
{
	if (len1 <= len2 && len1 <= buffer_size)
	{
		Pointer end_buffer = copy(first, middle, buffer);
		merge(buffer, end_buffer, middle, last, first);
	} else if (len2 <= buffer_size)
	{
		Pointer end_buffer = copy(middle, last, buffer);
		__merge_backward(first, middle, buffer, end_buffer, last);
	} else
	{
		BidirectionalIterator first_cut = first;
		BidirectionalIterator second_cut = middle;
		Difference len11;
		Difference len22;
		if (len1 > len2)
		{
			len11 = len1 / 2;
			advance(first_cut, len11);
			second_cut = lower_bound(middle, last, *first_cut);
			len22 = distance(middle, second_cut);
		} else
		{
			len22 = len2 / 2;
			advance(second_cut, len22);
			first_cut = upper_bound(first, middle, *second_cut);
			len11 = distance(first, first_cut);
		}
		BidirectionalIterator new_middle = __rotate_adaptive(first_cut, middle, second_cut,
			len1 - len11, len22, buffer, buffer_size);
		__inplace_merge(first, first_cut, new_middle, len11, len22, buffer, buffer_size);
		__inplace_merge(new_middle, second_cut, last, len1 - len11, len2 - len22, buffer, buffer_size);
	}
}

template <class BidirectionalIterator, class Difference, class Pointer, class Compare>
void
__inplace_merge(BidirectionalIterator first, BidirectionalIterator middle,
                BidirectionalIterator last, Difference len1, Difference len2,
                Pointer buffer, Difference buffer_size, Compare comp)
{
	if (len1 <= len2 && len1 <= buffer_size)
	{
		Pointer end_buffer = copy(first, middle, buffer);
		merge(buffer, end_buffer, middle, last, first, comp);
	} else if (len2 <= buffer_size)
	{
		Pointer end_buffer = copy(middle, last, buffer);
		__merge_backward(first, middle, buffer, end_buffer, last, comp);
	} else
	{
		BidirectionalIterator first_cut = first;
		BidirectionalIterator second_cut = middle;
		Difference len11;
		Difference len22;
		if (len1 > len2)
		{
			len11 = len1 / 2;
			advance(first_cut, len11);
			second_cut = lower_bound(middle, last, *first_cut, comp);
			len22 = distance(middle, second_cut);
		} else
		{
			len22 = len2 / 2;
			advance(second_cut, len22);
			first_cut = upper_bound(first, middle, *second_cut, comp);
			len11 = distance(first, first_cut);
		}
		BidirectionalIterator new_middle = __rotate_adaptive(first_cut, middle, second_cut,
			len1 - len11, len22, buffer, buffer_size);
		__inplace_merge(first, first_cut, new_middle, len11, len22, buffer, buffer_size, comp);
		__inplace_merge(new_middle, second_cut, last, len1-len11, len2-len22, buffer, buffer_size, comp);
	}
}

template <class BidirectionalIterator>
void
inplace_merge(BidirectionalIterator first, BidirectionalIterator middle,
              BidirectionalIterator last)
{
	typedef typename iterator_traits<BidirectionalIterator>::difference_type Difference;
	typedef typename iterator_traits<BidirectionalIterator>::value_type Value;
	if (first == middle || middle == last)
		return;
	Difference len1 = distance(first, middle);
	Difference len2 = distance(middle, last);
	_TempVec<Value> buf(len1 + len2, *first);
	if (buf.size() == 0)
		__inplace_merge(first, middle, last, len1, len2);
	else
		__inplace_merge(first, middle, last, len1, len2, buf.begin(), buf.size());
}

template <class BidirectionalIterator, class Compare>
void
inplace_merge(BidirectionalIterator first, BidirectionalIterator middle,
              BidirectionalIterator last, Compare comp)
{
	typedef typename iterator_traits<BidirectionalIterator>::difference_type Difference;
	typedef typename iterator_traits<BidirectionalIterator>::value_type Value;
	if (first == middle || middle == last)
		return;
	Difference len1 = distance(first, middle);
	Difference len2 = distance(middle, last);
	_TempVec<Value> buf(len1 + len2, *first);
	if (buf.size() == 0)
		__inplace_merge(first, middle, last, len1, len2, comp);
	else
		__inplace_merge(first, middle, last, len1, len2, buf.begin(), buf.size(), comp);
}

// Section 25.3.5 -- Set operations on sorted structures

// Section 25.3.5.1 -- includes

template <class InputIterator1, class InputIterator2>
bool
includes(InputIterator1 first1, InputIterator1 last1,
         InputIterator2 first2, InputIterator2 last2)
{
	while (first1 != last1 && first2 != last2)
	{
		if (*first2 < *first1)
			return false;
		else if (*first1 < *first2) 
			++first1;
		else
		{
			++first1;
			++first2;
		}
	}
	return first2 == last2;
}

template <class InputIterator1, class InputIterator2, class Compare>
bool
includes(InputIterator1 first1, InputIterator1 last1,
         InputIterator2 first2, InputIterator2 last2, Compare comp)
{
	while (first1 != last1 && first2 != last2)
	{
		if (comp (*first2, *first1))
			return false;
		else if (comp (*first1, *first2)) 
			++first1;
		else
		{
			++first1;
			++first2;
		}
	}
	return first2 == last2;
}

// Section 25.3.5.2 -- set union

template <class InputIterator1, class InputIterator2, class OutputIterator>
OutputIterator
set_union(InputIterator1 first1, InputIterator1 last1,
          InputIterator2 first2, InputIterator2 last2,
          OutputIterator result)
{
	for (; first1 != last1 && first2 != last2; ++result)
	{
		if (*first1 < *first2)
		{
			*result = *first1;
			++first1;
		}
		else if (*first2 < *first1)
		{
			*result = *first2;
			++first2;
		}
		else
		{
			*result = *first1;
			++first1;
			++first2;
		}
	}
	if (first2 == last2)
		return copy(first1, last1, result);
	return copy(first2, last2, result);
}

template <class InputIterator1, class InputIterator2, class OutputIterator,
          class Compare>
OutputIterator
set_union(InputIterator1 first1, InputIterator1 last1,
          InputIterator2 first2, InputIterator2 last2,
          OutputIterator result, Compare comp)
{
	for (; first1 != last1 && first2 != last2; ++result)
	{
		if (comp(*first1, *first2))
		{
			*result = *first1;
			++first1;
		}
		else if (comp(*first2, *first1))
		{
			*result = *first2;
			++first2;
		}
		else
		{
			*result = *first1;
			++first1;
			++first2;
		}
	}
	if (first2 == last2)
		return copy(first1, last1, result);
	return copy(first2, last2, result);
}

// Section 25.3.5.3 -- set intersection

template <class InputIterator1, class InputIterator2, class OutputIterator>
OutputIterator
set_intersection(InputIterator1 first1, InputIterator1 last1,
                 InputIterator2 first2, InputIterator2 last2,
                 OutputIterator result)
{
	while (first1 != last1 && first2 != last2)
	{
		if (*first1 < *first2)
			++first1;
		else if (*first2 < *first1)
			++first2;
		else
		{
			*result = *first1;
			++result;
			++first1;
			++first2;
		}
	}
	return result;
}

template <class InputIterator1, class InputIterator2, class OutputIterator,
          class Compare>
OutputIterator
set_intersection(InputIterator1 first1, InputIterator1 last1,
                 InputIterator2 first2, InputIterator2 last2,
                 OutputIterator result, Compare comp)
{
	while (first1 != last1 && first2 != last2)
	{
		if (comp(*first1, *first2))
			++first1;
		else if (comp(*first2, *first1))
			++first2;
		else
		{
			*result = *first1;
			++result;
			++first1;
			++first2;
		}
	}
	return result;
}

// Section 25.3.5.4 -- set difference

template <class InputIterator1, class InputIterator2, class OutputIterator>
OutputIterator
set_difference(InputIterator1 first1, InputIterator1 last1,
               InputIterator2 first2, InputIterator2 last2,
               OutputIterator result)
{
	while (first1 != last1 && first2 != last2)
	{
		if (*first1 < *first2)
		{
			*result = *first1;
			++result;
			++first1;
		}
		else if (*first2 < *first1)
			++first2;
		else
		{
			++first1;
			++first2;
		}
	}
	return copy(first1, last1, result);
}

template <class InputIterator1, class InputIterator2, class OutputIterator,
          class Compare>
OutputIterator
set_difference(InputIterator1 first1, InputIterator1 last1,
               InputIterator2 first2, InputIterator2 last2, 
               OutputIterator result, Compare comp)
{
	while (first1 != last1 && first2 != last2)
	{
		if (comp(*first1, *first2))
		{
			*result = *first1;
			++result;
			++first1;
		}
		else if (comp(*first2, *first1))
			++first2;
		else
		{
			++first1;
			++first2;
		}
	}
	return copy(first1, last1, result);
}

// Section 25.3.5.5 -- set symmetric difference

template <class InputIterator1, class InputIterator2, class OutputIterator>
OutputIterator
set_symmetric_difference(InputIterator1 first1, InputIterator1 last1,
                         InputIterator2 first2, InputIterator2 last2,
                         OutputIterator result)
{
	while (first1 != last1 && first2 != last2)
	{
		if (*first1 < *first2)
		{
			*result = *first1;
			++result;
			++first1;
		}
		else if (*first2 < *first1)
		{
			*result = *first2;
			++result;
			++first2;
		}
		else
		{
			++first1;
			++first2;
		}
	}
	if (first2 == last2)
		return copy(first1, last1, result);
	return copy(first2, last2, result);
}

template <class InputIterator1, class InputIterator2, class OutputIterator,
          class Compare>
OutputIterator
set_symmetric_difference(InputIterator1 first1, InputIterator1 last1,
                         InputIterator2 first2, InputIterator2 last2,
                         OutputIterator result, Compare comp)
{
	while (first1 != last1 && first2 != last2)
	{
		if (comp(*first1, *first2))
		{
			*result = *first1;
			++result;
			++first1;
		}
		else if (comp(*first2, *first1))
		{
			*result = *first2;
			++result;
			++first2;
		}
		else
		{
			++first1;
			++first2;
		}
	}
	if (first2 == last2)
		return copy(first1, last1, result);
	return copy(first2, last2, result);
}

// Section 25.3.6 -- Heap operations
// Section 25.3.6.1 -- push_heap -- in heap.h
// Section 25.3.6.2 -- pop_heap  -- in heap.h
// Section 25.3.6.3 -- make_heap -- in heap.h
// Section 25.3.6.4 -- sort_heap -- in heap.h

// Section 25.3.7 -- Minimum and Maximum

// Section 25.3.7.1 -- min  -- in algobase.h
// Section 25.3.7.2 -- max  -- in algobase.h

// Section 25.3.7.3 -- max_element

template <class ForwardIterator>
inline
ForwardIterator
max_element(ForwardIterator first, ForwardIterator last)
{
	if (first == last)
		return first;
	ForwardIterator result = first;
	while (++first != last) 
		if (*result < *first)
			result = first;
	return result;
}

template <class ForwardIterator, class Compare>
inline
ForwardIterator
max_element(ForwardIterator first, ForwardIterator last, Compare comp)
{
	if (first == last)
		return first;
	ForwardIterator result = first;
	while (++first != last) 
		if (comp(*result, *first))
			result = first;
	return result;
}

// Section 25.3.7.4 -- min_element

template <class ForwardIterator>
inline
ForwardIterator
min_element(ForwardIterator first, ForwardIterator last)
{
	if (first == last)
		return first;
	ForwardIterator result = first;
	while (++first != last) 
		if (*first < *result)
			result = first;
	return result;
}

template <class ForwardIterator, class Compare>
inline
ForwardIterator
min_element(ForwardIterator first, ForwardIterator last, Compare comp)
{
	if (first == last)
		return first;
	ForwardIterator result = first;
	while (++first != last) 
		if (comp(*first, *result))
			result = first;
	return result;
}

// Section 25.3.8 -- Lexicographical comparison -- in algobase.h

// Section 25.3.9 -- Permutation generators

// Section 25.3.9.1 -- next permutation

template <class BidirectionalIterator>
bool
next_permutation(BidirectionalIterator first, BidirectionalIterator last)
{
	if (first == last)
		return false;
	BidirectionalIterator i = first;
	++i;
	if (i == last)
		return false;
	i = last;
	--i;
	while (true)
	{
		BidirectionalIterator ii = i;
		--i;
		if (*i < *ii)
		{
			BidirectionalIterator j = last;
			--j;
			while (!(*i < *j))
				--j;
			iter_swap(i, j);
			reverse(ii, last);
			return true;
		}
		if (i == first)
		{
			reverse(first, last);
			return false;
		}
	}
}

template <class BidirectionalIterator, class Compare>
bool
next_permutation(BidirectionalIterator first, BidirectionalIterator last, Compare comp)
{
	if (first == last)
		return false;
	BidirectionalIterator i = first;
	++i;
	if (i == last)
		return false;
	i = last;
	--i;
	while (true)
	{
		BidirectionalIterator ii = i;
		--i;
		if (comp(*i, *ii))
		{
			BidirectionalIterator j = last;
			--j;
			while (!comp(*i, *j))
				--j;
			iter_swap(i, j);
			reverse(ii, last);
			return true;
		}
		if (i == first)
		{
			reverse(first, last);
			return false;
		}
	}
}

// Section 25.3.9.2 -- previous permutation

template <class BidirectionalIterator>
bool
prev_permutation(BidirectionalIterator first, BidirectionalIterator last)
{
	if (first == last)
		return false;
	BidirectionalIterator i = first;
	++i;
	if (i == last)
		return false;
	i = last;
	--i;
	while (true)
	{
		BidirectionalIterator ii = i;
		--i;
		if (*ii < *i)
		{
			BidirectionalIterator j = last;
			--j;
			while (!(*j < *i))
				--j;
			iter_swap(i, j);
			reverse(ii, last);
			return true;
		}
		if (i == first)
		{
			reverse(first, last);
			return false;
		}
	}
}

template <class BidirectionalIterator, class Compare>
bool
prev_permutation(BidirectionalIterator first, BidirectionalIterator last, Compare comp)
{
	if (first == last)
		return false;
	BidirectionalIterator i = first;
	++i;
	if (i == last)
		return false;
	i = last;
	--i;
	while (true)
	{
		BidirectionalIterator ii = i;
		--i;
		if (comp(*ii, *i))
		{
			BidirectionalIterator j = last;
			--j;
			while (!comp(*j, *i))
				--j;
			iter_swap(i, j);
			reverse(ii, last);
			return true;
		}
		if (i == first)
		{
			reverse(first, last);
			return false;
		}
	}
}

#ifdef MSIPL_USING_NAMESPACE
	} // namespace std 
#endif

#if defined(__CFM68K__) && !defined(__USING_STATIC_LIBS__)
	#pragma import reset
#endif
#pragma options align=reset

#endif // RC_INVOKED

#endif /* MSIPL_ALGORITHM_H */

// hh 971220 fixed MOD_INCLUDE
// hh 971221  filename changed from algorithm.h
// hh 971221  include guards given standard compliant name
// hh 971221 added align and import pragmas
// hh 971221 expanded namespace macro
// hh 971221 added using namespace std::rel_ops;
// hh 971230 added RC_INVOKED wrapper
// hh 980520 Changed return on generate_n from OutputIterator to void
// hh 980520 Simplified unique_copy (but kept same basic algorithm)
// hh 980520 Rewrote reverse (used example from standard)
// hh 980520  Did analysis of the 3 rotate algorithms (forward, bidirect, and random)
//            The forward and rand access iterator versions have the same efficiency.
//            The bidirectional version is more expensive.
//            Simplifying the whole thing down to forward iterators.
// hh 980902 #ifdef'd out exception code when ndef MSIPL_EXCEPT
// hh 980911 unique_copy did not work for output iterators
