// This code implementation is the intellectual property of
// the GEANT4 collaboration.
//
// By copying, distributing or modifying the Program (or any work
// based on the Program) you indicate your acceptance of this statement,
// and all its terms.
//
// $Id: tpsrtvec.icc,v 1.2 1999/11/25 13:41:26 gcosmo Exp $
// GEANT4 tag $Name: geant4-01-00 $
//
// 
//---------------------------------------------------------------
//  GEANT 4 class implementation file
//
//  G4RWTPtrSortedVector
//---------------------------------------------------------------

template<class T>
G4RWTPtrSortedVector<T>::G4RWTPtrSortedVector(size_t n)
  : std_pvector(n),rwsize(0)
{
  for(int i=0;i<n;i++)
    std_pvector::operator[](i)=0;
}

template<class T>
G4RWTPtrSortedVector<T>::G4RWTPtrSortedVector(const G4RWTPtrSortedVector<T>& v)
  : std_pvector(v), rwsize(v.rwsize){}

template<class T>
G4RWTPtrSortedVector<T>::~G4RWTPtrSortedVector(){}

template<class T>
G4RWTPtrSortedVector<T>&
G4RWTPtrSortedVector<T>::operator=(const G4RWTPtrSortedVector<T>& v)
{
  std_pvector::operator=(v);
  rwsize=v.rwsize;
  return *this;     
}

template<class T>
T* const& G4RWTPtrSortedVector<T>::operator [] (size_t n) const
{
  if(n>=rwsize)
    G4RWTHROW(G4RWBoundsErr("G4RWTPtrSortedVector",rwsize,n));
  return std_pvector::operator[](n);
}

template<class T>
T* const& G4RWTPtrSortedVector<T>::operator () (size_t n) const
{
  return std_pvector::operator[](n);
}

template<class T>
T*& G4RWTPtrSortedVector<T>::at(size_t n )
{
  if(n>=rwsize)
    G4RWTHROW(G4RWBoundsErr("G4RWTPtrSortedVector",rwsize,n));
  if(n<std_pvector::size() && rwsize<=n)
    rwsize=n+1;
  return std_pvector::operator[](n);
}

template<class T>
T*  G4RWTPtrSortedVector<T>::at(size_t n ) const
{
  if(n>=rwsize)
    G4RWTHROW(G4RWBoundsErr("G4RWTPtrSortedVector",rwsize,n));
  return std_pvector::operator[](n);
}

template<class T>
void G4RWTPtrSortedVector<T>::clear()
{
  std_pvector::erase(std_pvector::begin(),std_pvector::end());
  rwsize=0;
}

template<class T>
void G4RWTPtrSortedVector<T>::clearAndDestroy () 
{ 
  size_t sz=0;
  for(iterator it=std_pvector::begin();sz<rwsize;it++,sz++)
    delete *it;
  std_pvector::erase(std_pvector::begin(),std_pvector::end());
  rwsize=0;
}

template<class T>
T* G4RWTPtrSortedVector<T>::find (const T* a) const
{
  if(!a || std_pvector::empty()) return 0;
  //We are sorted, so try a n log n search
  int t,d;
  int u=rwsize,l=0;
  do
    {
      d=(u-l)/2;
      t=d+l;
      //this asks *a <= (*(*this)[t] whithout requiring operator<=
      if(sorter(a,(*this)[t]) || *a==*(*this)[t])
        u=t;
      else
        l=t;
    }
  while(d>0);
    
  if(*(*this)[u]==*a)
    return (*this)[u];
  else
    return 0;
}

template<class T>
size_t G4RWTPtrSortedVector<T>::entries () const
{
  return rwsize;
}

template<class T>
void G4RWTPtrSortedVector<T>::insert ( T* a ) 
{ 
  if(rwsize<std_pvector::size())
    {
      //We have empty entries
      iterator it=std_pvector::begin();
      for(int i=0;i<rwsize;i++,it++);
      *it=a;
      it++;
      G4std::sort(std_pvector::begin(),it,sorter);
    }
  else
    {
      std_pvector::push_back(a);
      //This makes it a sorted thing;
      G4std::sort(std_pvector::begin(),std_pvector::end(),sorter);
    }
  rwsize++;
}

template<class T>
size_t G4RWTPtrSortedVector<T>::index ( const T* a )
{
  T*const* ii = std_pvector::begin();
  size_t cnt = 0;
  for (T*const* it = ii;cnt<rwsize; ++it,cnt++)
    {
      if ( **it == *a ) return cnt;
    }
  return 0;
}

template<class T>
G4bool G4RWTPtrSortedVector<T>::isEmpty () const
{
  return rwsize==0;
}

template<class T>
T* const & G4RWTPtrSortedVector<T>::first () const
{
  if(!rwsize)
    G4RWTHROW(G4RWBoundsErr("G4RWTPtrSortedVector first()",rwsize,0));
  return std_pvector::front();
}
  
template<class T>
T* const & G4RWTPtrSortedVector<T>::last () const
{
  if(rwsize)
    return std_pvector::operator[](rwsize-1);
  else
    G4RWTHROW(G4RWBoundsErr("G4RWTPtrSortedVector last()",rwsize,0));
}

template<class T>
size_t G4RWTPtrSortedVector<T>::occurrencesOf(const T* a) const
{
  size_t cnt = 0;
  size_t sz = 0;
  for (const_iterator it = std_pvector::begin();sz<rwsize; ++it,sz++) 
    {
      if ( **it == *a ) cnt++;
    }
  return cnt;
}

template<class T>
T* G4RWTPtrSortedVector<T>::remove ( const T* a )
{
  iterator retval;
  size_t sz=0;
  for(retval=std_pvector::begin();sz<rwsize;retval++,sz++)
    if(**retval==*a) break;
  if(sz<rwsize && retval!=std_pvector::end()) 
    {
      T* tmp=*retval;
      std_pvector::erase(retval);
      rwsize--;
      return tmp;
    }
  else
    return 0;
}

template<class T>
size_t G4RWTPtrSortedVector<T>::removeAll ( const T* a)
{
  iterator s=std_pvector::end();
  iterator e=std_pvector::end();
  iterator r;
  size_t sz=0;
  int i=0;
  for(r=std_pvector::begin();sz<rwsize;r++,sz++)
    {
      if(i==0)
        {
          if(**r==*a)
            {
              s=r;
              i++;
            }
        }
      else 
        {
          if(**r!=*a)
            {
              e=r;
              break;
            }
          else
            i++;
        }
    }
  std_pvector::erase(s,e);
  rwsize-=i;
  return i;
}
