//  algorithm : headerfile for the free standard C++ library
//  
//  Copyright (C) 1999 by the free standard C++ Library Team
//                        see AUTHORS for more details
//
//  Homepage : http://www.inf.fu-berlin.de/~mkrueger/fscl/
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Library General Public
//  License as published by the Free Software Foundation; either	
//  version 2 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Library General Public License for more details.
//  You should have received a copy of the GNU Library General Public
//  License along with this library; if not, write to the Free
//  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
//  version : 0.1 last modified : 17.09.99

/*
 * some parts of this file came from another file that contained
 * following restriction :
 *
 * 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.
 *
 */

#ifndef __CPP_ALGORITHM
#define __CPP_ALGORITHM

#include<cstddef>
#include<new>

#include<cpp_extensions>
#include<iterator>
#include<functional>
#include<utility>

namespace std {

	// NON STANDARD FUNCTION gcd : returns greatest common divisor of u and v
	// change - to % for higher performance
	// (I get floating point exceptions with %)
	template<class T>
	T gcd(T u, T v)
	{
		while (0 < u)
		{
			if (u < v)
				v -= u;
			else
				u -= v;
		}
		return v;
	}
	
	
	/////////////////////////////////////////////////

	// 25.1, non-modifying sequence operations:
	template<class InputIterator, class Function>
	Function for_each(InputIterator first, InputIterator last, Function f)
	{
		while (first !=  last)
			f(*first++);
		return f;
	}	
	
	template<class InputIterator, class T>
	inline InputIterator find(InputIterator first, InputIterator last, const T &value)
	{
		return find_if(first, last, bind2nd(equal_to<typename iterator_traits<InputIterator>::value_type>(), value));
	}
	
	template<class InputIterator, class Predicate>
	InputIterator find_if(InputIterator first, InputIterator last, Predicate pred)
	{
		while(first != last && !pred(*first))
			++first;
		return first;
	}

	template<class ForwardIterator1, class ForwardIterator2>
	inline ForwardIterator1 find_end(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2)
	{
		return find_end(first1, last1, first2, last2, equal_to<typename iterator_traits<ForwardIterator1>::value_type>());
	}

	template<class ForwardIterator1, class ForwardIterator2, class BinaryPredicate>
	ForwardIterator1 find_end(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, BinaryPredicate pred)
	{
		if (first2 == last2)
			return last1;
		ForwardIterator1 result = last1;
		while (1) {
			ForwardIterator1 new_result = search(first1, last1, first2, last2, comp);
			if (new_result == last1)
				return result;
			result = new_result;
			first1 = new_result;
			++first1;
		}
	}

	template<class ForwardIterator1, class ForwardIterator2>
	inline ForwardIterator1 find_first_of(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2)
	{
		return find_first_of(first1, last1, first2, last2, equal_to<typename iterator_traits<ForwardIterator1>::value_type>());
	}

	template<class ForwardIterator1, class ForwardIterator2, class BinaryPredicate>
	ForwardIterator1 find_first_of(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, BinaryPredicate pred)
	{
		while(first1 != last1) {
			for (ForwardIterator1 i = first2; i != last2; ++i)
				if (comp(*first1, *i))
					return first1;
			++first1;
		}
		return last1;
	}

	template<class ForwardIterator>
	inline ForwardIterator adjacent_find(ForwardIterator first, ForwardIterator last)
	{
		return adjacent_find(first, last, equal_to<typename iterator_traits<ForwardIterator>::value_type>());
	}
	
	template<class ForwardIterator, class BinaryPredicate>
	ForwardIterator adjacent_find(ForwardIterator first, ForwardIterator last, BinaryPredicate pred)
	{
		if (first == last)
			return last;
		ForwardIterator next = first;
		while(++next != last) {
			if (pred(*first, *next))
				return first;
			first = next;
		}
		return last;
	}

	template<class InputIterator, class T>
	inline typename iterator_traits<InputIterator>::difference_type count(InputIterator first, InputIterator last, const T &value)
	{
		return count_if(first,last, bind2nd(equal_to<typename iterator_traits<InputIterator>::value_type>(), value));				
	}

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

	template<class InputIterator1, class InputIterator2>
	inline pair<InputIterator1, InputIterator2> mismatch(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2)
	{
		return mismatch(first1,last1, first2, equal_to<typename iterator_traits<InputIterator1>::value_type>());
	}
	
	template<class InputIterator1, class InputIterator2, class BinaryPredicate>
	pair<InputIterator1, InputIterator2> mismatch(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, BinaryPredicate pred)
	{
		while (first != last && pred(*first++, *first2++)) ;

		return pair<InputIterator1, InputIterator2>(first, first2);
	}

	template<class InputIterator1, class InputIterator2>
	inline bool equal(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2)
	{
		return equal(first1,last1, first2, equal_to<typename iterator_traits<InputIterator1>::value_type>());
	}

	template<class InputIterator1, class InputIterator2, class BinaryPredicate>
	bool equal(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, BinaryPredicate pred)
	{
		while (first1 != last1 && pred(*first1++, *first2++)) ;
		return first1 == last1;
	}	

	template<class ForwardIterator1, class ForwardIterator2>
	inline ForwardIterator1 search(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2)
	{
		return search(first1, last1, first2, last2, equal_to<typename iterator_traits<ForwardIterator1>::value_type>());
	}

	template<class ForwardIterator1, class ForwardIterator2, class BinaryPredicate>
	ForwardIterator1 search(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, BinaryPredicate pred)
	{
		if (first1 == last1 || first2 == last2)
			return first1;

		if (last2 - first2 == 1)
			return find_if(first, last, bind2nd(pred, *first2));
		
		while (1) {
			first1 = find_if(first,last, bind2nd(pred, *first2));
			
			if (first1 == last1)
				return last1;
			
			if (equal(first2, last2, first1))
				return first1;
		}
		
	}	

	template<class ForwardIterator, class Size, class T>
	inline ForwardIterator search_n(ForwardIterator first, ForwardIterator last, Size count, const T& value)
	{
		return search(first, last, count, value, equal_to<typename iterator_traits<ForwardIterator>::value_type>());		
	}
	
	template<class ForwardIterator, class Size, class T, class BinaryPredicate>
	ForwardIterator search_n(ForwardIterator first, ForwardIterator last, Size count, const T &value, BinaryPredicate pred)
	{
		if (count <= 0)
			return first;
		
		while (1) {			
			first = find_if(first,last, bind2nd(pred, value));
			
			if (first == last)
				return last;

			Size n = 0;
			for (ForwardIterator i = first; i <= first + count;i++, n++)  
				if ( i == last || !pred(*i,value)) 
					break;
			
			if (n == count)
				return first;
		}
	}
	// 25.2 modifying sequence operations:
	// 25.2.1, copy :	
	template<class InputIterator, class OutputIterator>
	OutputIterator copy(InputIterator first, InputIterator last, OutputIterator result)
	{
		while (first != last)
			*result++ = *first++;
		return result;
	}

	template<class BidirectionalIterator1, class BidirectionalIterator2>
	BidirectionalIterator2 copy_backward(BidirectionalIterator1 first, BidirectionalIterator1 last, BidirectionalIterator2 result)
	{
		while (first != last)
			*--result = *--end;
		return result;
	}

	// 25.2.2, swap : 
	template<class T> 
	inline void swap(T &a, T &b)
	{
		T tmp = a;
		a = b;
		b = a;
	}
	
	template<class ForwardIterator1, class ForwardIterator2>
	ForwardIterator2 swap_ranges(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2)
	{
		while (first1 != last1) 
			iter_swap(first1++, first2++);
		return first2;
	}

	template<class ForwardIterator1, class ForwardIterator2>
	inline void iter_swap(ForwardIterator1 a, ForwardIterator2 b)
	{
		typename iterator_traits<ForwardIterator1>::value_type tmp = *a;
		*a = *b;
		*b = *a;
	}

	template<class InputIterator1, class InputIterator2, class OutputIterator, class BinaryOperation>
	OutputIterator transform(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, OutputIterator result, BinaryOperation binary_op)
	{
		while (first != last)
			*result++ = binary_op(*first++, *first2++);
		return result;
	}
	
	template<class InputIterator, class OutputIterator, class UnaryOperation>
	OutputIterator transform(InputIterator first, InputIterator last, OutputIterator result, UnaryOperation op)
	{
		while (first != last)
			*result++ = op(*first++);
		return result;
	}
	
	template<class ForwardIterator, class T>
	inline void replace(ForwardIterator first, ForwardIterator last, const T &old_value, const T &new_value)
	{
		replace_if(first,last, bind2nd(equal_to<typename iterator_traits<ForwardIterator>::value_type>(), old_value), new_value);
	}
	
	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;
	}

	template<class InputIterator, class OutputIterator, class T>
	inline OutputIterator replace_copy(InputIterator first, InputIterator last, OutputIterator result, const T& old_value, const T& new_value)
	{
		return replace_copy(first,last, result, bind2nd(equal_to<typename iterator_traits<InputIterator>::value_type>(), old_value), new_value);
	}

	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;
			++first;
		}
		return result;
	}

	template<class ForwardIterator, class T>
	inline void fill(ForwardIterator first, ForwardIterator last, const T &value)
	{
		while (first != last)
			*(first++) = value;
	}

	template<class OutputIterator, class Size, class T>
	void fill_n(OutputIterator first, Size n, const T &value)
	{
		while (n--)
			*(first++) = value;
	}
	
	template<class ForwardIterator, class Generator>
	void generate(ForwardIterator first, ForwardIterator last, Generator gen)
	{
		while (first != last)
			*(first++) = gen();
	}

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

	template<class ForwardIterator, class T>
	inline ForwardIterator remove(ForwardIterator first, ForwardIterator last, const T& value)
	{
		return remove_if(first,last, bind2nd(equal_to<typename iterator_traits<ForwardIterator>::value_type>(), old_value), value);		
	}

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

	template<class InputIterator, class OutputIterator, class T>
	inline OutputIterator remove_copy(InputIterator first, InputIterator last, OutputIterator result, const T& value)
	{
		return remove_copy_if(first,last, result, bind2nd(equal_to<typename iterator_traits<InputIterator>::value_type>(), value));
	}

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

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

	template<class InputIterator, class OutputIterator>
	inline OutputIterator unique_copy(InputIterator first, InputIterator last, OutputIterator result)
	{
		return unique_copy(first, last, result, equal_to<typename iterator_traits<InputIterator>::value_type>());
	}

	template<class InputIterator, class OutputIterator, class BinaryPredicate>
	OutputIterator unique_copy(InputIterator first, InputIterator last, OutputIterator result, BinaryPredicate pred)
	{
		*result = *first;
		while (++first != last) 
			if (!pred(*result, *first)) 
				*++result = *first;				
		return ++result;
	}

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

	template<class ForwardIterator>
	void rotate(ForwardIterator first, ForwardIterator middle, ForwardIterator last)
	{
		if (first == middle)
			return last;
		if (last  == middle)
			return first;
		ForwardIterator first2 = middle;
		do {
			swap(*first++, *first2++);
			if (first == middle)
				middle = first2;
		} while (first2 != last);
		ForwardIterator new_middle = first;
		first2 = middle;
		while (first2 != last) {
			swap (*first++, *first2++);
			if (first == middle)
				middle = first2;
			else if (first2 == last)
				first2 = middle;
		}
		return new_middle;
	}

	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));
	}

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

	template<class BidirectionalIterator, class Predicate>
	BidirectionalIterator partition(BidirectionalIterator first, BidirectionalIterator last, Predicate pred)
	{
		if (first == last) 
			return first;
		while (pred(*first))
			if (++first == last) 
				return first;

		BidirectionalIterator next = first;

		while (++next != last)
			if (pred(*next)) {
				swap(*first, *next);
				++first;
			}
		return first;
	}

	template<class BidirectionalIterator, class Predicate>
	BidirectionalIterator stable_partition(BidirectionalIterator first, BidirectionalIterator last, Predicate pred)
	{
		if (last - first == 1)
			return pred(*first) ? last : first;
		BidirectionalIterator middle = first;
		advance(middle, (last - first) / 2);		
		return rotate(stable_partition(first, middle, red), middle, stable_partition(middle, last, pred));
	}
	// 25.3 sorting and related operations:
	// 25.3.1 sorting:
	template<class RandomAccessIterator>
	inline void sort(RandomAccessIterator first, RandomAccessIterator last)
	{
		sort(first, last, less<typename iterator_traits<RandomAccessIterator>::value_type>());		
	}
	
	template<class RandomAccessIterator, class Compare>
	void sort(RandomAccessIterator first, RandomAccessIterator last, Compare comp)
	{
	}
	
	template<class RandomAccessIterator>
	inline void stable_sort(RandomAccessIterator first, RandomAccessIterator last)
	{
		stable_sort(first, last, less<typename iterator_traits<RandomAccessIterator>::value_type>());
	}

	template<class RandomAccessIterator, class Compare>
	void stable_sort(RandomAccessIterator first, RandomAccessIterator last, Compare comp)
	{
	}

	template<class RandomAccessIterator>
	inline void partial_sort(RandomAccessIterator first, RandomAccessIterator middle, RandomAccessIterator last)
	{
		partial_sort(first, middle, last, less<typename iterator_traits<RandomAccessIterator>::value_type>());
	}

	template<class RandomAccessIterator, class Compare>
	void partial_sort(RandomAccessIterator first, RandomAccessIterator middle, RandomAccessIterator last, Compare comp)
	{
	}

	template<class InputIterator, class RandomAccessIterator>
	inline RandomAccessIterator partial_sort_copy(InputIterator first, InputIterator last, RandomAccessIterator result_first, RandomAccessIterator result_last)
	{
		partial_sort_copy(first, last, result_first, result_last, less<typename iterator_traits<RandomAccessIterator>::value_type>());
	}

	template<class InputIterator, class RandomAccessIterator, class Compare>
	RandomAccessIterator partial_sort_copy(InputIterator first, InputIterator last, RandomAccessIterator result_first, RandomAccessIterator result_last, Compare comp)
	{
	}

	template<class RandomAccessIterator>
	inline void nth_element(RandomAccessIterator first, RandomAccessIterator nth, RandomAccessIterator last)
	{
		nth_element(first, nth, last, less<typename iterator_traits<RandomAccessIterator>::value_type>());
	}

	template<class RandomAccessIterator, class Compare>
	void nth_element(RandomAccessIterator first, RandomAccessIterator nth, RandomAccessIterator last, Compare comp)
	{
	}
	
	// 25.3.3 binary search:
	template<class ForwardIterator, class T>
	inline ForwardIterator lower_bound(ForwardIterator first, ForwardIterator last, const T &value)
	{
		return lower_bound(first, last, value, less<typename iterator_traits<ForwardIterator>::value_type>());
	}

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

	template<class ForwardIterator, class T>
	inline ForwardIterator upper_bound(ForwardIterator first, ForwardIterator last, const T& value)
	{
		return upper_bound(first, last, value, less<typename iterator_traits<ForwardIterator>::value_type>());		
	}

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

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

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

	template<class ForwardIterator, class T>
	inline bool binary_search(ForwardIterator first, ForwardIterator last, const T &value)	
	{
		return binary_search(first, last, value, less<typename iterator_traits<ForwardIterator>::value_type>());
	}

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

	template<class InputIterator1, class InputIterator2, class OutputIterator>
	inline OutputIterator merge(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result)
	{
		return merge(first1, last1, first2, last2, result, less<typename iterator_traits<InputIterator1>::value_type>());
	}

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

	template<class BidirectionalIterator>
	inline void inplace_merge(BidirectionalIterator first, BidirectionalIterator middle, BidirectionalIterator last)
	{
		inplace_merge(first, middle, last, less<typename iterator_traits<BidirectionalIterator>::value_type>());
	}

	template<class BidirectionalIterator, class Compare>
	void inplace_merge(BidirectionalIterator first, BidirectionalIterator middle, BidirectionalIterator last, Compare comp)
	{
	}

	template<class InputIterator1, class InputIterator2>
	inline bool includes(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2)
	{
		return includes(first1, last1, first2, last2, less<typename iterator_traits<InputIterator1>::value_type>());
	}

	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;
	}

	template<class InputIterator1, class InputIterator2, class OutputIterator>
	inline OutputIterator set_union(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result)
	{
		return set_union(first1, last1, first2, last2, result, less<typename iterator_traits<InputIterator1>::value_type>());
	}

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

	template<class InputIterator1, class InputIterator2, class OutputIterator>
	inline OutputIterator set_intersection(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result)
	{
		return set_intersection(first1, last1, first2, last2, result, less<typename iterator_traits<InputIterator1>::value_type>());		
	}

	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;
				++first1;
				++first2;
				++result;
			}
		return result;
	}

	template<class InputIterator1, class InputIterator2, class OutputIterator>
	inline OutputIterator set_difference(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result)
	{
		return set_difference(first1, last1, first2, last2, result, less<typename iterator_traits<InputIterator1>::value_type>());		
	}

	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;
				++first1;
				++result;
			}
			else if (comp(*first2, *first1))
				++first2;
			else {
				++first1;
				++first2;
			}
		return copy(first1, last1, result);
	}

	template<class InputIterator1, class InputIterator2, class OutputIterator>
	inline OutputIterator set_symmetric_difference(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result)
	{
		return set_symmetric_difference(first1, last1, first2, last2, result, less<typename iterator_traits<InputIterator1>::value_type>());				
	}

	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;
				++first1;
				++result;
			}
			else if (comp(*first2, *first1)) {
				*result = *first2;
				++first2;
				++result;
			} else {
				++first1;
				++first2;
			}
		return copy(first2, last2, copy(first1, last1, result));
	}

	// 25.3.6, heap operations:


	template<class RandomAccessIterator>
	inline void push_heap(RandomAccessIterator first, RandomAccessIterator last)
	{
		push_heap(first, last, less<typename iterator_traits<RandomAccessIterator>::value_type>());
	}
	
	template<class RandomAccessIterator, class Compare>
	void push_heap(RandomAccessIterator first, RandomAccessIterator last, Compare comp)
	{ /*
		typename first::value_type     v = *first;
		typename first::distance_type  j = 0, h = (last - first - 1);

		for (typename first::distance_type i = (h - 1) /2; j < h && comp(*(first + i), v); i = (h-1) /2)
			*(first + h) = *(first + i), h = i;
		*(first + h) = v; */
	}
			
	template<class RandomAccessIterator>
	inline void pop_heap(RandomAccessIterator first, RandomAccessIterator last)
	{
		pop_heap(first, last, less<typename iterator_traits<RandomAccessIterator>::value_type>());
	}
	
	template<class RandomAccessIterator, class Compare>
	void pop_heap(RandomAccessIterator first, RandomAccessIterator last, Compare comp)
	{
	}

	template<class RandomAccessIterator>
	inline void make_heap(RandomAccessIterator first, RandomAccessIterator last)
	{
		make_heap(first, last, less<typename iterator_traits<RandomAccessIterator>::value_type>());
	}
	
	template<class RandomAccessIterator, class Compare>
	void make_heap(RandomAccessIterator first, RandomAccessIterator last, Compare comp)
	{ /*
		typename first::distance_type dist = last - first;
		if (dist >= 2) {
			for (typename first::distance_type h = dist / 2; 0 < h;)
					--h, adjust_heap(first, h, dist, *(first + h), comp);
		}*/
	}

	template<class RandomAccessIterator>
	inline void sort_heap(RandomAccessIterator first, RandomAccessIterator last)
	{
		sort_heap(first, last, less<typename iterator_traits<RandomAccessIterator>::value_type>());
	}
	
	template<class RandomAccessIterator, class Compare>
	void sort_heap(RandomAccessIterator first, RandomAccessIterator last, Compare comp)
	{
		while (1 < last - first)
			pop_heap(first, last), --last;
	}
	
	// 25.3.7 minimum and maximum :
	template<class T> 
	inline const T &min(const T &a, const T &b)
	{
		return a < b ? a : b;
	}

	template<class T, class Compare>
	inline const T &min(const T &a, const T &b, Compare comp)
	{
		return comp(a, b) ? a : b;
	}

	template<class T> 
	inline const T &max(const T &a, const T &b)
	{
		return a > b ? a : b;
	}
	
	template<class T, class Compare>
	inline const T &max(const T &a, const T &b, Compare comp)
	{
		return comp(a, b) ? a : b;
	}
	
	template<class ForwardIterator>
	inline ForwardIterator min_element(ForwardIterator first, ForwardIterator last)
	{
		return min_element(first, last, less<typename iterator_traits<ForwardIterator>::value_type>());
	}

	template<class ForwardIterator, class Compare>
	ForwardIterator min_element(ForwardIterator first, ForwardIterator last, Compare comp)
	{
		ForwardIterator min = first;		
		while (++first !=  last) 
			if (comp(*first, *min))
				min = first;		
		return min;
	}
	
	template<class ForwardIterator>
	inline ForwardIterator max_element(ForwardIterator first, ForwardIterator last)
	{
		return max_element(first, last, less<typename iterator_traits<ForwardIterator>::value_type>());
	}

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

	template<class InputIterator1, class InputIterator2>
	inline bool lexicographical_compare(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2)
	{
		return lexicographical_compare(first1, last1, first2, last2, less<typename iterator_traits<InputIterator1>::value_type>());
	}

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

	// 25.3.9, permutations:
	template<class BidirectionalIterator>
	inline bool next_permutation(BidirectionalIterator first, BidirectionalIterator last)
	{
		return next_permutation(first, last, less<typename iterator_traits<BidirectionalIterator>::value_type>());						
	}

	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;
		for(;;) {
			BidirectionalIterator ii = i;
			--i;
			if (comp(*i, *ii)) {
				BidirectionalIterator j = last;
				while (!comp(*i, *--j)) {
				}
				iter_swap(i, j);
				reverse(ii, last);
				return true;
			}
			if (i == first) {
				reverse(first, last);
				return false;
			}
		}
	}
	
	template<class BidirectionalIterator>
	inline bool prev_permutation(BidirectionalIterator first, BidirectionalIterator last)
	{
		return prev_permutation(first, last, less<typename iterator_traits<BidirectionalIterator>::value_type>());
	}

	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;
		for(;;) {
			BidirectionalIterator ii = i;
			--i;
			if (comp(*ii, *i)) {
				BidirectionalIterator j = last;
				while (!comp(*--j, *i)) {
				}
				iter_swap(i, j);
				reverse(ii, last);
				return true;
			}
			if (i == first) {
				reverse(first, last);
				return false;
			}
		}
	}
}
#endif
