/*
 * ===========================
 * VDK Visual Development Kit
 * Version 0.4
 * October 1998
 * ===========================
 *
 * Copyright (C) 1998, Mario Motta
 * Developed by Mario Motta <mmotta@guest.net>
 *
 * 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., 59 Temple Place - Suite 330, Boston, MA
 * 02111-130
*/
#define NO_DEBUG
#ifndef VDKARRAY_H
#define VDKARRAY_H
//#include <iostream>


//================
// M_ARRAY CLASS
//================
/*!
  \class VDKArray
  \brief provides a templatized array

  \par OVERVIEW
  VDKArray<T> class implements a value semantic, all managed objects 
  are copied from original values.  An array can contains type<T> objects, 
  can resize himself to accomodate others objects, however resizing 
  operations must be explicit.
  A generic type<T> must provide consistent:
  \arg T() 	default constructor
  \arg T(T& t)	copy initializer
  \arg =(T& t)	assignement operator
  in order to assure correct array deep-copying
  \par Relational operators
  A generic type<T> should provide also:
  \arg int operator==(T& t) equality operator
  \arg int operator<(T& t)	disequality operator
  in order to correctly use heapsort routine.
  \par CONSIDERATIONS
  Arrays are bounds checked, try to access an element out
  of bounds will cause an assert()-call failure and abnormal
  program termination.
  I recommend to use typedef to consistently declare a type<T>
  Array:
  \code
  typedef Array<someClass>   SomeClassArray;
  \endcode

  \par DEBUGGING
  NO_DEBUG directive will avoid any bound checking
  
  \par REFERENCE
  U. Breymann et al. "Composite templates and inheritance"
  C++ Report, Vol.7, nr. 2, pp. 33-39, 1995
 */

template <class T> class VDKArray 
{

 private:
  // friend ostream& operator<<(ostream& os, VDKArray<T>& a);
  // At() operator view arrays in scientific index notation
  // A[1...n] instead of A[0..n-1].
  // (used for heapsort alghoritm)
  /*!
    /internal
   */
  T& At(int ndx) 
    { 
      return start[ndx-1]; 
    }
 protected:
  int xDim;		// number of elements
  T* start;	// pointer to data array
 public:
  /*!
    Constructor.
    \param n array length
   */
  VDKArray(int n = 0):xDim(n),start(n ? new T[n]: (T*) NULL) 
    {
    }
  /*!
    Copy initializer
   */
  VDKArray(const VDKArray&);
  /*!
    Assignement
   */
  VDKArray& operator=(const VDKArray&);
  /*!
Destructor
   */
  virtual ~VDKArray() 
    { 
      if(start) 
	delete[] start; 
    }
  /*!
    Returns array size
   */
  int size() 
    { 
      return xDim ; 
    }
  /*!
    Resize array
   */
  void resize(int);		// change vector size
  
  // index operations
  /*!
    Access operator
    \par tip
    can be used in both left or rigth side of an expression
    \code
    typedef<int> IntArray;
    IntArray integers(10);
    integers[0] = 6;
    int i = integers[0];
    \endcode
   */
  T& operator[](int ndx) 
    {
     return start[ndx]; 
    }
  const T& operator[](int ndx) const 
    {
      return start[ndx]; 
    }
  // sorting routine
  /*!
    Sorts array on place in n*log(n) time.
    \par Reference
    W.H.Press et al.
    "Numerical recipes in C" 2nd edition
    Cambridge University Press, 1992
   */
  VDKArray<T>& Heapsort();
  /*!
    equality operator
  */
  virtual int operator==(VDKArray<T>& m); // equality operator
};


//copy inizializer
template <class T>
VDKArray<T>::VDKArray(const VDKArray<T> &v) 
{
  xDim = v.xDim;
  start = new T[xDim];
  for(register int i = 0;i < xDim; i++) start[i] = v.start[i];
}
// resize dinamically
template <class T>
void VDKArray<T>::resize(int ns) 
{
  T* temp = new T[ns];
  T* pstart = start,*ptemp = temp;
  // compute the smaller size
  int s = (ns > xDim) ? xDim : ns;
  // copy elements  into new array
  for(register int i = 0;i < s; i++) *ptemp++ = *pstart++;
  // delete old array and update pointer to data
  delete[] start;
  start = temp;
  xDim = ns;
}
// assignement
template <class T>
VDKArray<T>& VDKArray<T>::operator=(const VDKArray<T>&v) 
{
  // avoid v = v;
  if(this !=&v) 
    {
      if(start) delete[] start;
      xDim = v.xDim;
      start=new T[xDim];
      for(register int i = 0;i < xDim; i++) 
	start[i] = v.start[i];
    }
  return *this;
}
// equality operator
template <class T> int
VDKArray<T>::operator==(VDKArray<T>& m) 
{
  if(xDim != m.xDim) return 0;
  register int i;
  for(i = 0;
      (i < xDim)  &&
	((*this)[i] == m[i]); i++) ;
  return i == xDim ? 1 : 0 ;
}
// Heap sort routine, ref: W.H.Press et al.
// "Numerical recipes in C" 2nd edition
// Cambridge University Press, 1992
template <class T>
VDKArray<T>& VDKArray<T>::Heapsort() 
{
  unsigned int n = size();
  unsigned int i,ir,j,l;
  T rra;
  if(n<2) return *this;
  l = (n >> 1)+1;
  ir=n;
  for(;;) 
    {
      if (l > 1) rra = At(--l);
      else 
	{
	  rra = At(ir);	At(ir) = At(1);
	  if(--ir == 1) 
	    { 
	      At(1) = rra; break; 
	    }
	}
      i = l; j = l+l;
      while(j <= ir) 
	{
	  if(j < ir && At(j) < At(j+1) ) j++;
	  if(rra < At(j)) 
	    {
	    At(i) = At(j); i = j; j <<= 1;
	    }
	  else j = ir+1;
	}
      At(i) = rra;
    }
  return *this;
}
// stream output
/*
  template <class T>
  ostream& operator<<(ostream& os, VDKArray<T>& a) 
  {
  for(register int i = 0; i < a.xDim; i++)
  os << a[i] << ' ';
  return os;
  }
*/
#endif





