///////////////////////////////////////////////////////////////////////////
// FILE: algorithm (Definitions of various algorithm templates)
//
//                          Open Watcom Project
//
//    Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
//
//    This file is automatically generated. Do not edit directly.
//
// =========================================================================
//
// Description: This header is part of the C++ standard library. It
//              defines a collection of useful algorithm templates.
///////////////////////////////////////////////////////////////////////////
#ifndef _ALGORITHM_INCLUDED
#define _ALGORITHM_INCLUDED
#if !defined(_ENABLE_AUTODEPEND)
  #pragma read_only_file;
#endif


#ifndef __cplusplus
#error The header algorithm requires C++
#endif

#ifndef _ITERATOR_INCLUDED
  #include <iterator>
#endif

#ifndef _STDEXCEPT_INCLUDED
  #include <stdexcept>
#endif

namespace std {

  // Non-modifying sequence operations
  // =================================

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

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

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

  // find_end( FwdIterator, FwdIterator, FwdIterator, FwdIterator)
  // *************************************************************
  template< class ForwardIterator1, class ForwardIterator2 >
  ForwardIterator1 find_end( ForwardIterator1 first1,
                             ForwardIterator1 last1,
                             ForwardIterator2 first2,
                             ForwardIterator2 last2 )
  {
    ForwardIterator1 a;
    ForwardIterator2 b;
    ForwardIterator1 ans = last1;
    while( first1 != last1 ) {
      //find first item that matches
      while( ! ( *first1 == *first2 ) ){
        ++first1;
        if( first1 == last1 ) return( ans );
      }
      //see if other items match
      a = first1;
      b = first2;
      do{
        ++a;
        ++b;
        if( b == last2 ){
          ans = first1;
          break;
        }
        if( a == last1 ) return( ans );
      }while( *a == *b );
      ++first1;
    }
    return( ans );
  }

  // find_end( FwdIterator, FwdIterator, FwdIterator, FwdIterator, BinaryPred )
  // **************************************************************************
  template< class ForwardIterator1,
            class ForwardIterator2,
            class BinaryPredictate >
  ForwardIterator1 find_end( ForwardIterator1 first1,
                             ForwardIterator1 last1,
                             ForwardIterator2 first2,
                             ForwardIterator2 last2,
                             BinaryPredictate pred )
  {
    ForwardIterator1 a;
    ForwardIterator2 b;
    ForwardIterator1 ans = last1;
    while( first1 != last1 ) {
      //find first item that matches
      while( ! ( pred( *first1, *first2 ) ) ){
        ++first1;
        if( first1 == last1 ) return( ans );
      }
      //see if other items match
      a = first1;
      b = first2;
      do{
        ++a;
        ++b;
        if( b == last2 ){
          ans = first1;
          break;
        }
        if( a == last1 ) return( ans );
      }while( pred( *a, *b ) );
      ++first1;
    }
    return( ans );
  }

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

  // find_first_of( Fwd1, Fwd1, Fwd2, Fwd2, Pred )
  // *********************************************
  template< class ForwardIterator1,
            class ForwardIterator2, 
            class BinaryPredictate >
  ForwardIterator1 find_first_of( ForwardIterator1 first1,
                                  ForwardIterator1 last1,
                                  ForwardIterator2 first2,
                                  ForwardIterator2 last2,
                                  BinaryPredictate pred )
  {
    ForwardIterator2 i;
    while( first1 != last1 ) {
      for( i = first2; i != last2; ++i ){
        if( pred( *first1, *i ) ) return first1;
      }
      ++first1;
    }
    return( last1 );
  }

#ifdef _NEVER
  // count( InputIterator, InputIterator, const Type & )
  // ***************************************************
  template< class InputIterator, class Type >
  typename iterator_traits< InputIterator >::difference_type
    count( InputIterator first,
           InputIterator last,
           const Type &value )
  {
    typename iterator_traits< InputIterator >::difference_type number(0);
    while( first != last ) {
      if( *first == value ) ++number;
      ++first;
    }
    return( number );
  }

  // count_if( InputIterator, InputIterator, Predicate )
  // ***************************************************
  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 number(0);
    while( first != last ) {
      if( pred( *first ) != false ) ++number;
      ++first;
    }
    return( number );
  }
#endif

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

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


  // Mutating Sequence Operations
  // ============================

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

  // copy_backward( Bidirectional1, Bidirectional1, Bidirectional2 )
  // ****************************************************************
  template< class Bidirectional1, class Bidirectional2 >
  Bidirectional2 copy_backward( Bidirectional1 first,
                                Bidirectional1 last,
                                Bidirectional2 result )
  {
    if( first == last ) return( result );
    while( --last != first ) {
      *--result = *last;
    }
    *--result = *last;
    return( result );
  }

  // swap( Type &, Type & )
  // **********************
  template< class Type >
  inline void swap( Type &x, Type &y )
    { Type tmp(x); x = y; y = tmp; }


  // swap_ranges( ForwardIterator1, ForwardIterator1, ForwardIterator2 )
  // *******************************************************************
  template< class ForwardIterator1, class ForwardIterator2 >
  ForwardIterator2 swap_ranges( ForwardIterator1 first1,
                                ForwardIterator1 last1,
                                ForwardIterator2 first2 )
  {
    while( first1 != last1 ) {
      swap( *first1, *first2 ); // iter_swap? See 25.2.2p3
      ++first1;
      ++first2;
    }
    return( first2 );
  }

  // iter_swap( ForwardIterator1, ForwardIterator2 )
  // ***********************************************
  template< class ForwardIterator1, class ForwardIterator2 >
  inline void iter_swap( ForwardIterator1 x, ForwardIterator2 y )
  {
    iterator_traits< ForwardIterator1 >::value_type tmp(*x);
    *x = *y;
    *y = tmp;
  }

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

  // transform( Input1, Input1, Input2, Output, BinaryOperation )
  // ************************************************************
  template< class InputIterator1,
            class InputIterator2,
            class OutputIterator,
            class BinaryOperation >
  OutputIterator transform( InputIterator1 first1,
                            InputIterator1 last1,
                            InputIterator2 first2,
                            OutputIterator result,
                            BinaryOperation bop )
  {
    while( first1 != last1 ) {
      *result = bop( *first1, *first2 );
      ++first1;
      ++first2;
      ++result;
    }
    return( result );
  }

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

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

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

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

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

  // fill_n( OutputIterator, Size, const Type & )
  // ********************************************
  template< class OutputIterator, class Size, class Type >
  void fill_n( OutputIterator first, Size n, const Type &value )
  {
    unsigned long long i = 0ULL, max(n);
    while( i < max ) {
      *first = value;
      ++first;
      ++i;
    }
  }

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

  // generate_n( OutputIterator, Size, Generator )
  // *********************************************
  template< class OutputIterator, class Size, class Generator >
  void generate_n( OutputIterator first, Size n, Generator gen )
  {
    unsigned long long i = 0ULL, max(n);
    while( i < max ) {
      *first = gen( );
      ++first;
      ++i;
    }
  }

  // remove_copy( FwdIterator, FwdIterator, OutputIterator, Type const & )
  // *********************************************************************
  template< class ForwardIterator, class OutputIterator, class Type >
  OutputIterator remove_copy( ForwardIterator first, ForwardIterator last,
                               OutputIterator out, Type const & value)
  {
    while( first != last){
      if( *first == value ){
        ++first;
      }else{
        *out = *first;
        ++first;
        ++out;
      }
    }
    return( out );
  }

  // remove_copy_if( FwdIterator, FwdIterator, OutputIterator, Predictate )
  // **********************************************************************
  template< class ForwardIterator, class OutputIterator, class Predictate >
  ForwardIterator remove_copy_if( ForwardIterator first, ForwardIterator last,
                                  OutputIterator out, Predictate pred )
  {
    while( first != last){
      if( pred( *first ) != false ){
        ++first;
      }else{
        *out = *first;
        ++first;
        ++out;
      }
    }
    return( out );
  }

  // remove( ForwardIterator, ForwardIterator, Type const & )
  // ********************************************************
  template< class ForwardIterator, class Type >
  ForwardIterator remove( ForwardIterator first, ForwardIterator last,
                          Type const & value)
  {
    ForwardIterator out = first;
    bool copy = false;
    while( first != last){
      if( *first == value ){
        ++first;
        copy = true;
      }else{
        if( copy ){
            //avoid unecessary copies
            *out = *first;
        }
        ++first;
        ++out;
      }
    }
    return( out );
  }

  // remove_if( ForwardIterator, ForwardIterator, Predictate )
  // *********************************************************
  template< class ForwardIterator, class Predictate >
  ForwardIterator remove_if( ForwardIterator first, ForwardIterator last,
                             Predictate pred )
  {
    ForwardIterator out = first;
    bool copy = false;
    while( first != last){
      if( pred( *first ) != false ){
        ++first;
        copy = true;
      }else{
        if( copy ){
            //avoid unecessary copies
            *out = *first;
        }
        ++first;
        ++out;
      }
    }
    return( out );
  }

  // reverse( Bidirectional, Bidirectional )
  // ***************************************
  template< class Bidirectional >
  void reverse( Bidirectional first, Bidirectional last )
  {
    if( first == last ) return;
    --last;
    while( first != last ) {
      swap( *first, *last );
      ++first;
      if( first == last ) break;
      --last;
    }
  }

  // reverse_copy( Bidirectional, Bidirectional, OutputIterator )
  // ************************************************************
  template< class Bidirectional, class OutputIterator >
  OutputIterator reverse_copy( Bidirectional first,
                               Bidirectional last,
                               OutputIterator result )
  {
    if( first == last ) return( result );
    while( --last != first ) {
      *result = *last;
      ++result;
    }
    *result = *last;
    return( ++result );
  }


  // Sorting and related operations
  // ==============================

#ifdef _NEVER
  namespace _ow {

    template< class Int >
    inline Int heap_parent( Int index )
      { return ( ( index - 1 )/2 ); }

    template< class Int >
    inline Int heap_left( Int index )
      { return ( 2*index + 1 ); }

    template< class Int >
    inline Int heap_right( Int index )
      { return ( 2*index + 2 ); }

    template< class RandomAccess >
    void heapify(
      RandomAccess first,
      RandomAccess last,
      typename iterator_traits< RandomAccess >::difference_type index)
    {
      typedef typename iterator_traits< RandomAccess >::difference_type Int;
      using std::swap;

      Int size = last - first;
      Int L    = heap_left( index );   // Index of left child.
      Int R    = heap_right( index );  // Index of right child.
      Int largest = index;             // Index of largest child.

      // Compare the left child (if there is one) with the item at index.
      if( L < size && first[largest] < first[L] )
        largest = L;

      // Compare the right child (if there is one) with the largest from above.
      if( R < size && first[largest] < first[R] )
        largest = R;

      // If the largest was a child, swap it and then process that child.
      if( largest != index ) {
        swap( first[index], first[largest] );
        heapify( first, last, largest );
      }
    }

  } // namespace _ow

  // push_heap( RandomAccess, RandomAccess )
  // ***************************************
  template< class RandomAccess >
  void push_heap( RandomAccess first, RandomAccess last )
  {
    typedef typename iterator_traits< RandomAccess >::difference_type Int;
    using std::swap;
    using _ow::heap_parent;

    // If there is no heap, calling this function is illogical.
    if( first == last )
      throw std::domain_error( "heap underflow" );

    // Walk up the heap, swapping the index node with its parent as necessary.
    Int index = (last - first) - 1;
    while( index > 0 && first[heap_parent( index )] < first[index] ) {
      swap( first[heap_parent( index )], first[index] );
      index = heap_parent( index );
    }
  }

  // pop_heap( RandomAccess, RandomAccess )
  // **************************************
  template< class RandomAccess >
  void pop_heap( RandomAccess first, RandomAccess last )
  {
    using std::swap;

    // If there is no heap, calling this function is illogical.
    if( first == last )
      throw std::domain_error( "heap underflow" );

    // Back last up so that it is on the sequence. Swap max item with last.
    --last;
    if( first != last ) {
      swap( *first, *last );
      _ow::heapify( first, last, 0 );
    }
  }

  // make_heap( RandomAccess, RandomAccess )
  // ***************************************
  template< class RandomAccess >
  void make_heap( RandomAccess first, RandomAccess last )
  {
    typedef typename iterator_traits< RandomAccess >::difference_type Int;

    Int size = last - first;
    Int index;

    // Handle a sequence of one item (or zero items) as a special case.
    if( size <= 1 ) return;

    // Only half the items need to be heapified. The rest are leaves.
    for( index = size/2 - 1; index >= 0; --index ) {
      _ow::heapify( first, last, index );
    }
  }

  // sort_heap( RandomAccess, RandomAccess )
  // ***************************************
  template< class RandomAccess >
  void sort_heap( RandomAccess first, RandomAccess last )
  {
    typedef typename iterator_traits< RandomAccess >::difference_type Int;
    using std::swap;

    Int size = last - first;
    Int index;

    // Handle a sequence of one item (or zero items) as a special case.
    if( size <= 1 ) return;

    for( index = size - 1; index > 0; --index ) {
      swap( first[0], first[index] );
      --last;
      _ow::heapify( first, last, 0 );
    }
  }

  // sort( RandomAccess, RandomAccess )
  // **********************************
  template< class RandomAccess >
  void sort( RandomAccess first, RandomAccess last )
  {
    make_heap( first, last );
    sort_heap( first, last );
  }
#endif

  // min( const Type &, const Type & )
  // *********************************
  template< class Type >
  inline const Type &min( const Type &x, const Type &y )
    { return( (y < x) ? y : x ); }

  // max( const Type &, const Type & )
  // *********************************
  template< class Type >
  inline const Type &max( const Type &x, const Type &y )
    { return( (x < y) ? y : x ); }

  // min( const Type &, const Type &, Compare )
  // ******************************************
  template< class Type, class Compare >
  inline const Type &min( const Type &x, const Type &y, Compare comp )
    { return( comp( y, x ) ? y : x ); }

  // max( const Type &, const Type &, Compare )
  // ******************************************
  template< class Type, class Compare >
  inline const Type &max( const Type &x, const Type &y, Compare comp )
    { return( comp( x, y ) ? y : x ); }

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

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

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

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

} // namespace std

#endif
