/*	Copyright (C) 2004 Garrett A. Kajmowicz
	This file is part of the uClibc++ Library.
	This library is free software; you can redistribute it and/or
	modify it under the terms of the GNU Lesser General Public
	License as published by the Free Software Foundation; either
	version 2.1 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
	Lesser General Public License for more details.

	You should have received a copy of the GNU Lesser General Public
	License along with this library; if not, write to the Free Software
	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#include <cstdlib>
#include <iterator>
#include <utility>
#include <functional>

#ifndef __STD_HEADER_ALGORITHM
#define __STD_HEADER_ALGORITHM 1

//Elliminate any previously defined macro
#undef min
#undef max

#pragma GCC visibility push(default)

namespace std{

	// subclause _lib.alg.nonmodifying_, non-modifying sequence operations:
	template<class InputIterator, class Function> _UCXXEXPORT
		Function for_each(InputIterator first, InputIterator last, Function f)
	{
		while(first !=last){
			f(*first);
			++first;
		}
		return f;
	}


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

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

	template<class ForwardIterator1, class ForwardIterator2> _UCXXEXPORT ForwardIterator1
		find_end(ForwardIterator1 first1, ForwardIterator1 last1,
			ForwardIterator2 first2, ForwardIterator2 last2)
	{
		ForwardIterator1 retval = last1;
		while(first1 !=last1){
			ForwardIterator1 temp1(first1);
			ForwardIterator2 temp2(first2);
			while(temp2!=last2 && temp1!= last1){
				if(*temp1 != *temp2){
					break;		//Exit while loop
				}
				++temp1;
				++temp2;
				if(temp2 == last2){	//Have successfully checked the whole sequence
					retval = first1;
				}
			}
		}
		return retval;
	}

	template<class ForwardIterator1, class ForwardIterator2, class BinaryPredicate> _UCXXEXPORT
		ForwardIterator1
		find_end(ForwardIterator1 first1, ForwardIterator1 last1,
			ForwardIterator2 first2, ForwardIterator2 last2,
			BinaryPredicate pred)
	{
		ForwardIterator1 retval = last1;
		while(first1 !=last1){
			ForwardIterator1 temp1(first1);
			ForwardIterator2 temp2(first2);
			while(temp2!=last2 && temp1!= last1){
				if( ! pred(*temp1, *temp2)){
					break;		//Exit while loop
				}
				++temp1;
				++temp2;
				if(temp2 == last2){	//Have successfully checked the whole sequence
					retval = first1;
				}
			}
		}
		return retval;
	}

	template<class ForwardIterator1, class ForwardIterator2> _UCXXEXPORT
		ForwardIterator1
		find_first_of(ForwardIterator1 first1, ForwardIterator1 last1,
			ForwardIterator2 first2, ForwardIterator2 last2)
	{
		while(first1 != last1){
			ForwardIterator2 temp2(first2);
			while(temp2 != last2 ){
				if(*temp2 == first1){
					return first1;
				}
				++temp2;
			}

		}
		return last1;
	}

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

		}
		return last1;
	}

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

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

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

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

	template<class InputIterator1, class InputIterator2> _UCXXEXPORT
		pair<InputIterator1, InputIterator2>
		mismatch(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2)
	{
		while(first1 != last1){
			if(*first1 != *first2){
				break;
			}
			++first1;
			++first2;
		}

		pair<InputIterator1, InputIterator2> retval;
		retval.first = first1;
		retval.second = first2;
		return retval;
	}

	template<class InputIterator1, class InputIterator2, class BinaryPredicate> _UCXXEXPORT
		pair<InputIterator1, InputIterator2>
		mismatch(InputIterator1 first1, InputIterator1 last1,
			InputIterator2 first2, BinaryPredicate pred)
	{
		while(first1 != last1){
			if( !pred(*first1, *first2) ){
				break;
			}
			++first1;
			++first2;
		}

		pair<InputIterator1, InputIterator2> retval;
		retval.first = first1;
		retval.second = first2;
		return retval;
	}

	template<class InputIterator1, class InputIterator2> _UCXXEXPORT
		bool
		equal(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2)
	{
		while(first1 !=last1){
			if(*first1 != *first2){
				return false;
			}
			++first1;
			++first2;
		}
		return true;
	}

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

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


	template<class ForwardIterator1, class ForwardIterator2, class BinaryPredicate> _UCXXEXPORT
		ForwardIterator1
		search(ForwardIterator1 first1, ForwardIterator1 last1,
			ForwardIterator2 first2, ForwardIterator2 last2,
			BinaryPredicate pred)
	{
		while(first1 != last1){
			ForwardIterator1 temp1(first1);
			ForwardIterator2 temp2(first2);
			while(temp2 != last2 && temp1 != last1){
				if( !pred(*temp2, *temp1) ){
					break;
				}
				++temp1;
				++temp2;
				if(temp2 == last2){
					return first1;
				}
			}
			++first1;
		}
		return last1;
	}


	template<class ForwardIterator, class Size, class T> _UCXXEXPORT
		ForwardIterator
		search_n(ForwardIterator first, ForwardIterator last, Size count, const T& value)
	{
		while( first != last ){
			if(*first == value){
				ForwardIterator temp(first);
				Size i = 1;
				++first;	//Avoid doing the same comparison over again
				while(i < count && *temp == value){
					++first;
					++i;
				}
				if(i == count){
					return first;
				}
			}
			++first;
		}
		return first;
	}


	template<class ForwardIterator, class Size, class T, class BinaryPredicate> _UCXXEXPORT
		ForwardIterator
		search_n(ForwardIterator first, ForwardIterator last,
			Size count, const T& value, BinaryPredicate pred)
	{
		while( first != last ){
			if( pred(*first, value) ){
				ForwardIterator temp(first);
				Size i = 1;
				++first;	//Avoid doing the same comparison over again
				while(i < count && pred(*temp, value) ){
					++first;
					++i;
				}
				if(i == count){
					return first;
				}
			}
			++first;
		}
		return first;

	}

	// subclause _lib.alg.modifying.operations_, modifying sequence operations:

	template<class InputIterator, class OutputIterator> _UCXXEXPORT
		OutputIterator
		copy(InputIterator first, InputIterator last, OutputIterator result)
	{
		while(first != last){
			*result = *first;
			++first;
			++result;
		}
		return result;
	}

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

	template<class T> _UCXXEXPORT void swap(T& a, T& b){
		T temp(a);
		a = b;
		b = temp;
	}

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


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


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


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


	template<class ForwardIterator, class T> _UCXXEXPORT
		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> _UCXXEXPORT
		void
		replace_if(ForwardIterator first, ForwardIterator last,
			Predicate pred, const T& new_value)
	{
		while(first != last){
			if( pred(*first) ){
				*first = new_value;
			}
			++first;
		}
	}


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

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

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

	template<class OutputIterator, class Size, class T> _UCXXEXPORT
		void
		fill_n(OutputIterator first, Size n, const T& value)
	{
		while(n != 0){
			*first = value;
			--n;
			++first;
		}
	}

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

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

	template<class ForwardIterator, class T> _UCXXEXPORT
		ForwardIterator
		remove(ForwardIterator first, ForwardIterator last, const T& value)
	{
		ForwardIterator temp(first);
		while(temp !=last){
			if(*temp == value){

			}else{
				*first = *temp;
				++first;
			}
			++temp;
		}
		return first;
	}

	template<class ForwardIterator, class Predicate> _UCXXEXPORT
		ForwardIterator
		remove_if(ForwardIterator first, ForwardIterator last, Predicate pred)
	{
		ForwardIterator temp(first);
		while(temp !=last){
			if( pred(*temp) ){

			}else{
				*first = *temp;
				++first;
			}
			++temp;
		}
		return first;
	}


	template<class InputIterator, class OutputIterator, class T> _UCXXEXPORT
		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> _UCXXEXPORT
		OutputIterator
		remove_copy_if(InputIterator first, InputIterator last,
			OutputIterator result, Predicate pred)
	{
		while(first !=last){
			if( !pred(*first) ){
				*result = *first;
				++result;
			}
			++first;
		}
		return result;
	}

	template<class ForwardIterator> _UCXXEXPORT
		ForwardIterator
		unique(ForwardIterator first, ForwardIterator last)
	{
		ForwardIterator new_val(first);
		ForwardIterator old_val(first);

		while(new_val !=last){
			if(*new_val == *old_val && new_val != old_val){

			}else{
				*first = *new_val;
				old_val = new_val;
				++first;
			}
			++new_val;
		}
		return first;
	}

	template<class ForwardIterator, class BinaryPredicate> _UCXXEXPORT
		ForwardIterator
		unique(ForwardIterator first, ForwardIterator last, BinaryPredicate pred)
	{
		ForwardIterator new_val(first);
		ForwardIterator old_val(first);

		while(new_val !=last){
			if( pred(*new_val, *old_val) && new_val != old_val){

			}else{
				*first = *new_val;
				old_val = new_val;
				++first;
			}
			++new_val;
		}
		return first;
	}

	template<class InputIterator, class OutputIterator> _UCXXEXPORT
		OutputIterator
		unique_copy(InputIterator first, InputIterator last, OutputIterator result)
	{
		InputIterator temp(first);
		while(first !=last ){
			if(*first == *temp && first != temp){

			}else{
				*result = *first;
				temp = first;
				++result;
			}
			++first;
		}
		return result;
	}

	template<class InputIterator, class OutputIterator, class BinaryPredicate> _UCXXEXPORT
		OutputIterator
		unique_copy(InputIterator first, InputIterator last,
			OutputIterator result, BinaryPredicate pred)
	{
		InputIterator temp(first);
		while(first !=last ){
			if( pred(*first, *temp) && first != temp){

			}else{
				*result = *first;
				temp = first;
				++result;
			}
			++first;
		}
		return result;
	}

	template<class BidirectionalIterator> _UCXXEXPORT
		void
		reverse(BidirectionalIterator first, BidirectionalIterator last)
	{
		--last;		//Don't work with one past the end element
		while(first < last){
			iter_swap(first, last);
			++first;
			--last;
		}
	}

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

	template<class ForwardIterator> _UCXXEXPORT
		void
		rotate(ForwardIterator first, ForwardIterator middle, ForwardIterator last)
	{
		if ((first == middle) || (last  == middle)){
			return;
		}

		ForwardIterator first2 = middle;

		do {
			swap(*first, *first2);
			first++;
			first2++;
			if(first == middle){
				middle = first2;
			}
		} while(first2 != last);

		first2 = middle;

		while (first2 != last) {
			swap(*first, *first2);
			first++;
			first2++;
			if (first == middle){
				middle = first2;
			}else if (first2 == last){
				first2 = middle;
			}
		}
	}

	template<class ForwardIterator, class OutputIterator> _UCXXEXPORT
		OutputIterator
		rotate_copy(ForwardIterator first, ForwardIterator middle,
			ForwardIterator last, OutputIterator result)
	{
		ForwardIterator temp(middle);
		while(temp !=last){
			*result = *temp;
			++temp;
			++result;
		}
		while(first != middle){
			*result = *first;
			++first;
			++result;
		}
		return result;
	}


	template<class RandomAccessIterator> _UCXXEXPORT
		void
		random_shuffle(RandomAccessIterator first, RandomAccessIterator last)
	{
		--last;
		while(first != last){
			iter_swap(first, (first + (rand() % (last - first) ) ) );
			++first;
		}
	}

	template<class RandomAccessIterator, class RandomNumberGenerator> _UCXXEXPORT
		void
		random_shuffle(RandomAccessIterator first, RandomAccessIterator last,
		RandomNumberGenerator& rand)
	{
		--last;
		while(first != last){
			iter_swap(first, (first + (rand(last - first) ) ) );
			++first;
		}
	}

	// _lib.alg.partitions_, partitions:
	template<class BidirectionalIterator, class Predicate> _UCXXEXPORT BidirectionalIterator
		partition(BidirectionalIterator first, BidirectionalIterator last, Predicate pred)
	{
		return stable_partition(first, last, pred);
	}

	template<class BidirectionalIterator, class Predicate> _UCXXEXPORT BidirectionalIterator
		stable_partition(BidirectionalIterator first, BidirectionalIterator last, Predicate pred)
	{
		//first now points to the first non-desired element
		while( first != last && pred(*first) ){
			++first;
		}

		BidirectionalIterator tempb;
		BidirectionalIterator tempe = first;

		while( tempe != last ){
			//Find the next desired element
			while( !pred(*tempe) ){
				++tempe;

				//See if we should exit
				if(tempe == last){
					return first;
				}
			}

			//Rotate the element back to the begining
			tempb = tempe;
			while(tempb != first){
				iter_swap(tempb, tempb-1 );
				--tempb;
			}
			//First now has a desired element
			++first;
		}

		return first;
	}

	template<class RandomAccessIterator> _UCXXEXPORT
		void sort(RandomAccessIterator first, RandomAccessIterator last)
	{
		less<typename iterator_traits<RandomAccessIterator>::value_type> c;
		sort(first, last, c );
	}

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

	template<class RandomAccessIterator> _UCXXEXPORT
		void stable_sort(RandomAccessIterator first, RandomAccessIterator last)
	{
		less<typename iterator_traits<RandomAccessIterator>::value_type> c;
		stable_sort(first, last, c);
	}

	template<class RandomAccessIterator, class Compare> _UCXXEXPORT
		void stable_sort(RandomAccessIterator first, RandomAccessIterator last, Compare comp)
	{
		//FIXME - bubble sort
		RandomAccessIterator temp;
		--last;
		while(last - first > 0){
			temp = last;
			while(temp != first){
				if( comp( *temp, *(temp-1) ) ){
					iter_swap( temp-1, temp);
				}
				--temp;
			}
			++first;
		}
	}

	template<class RandomAccessIterator> _UCXXEXPORT
		void partial_sort(RandomAccessIterator first, RandomAccessIterator middle, RandomAccessIterator last)
	{
		less<typename iterator_traits<RandomAccessIterator>::value_type> c;
		partial_sort(first, middle, last, c);
	}
	template<class RandomAccessIterator, class Compare> _UCXXEXPORT
		void partial_sort(RandomAccessIterator first, RandomAccessIterator middle,
			RandomAccessIterator last, Compare comp)
	{
		//Fixme - partial bubble sort
		RandomAccessIterator temp;
		--last;
		while(first < middle){
			temp = last;
			while(temp != first){
				if( comp(*temp, *(temp -1 ) ) ) {
					iter_swap( temp-1, temp);
				}
				--temp;
			}
			++first;
		}
	}
	template<class InputIterator, class RandomAccessIterator> _UCXXEXPORT
		RandomAccessIterator
		partial_sort_copy(InputIterator first, InputIterator last,
			RandomAccessIterator result_first, RandomAccessIterator result_last)
	{
		less<typename iterator_traits<RandomAccessIterator>::value_type> c;
		return partial_sort_copy(first, last, result_first, result_last, c);
	}
	template<class InputIterator, class RandomAccessIterator, class Compare> _UCXXEXPORT
		RandomAccessIterator
		partial_sort_copy(InputIterator first, InputIterator last,
			RandomAccessIterator result_first, RandomAccessIterator result_last, Compare comp)
	{
		size_t output_size = last-first;
		size_t temp_size = result_last - result_first;
		if(temp_size < output_size){
			output_size = temp_size;
		}

		RandomAccessIterator middle = result_first + output_size;
		RandomAccessIterator temp = result_first;

		while(temp != middle){
			*temp = *first;
			++temp;
			++first;
		}
		sort(result_first, middle, comp);

		while( first != last){
			if( comp( *first, *(middle-1) ) ){
				*(middle-1) = *first;
				sort(result_first, middle, comp);
			}
			++first;
		}

		return middle;
	}
	template<class RandomAccessIterator> _UCXXEXPORT
		void nth_element(RandomAccessIterator first, RandomAccessIterator nth, RandomAccessIterator last)
	{
		less<typename iterator_traits<RandomAccessIterator>::value_type> c;
		nth_element(first, nth, last, c);
	}
	template<class RandomAccessIterator, class Compare> _UCXXEXPORT
		void nth_element(RandomAccessIterator first, RandomAccessIterator nth,
			RandomAccessIterator last, Compare comp)
	{
		partial_sort(first, nth, last, comp);
	}

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

	template<class ForwardIterator, class T, class Compare> _UCXXEXPORT
		ForwardIterator lower_bound(ForwardIterator first, ForwardIterator last,
			const T& value, Compare comp)
	{
		if(first == last){
			return last;
		}
		//If below or equal to the first element
		if( comp(*first, value) == false){
			return first;
		}
		ForwardIterator middle;

		//If greater than the top element
		middle = first;
		advance(middle, distance(first, last) - 1);
		if( comp(*middle, value) ){
			return last;
		}

		//Now begin the actual search for the begining
		while( distance(first, last) > 1 ){
			//Find middle
			middle = first;
			advance(middle, (distance(first, last)/2) );
			if( !comp(*middle, value) ){
				last = middle;
			}else{
				first = middle;
			}
		}

		if( !comp(*first, value) ){
			return first;
		}
		return last;
	}

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


	template<class ForwardIterator, class T, class Compare> _UCXXEXPORT
		ForwardIterator upper_bound(ForwardIterator first, ForwardIterator last,
			const T& value, Compare comp)
	{
		if(first == last){
			return last;
		}
		//If below the first element
		if( comp(value, *first) == true){
			return first;
		}

		ForwardIterator middle;

		//If greater than the top element
		middle = first;
		advance(middle, distance(first, last) - 1);
		if( comp(*middle, value) ){
			return last;
		}

		//Now begin the actual search for the end
		while( distance(first, last) > 1 ){
			//Find middle
			middle = first;
			advance(middle, (distance(first, last)/2) );
			if( comp(value, *middle) ){
				last = middle;
			}else{
				first = middle;
			}
		}

		if( comp(value, *first) ){
			return first;
		}
		return last;
	}


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

	template<class ForwardIterator, class T, class Compare> _UCXXEXPORT
		pair<ForwardIterator, ForwardIterator>
		equal_range(ForwardIterator first, ForwardIterator last, const T& value, Compare comp)
	{
		pair<ForwardIterator, ForwardIterator> retval;
		retval.first = lower_bound(first, last, value, comp);
		//Reuse retval.first in order to (possibly) save a few comparisons
		retval.second = upper_bound(retval.first, last, value, comp);
		return retval;

	}

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

	template<class ForwardIterator, class T, class Compare> _UCXXEXPORT
		bool binary_search(ForwardIterator first, ForwardIterator last,
			const T& value, Compare comp)
	{
		if( distance(first, last) == 0){
			return false;
		}

		ForwardIterator middle;

		while( distance(first, last) > 1 ){
			//Set middle between first and last
			middle = first;
			advance(middle, distance(first, last)/2 );

			if( comp(*middle, value ) == true){
				first = middle;
			}else{
				last = middle;
			}
		}

		if( !comp(*first, value) && !comp(value, *first) ){
			return true;
		}
		if( !comp(*last, value) && !comp(value, *last) ){
			return true;
		}

		return false;
	}

	// _lib.alg.merge_, merge:
	template<class InputIterator1, class InputIterator2, class OutputIterator> _UCXXEXPORT
		OutputIterator
		merge(InputIterator1 first1, InputIterator1 last1,
			InputIterator2 first2, InputIterator2 last2, OutputIterator result)
	{
		less<typename iterator_traits<InputIterator1>::value_type> c;
		return merge(first1, last1, first2, last2, result, c);
	}
	template<class InputIterator1, class InputIterator2, class OutputIterator, class Compare> _UCXXEXPORT
		OutputIterator
		merge(InputIterator1 first1, InputIterator1 last1,
			InputIterator2 first2, InputIterator2 last2, OutputIterator result, Compare comp)
	{
		while( first1 != last1 && first2 != last2){
			//If in this order so first1 elements which are equal come first
			if( comp(*first2, *first1) ){
				*result = *first2;
				++first2;
			}else{
				*result = *first1;
				++first1;
			}
			++result;
		}
		//Clean up remaining elements
		while(first1 != last1){
			*result = *first1;
			++first1;
			++result;
		}
		while(first2 != last2){
			*result = *first2;
			++first2;
			++result;
		}
		return result;
	}
	template<class BidirectionalIterator> _UCXXEXPORT
		void inplace_merge(BidirectionalIterator first,
			BidirectionalIterator middle, BidirectionalIterator last)
	{
		less<typename iterator_traits<BidirectionalIterator>::value_type> c;
		inplace_merge(first, middle, last, c);
	}
	template<class BidirectionalIterator, class Compare> _UCXXEXPORT
		void inplace_merge(BidirectionalIterator first,
			BidirectionalIterator middle, BidirectionalIterator last, Compare comp)
	{
		//FIXME - using a bubble exchange method
		while(first != middle && middle !=last){
			if( comp(*middle, *first) ){
				BidirectionalIterator temp(middle);
				while( temp != first){
					iter_swap(temp, temp-1);
					--temp;
				}
				++middle;
			}
			++first;
		}
	}

	// _lib.alg.set.operations_, set operations:
	template<class InputIterator1, class InputIterator2> _UCXXEXPORT
		bool includes(InputIterator1 first1, InputIterator1 last1,
			InputIterator2 first2, InputIterator2 last2)
	{
		less<typename iterator_traits<InputIterator1>::value_type> c;
		return includes(first1, last1, first2, last2, c );
	}

	template<class InputIterator1, class InputIterator2, class Compare> _UCXXEXPORT
		bool includes(InputIterator1 first1, InputIterator1 last1,
			InputIterator2 first2, InputIterator2 last2, Compare comp)
	{
		while(first2 != last2){
			//Advance the large set until no longer smaller than the element we are looking for
			while( comp(*first1, *first2) ){
				++first1;
				//If we are at the end of the list, we don't have the desired element
				if(first1 == last1){
					return false;
				}
			}
			//If we are past the element we want, it isn't here
			if( comp(*first2, *first1) ){
				return false;
			}
			++first2;	//Move to next element
		}
		return true;
	}

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

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

				//Elliminate duplicates
				InputIterator2 temp = first2;
				while( first1 != last1 && !comp( *temp, *first1) ){
					++first1;
				}
				while( first2 != last2 && !comp( *temp, *first2) ){
					++first2;
				}
			}else{
				*result = *first1;
					//Elliminate duplicates
				InputIterator1 temp = first1;
				while( first1 != last1 && !comp( *temp, *first1) ){
					++first1;
				}
				while( first2 != last2 && !comp( *temp, *first2) ){
					++first2;
				}
			}
			++result;
		}

		//Clean up remaining elements
		while(first1 != last1){
			*result = *first1;
			++result;
			InputIterator1 temp = first1;
			while( first1 != last1 && !comp( *temp, *first1) ){
				++first1;
			}
		}

		while(first2 != last2){
			*result = *first2;
			++result;
			InputIterator2 temp = first2;
			while( first2 != last2 && !comp( *temp, *first2) ){
				++first2;
			}
		}
		return result;
	}

	template<class InputIterator1, class InputIterator2, class OutputIterator> _UCXXEXPORT
		OutputIterator set_intersection(InputIterator1 first1, InputIterator1 last1,
			InputIterator2 first2, InputIterator2 last2, OutputIterator result)
	{
		less<typename iterator_traits<InputIterator1>::value_type> c;
		return set_intersection(first1, last1, first2, last2, result, c);
	}
	template<class InputIterator1, class InputIterator2, class OutputIterator, class Compare> _UCXXEXPORT
		OutputIterator set_intersection(InputIterator1 first1, InputIterator1 last1,
			InputIterator2 first2, InputIterator2 last2, OutputIterator result, Compare comp)
	{
		while( first1 != last1 && first2 != last2){
			if( comp(*first2, *first1) ){
				++first2;
			}else if( comp(*first1, *first2) ) {
				++first1;
			}else{
				*result = *first1;
				++result;
				InputIterator1 temp = first1;
				while( first1 != last1 && !comp( *temp, *first1) ){
					++first1;
				}
				++first2;
			}
		}
		return result;
	}
	template<class InputIterator1, class InputIterator2, class OutputIterator> _UCXXEXPORT
		OutputIterator set_difference(InputIterator1 first1, InputIterator1 last1,
			InputIterator2 first2, InputIterator2 last2, OutputIterator result)
	{
		less<typename iterator_traits<InputIterator1>::value_type> c;
		return set_difference(first1, last1, first2, last2, result, c);
	}
	template<class InputIterator1, class InputIterator2, class OutputIterator, class Compare> _UCXXEXPORT
		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;

				//Elliminate duplicates
				InputIterator1 temp = first1;
				while( first1 != last1 && !comp( *temp, *first1) ){
					++first1;
				}
			}else if( comp(*first2, *first1) ){

				//Elliminate duplicates
				InputIterator2 temp = first2;
				while( first2 != last2 && !comp( *temp, *first2) ){
					++first2;
				}

			}else{	//They are identical - skip
				//Elliminate duplicates
				InputIterator1 temp = first1;
				while( first1 != last1 && !comp( *temp, *first1) ){
					++first1;
				}
				while( first2 != last2 && !comp( *temp, *first2) ){
					++first2;
				}
			}
		}

		//Clean up remaining elements
		while(first1 != last1){
			*result = *first1;
			++result;
			InputIterator1 temp = first1;
			while( first1 != last1 && !comp( *temp, *first1) ){
				++first1;
			}
		}

		return result;
	}
	template<class InputIterator1, class InputIterator2, class OutputIterator> _UCXXEXPORT
		OutputIterator set_symmetric_difference(InputIterator1 first1, InputIterator1 last1,
			InputIterator2 first2, InputIterator2 last2, OutputIterator result)
	{
		less<typename iterator_traits<InputIterator1>::value_type> c;
		return set_symmetric_difference(first1, last1, first2, last2, result, c);
	}
	template<class InputIterator1, class InputIterator2, class OutputIterator, class Compare> _UCXXEXPORT
		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;

				//Elliminate duplicates
				InputIterator1 temp = first1;
				while( first1 != last1 && !comp( *temp, *first1) ){
					++first1;
				}
			}else if( comp(*first2, *first1) ){
				*result = *first2;
				++result;

				//Elliminate duplicates
				InputIterator2 temp = first2;
				while( first2 != last2 && !comp( *temp, *first2) ){
					++first2;
				}

			}else{	//They are identical - skip
				//Elliminate duplicates
				InputIterator1 temp = first1;
				while( first1 != last1 && !comp( *temp, *first1) ){
					++first1;
				}
				while( first2 != last2 && !comp( *temp, *first2) ){
					++first2;
				}
			}
		}

		//Clean up remaining elements
		while(first1 != last1){
			*result = *first1;
			++result;
			InputIterator1 temp = first1;
			while( first1 != last1 && !comp( *temp, *first1) ){
				++first1;
			}
		}

		while(first2 != last2){
			*result = *first2;
			++result;
			InputIterator2 temp = first2;
			while( first2 != last2 && !comp( *temp, *first2) ){
				++first2;
			}
		}

		return result;
	}

	// _lib.alg.heap.operations_, heap operations:

	template<class RandomAccessIterator> _UCXXEXPORT
		void push_heap(RandomAccessIterator first, RandomAccessIterator last)
	{
		less<typename iterator_traits<RandomAccessIterator>::value_type> c;
		push_heap(first, last, c);
	}

	template<class RandomAccessIterator, class Compare> _UCXXEXPORT
		void push_heap(RandomAccessIterator first, RandomAccessIterator last, Compare comp)
	{
		// *(last - 1) is the last element
		RandomAccessIterator begin, middle, end;
		begin = first;
		end = last - 2;
		if(last - first < 2){		//Empty heap
			return;
		}
		if ( comp(*(last-1), *end) ){	//Belongs past the end - already in place
			return;
		}
		while(end - begin > 1){
			middle = begin + ((end - begin)/2);
			if( comp(*middle, *(last-1) ) ){
				end = middle;
			}else{
				begin = middle;
			}
		}

		if( comp(*begin, *(last-1)) ){
			middle = begin;
		}else{
			middle = end;
		}

		//Now all we do is swap the elements up to the begining
		--last;

		while(last > middle){
			iter_swap(last, last-1);
			--last;
		}
	}

	template<class RandomAccessIterator> _UCXXEXPORT
		void pop_heap(RandomAccessIterator first, RandomAccessIterator last)
	{
		less<typename iterator_traits<RandomAccessIterator>::value_type> c;
		pop_heap(first, last, c);
	}
	template<class RandomAccessIterator, class Compare> _UCXXEXPORT
		void pop_heap(RandomAccessIterator first, RandomAccessIterator last, Compare)
	{
		--last;
		while(first < last){
			iter_swap( first, first+1);
			++first;
		}
	}

	template<class RandomAccessIterator> _UCXXEXPORT
		void make_heap(RandomAccessIterator first, RandomAccessIterator last)
	{
		less<typename iterator_traits<RandomAccessIterator>::value_type> c;
		make_heap(first, last, c);
	}
	template<class RandomAccessIterator, class Compare> _UCXXEXPORT
		void make_heap(RandomAccessIterator first, RandomAccessIterator last, Compare comp)
	{
		sort( reverse_iterator<RandomAccessIterator>(last), reverse_iterator<RandomAccessIterator>(first), comp);
	}
	template<class RandomAccessIterator> _UCXXEXPORT
		void sort_heap(RandomAccessIterator first, RandomAccessIterator last)
	{
		less<typename iterator_traits<RandomAccessIterator>::value_type> c;
		sort_heap(first, last, c);
	}
	template<class RandomAccessIterator, class Compare> _UCXXEXPORT
		void sort_heap(RandomAccessIterator first, RandomAccessIterator last, Compare comp)
	{
		sort( first, last, comp);
	}


	// _lib.alg.min.max_, minimum and maximum:
	template<class T> _UCXXEXPORT
		const T& min(const T& a, const T& b)
	{
		if(b < a){
			return b;
		}
		return a;
	}

	template<class T, class Compare> _UCXXEXPORT
		const T& min(const T& a, const T& b, Compare comp)
	{
		if( comp(b, a) == true){
			return b;
		}
		return a;
	}

	template<class T> _UCXXEXPORT
		const T& max(const T& a, const T& b)
	{
		if( a < b){
			return b;
		}
		return a;
	}

	template<class T, class Compare> _UCXXEXPORT
		const T& max(const T& a, const T& b, Compare comp)
	{
		if( comp(a, b) ){
			return b;
		}
		return a;
	}

	template<class ForwardIterator> _UCXXEXPORT
		ForwardIterator min_element(ForwardIterator first, ForwardIterator last)
	{
		less<typename iterator_traits<ForwardIterator>::value_type> c;
		return min_element(first, last, c);
	}

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

	template<class ForwardIterator> _UCXXEXPORT
		ForwardIterator max_element(ForwardIterator first, ForwardIterator last)
	{
		less<typename iterator_traits<ForwardIterator>::value_type> c;
		return max_element(first, last, c);
	}

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

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

	template<class InputIterator1, class InputIterator2, class Compare> _UCXXEXPORT
		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;
			}
			++first1;
			++first2;
		}
		return first1==last1 && first2 != last2;
	}

	// _lib.alg.permutation.generators_, permutations
	template<class BidirectionalIterator> _UCXXEXPORT
		bool next_permutation(BidirectionalIterator first, BidirectionalIterator last)
	{
		less<typename iterator_traits<BidirectionalIterator>::value_type> c;
		return next_permutation(first, last, c);
	}

	template<class BidirectionalIterator, class Compare> _UCXXEXPORT
		bool next_permutation(BidirectionalIterator first, BidirectionalIterator last, Compare comp)
	{
		if(first == last){
			return false;	// No data
		}
		BidirectionalIterator i = last;
		--i;
		if(i == first){
			return false;	//Only one element
		}
		BidirectionalIterator ii = i;
		--ii;
		//If the last two items are in order, swap them and call it done
		if( comp(*ii, *i) ){
			iter_swap(ii, i);
			return true;
		}


		//This part of the algorithm copied from G++ header files ver. 3.4.2
		i = last;
		--i;
		for(;;){
			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;
			}
		}


	}

	template<class BidirectionalIterator> _UCXXEXPORT
		bool prev_permutation(BidirectionalIterator first, BidirectionalIterator last)
	{
		less<typename iterator_traits<BidirectionalIterator>::value_type> c;
		return prev_permutation(first, last, c);
	}

	template<class BidirectionalIterator, class Compare> _UCXXEXPORT
		bool prev_permutation(BidirectionalIterator first, BidirectionalIterator last, Compare comp)
	{
		if(first == last){
			return false;	// No data
		}
		BidirectionalIterator i = last;
		--i;
		if(i == first){
			return false;	//Only one element
		}
		BidirectionalIterator ii = i;
		--ii;
		//If the last two items are in reverse order, swap them and call it done
		if( comp(*i, *ii) ){
			iter_swap(ii, i);
			return true;
		}

		//Copied from GNU GCC header files version 3.4.2
		i = last;
		--i;

		for(;;){
			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;
			}
		}

	}

}

#pragma GCC visibility pop

#endif



