//
// LiDIA - a library for computational number theory
//   Copyright (c) 1995, 1996 by the LiDIA Group
//
// File        : base_vector.h 
// Author      : Frank Lehmann (FL), Markus Maurer (MM) 
//               Thomas Papanikolaou (TP), Patrick Theobald (PT)
// Last change : FL/MM, Feb 15 1995, initial version
//               FL/MM, Mar  8 1995
//               FL/MM, May 10 1995, added get_data_address 
//                                   clean-up
//		 FL/MM, May 15 1995, added typedef size_type and
//				     changed type of corresponding variables
//               FL/MM, May 23 1995, removed #define LiDIA_VECTOR_NO_RANGE_CHECK
//		 FL/MM, Jul  6 1995, changed internal size_type of base_vector
//				     to the global LiDIA-type lidia_size_t
//               FL/MM, Jul 24 1995, added 'const' to T* parameters of constructors
//		 FL/MM, Aug 30 1995, changed typedef int lidia_size_t to
//				     "#define ..."
//		 FL/MM, Aug 30 1995, changed "error_handler" to "lidia_error_handler"
//		 FL/MM, Sep 22 1995, removed "#define lidia_size_t ..." and
//				     "#ifdef LiDIA_VECTOR_INTERNAL_DATA_ACCESS ..."
//		 FL/MM, Sep 29 1995, changed "debug_handler" to "debug_handler_l"
//               PT,    Oct 28 1995, new template concept   
//		 MM,	Feb 01 1996, added const for first argument of "set_data(...)"            
//               SN,PT  Mar 01 1996, added HEADBANGER defines

/*
$Id: base_vector.h,v 1.26 1996/12/18 15:11:10 theobald Exp $
*/

#ifndef LIDIA_BASE_VECTOR_H
#define LIDIA_BASE_VECTOR_H

#define  EXPAND  'E'
#define  FIXED   'F'
#define  DEFAULT_RATIO 2.0

#if defined(HAVE_MAC_DIRS) || defined(__MWERKS__)
#include <LiDIA:lidia.h>
#else
#include <LiDIA/lidia.h>
#endif

#ifdef __GNUG__
class crt;
class bigint_matrix;
template < class T > class base_matrix;
template < class T > class math_matrix;
#endif

template <class T> 
class base_vector
{
#ifdef __GNUG__
  friend class crt;
  friend class base_matrix < T >;
  friend class math_matrix < T >;
  friend class bigint_matrix;
#endif

 protected:
  
  T *data;
  
  lidia_size_t length;
  lidia_size_t allocated;
  
  char mode;
  float dyn_exp_ratio;
  
  char sort_dir;                         /* sort-direction */
  int (*el_cmp) (const T &, const T &);  /* compare-func. for vec.elements */

 protected:
     
  T * copy_data(T *, const T *, lidia_size_t);
  
  /**
   ** constructors
   **/
  
 public:

  base_vector();
  base_vector(lidia_size_t, char);
  base_vector(lidia_size_t, lidia_size_t);
  base_vector(lidia_size_t, lidia_size_t, char); 
  base_vector(const base_vector < T > &);
  base_vector(const base_vector < T > &, char);

#ifndef HEADBANGER
  base_vector(const T *, lidia_size_t);
  base_vector(const T *, lidia_size_t, char); 
#endif
  
  /**
   ** destructor
   **/
  
 public:
 
  virtual ~base_vector();
      
  /**
   ** Input / Output
   **/

 public: 
 
  inline friend ostream & operator << (ostream &s, const base_vector < T > &x)
    {x.write(s); return s;}
  inline friend istream & operator >> (istream &s, base_vector < T > &x)
    {x.read(s); return s;}

 protected:

  void write(ostream &) const;
  void read(istream &);
  
  /**
   ** BEGIN: access functions
   **/
 
  /**
   ** capacity
   **/ 

 public:
 
  inline lidia_size_t capacity() const             
    {return allocated;}                      
  inline lidia_size_t get_capacity() const             
    {return allocated;}
  void set_capacity(lidia_size_t all);
  
  inline void reset()
    {kill();}
  void kill();
                         
  /**
   ** size
   **/
   
 public:

  inline lidia_size_t size() const                 
    {return length;}    
  inline lidia_size_t get_size() const                 
    {return length;}
  void set_size(lidia_size_t len);

  /**
   ** exp_ratio
   **/
 
 public:
    
  inline float exp_ratio() const
    {return dyn_exp_ratio;}   
  inline float get_exp_ratio() const
    {return dyn_exp_ratio;}
  void set_exp_ratio (float ratio)
    {dyn_exp_ratio = ((ratio >= (float) 1.0) ? ratio : (float) 1.0);}

  /**
   ** mode
   **/

 public:

  inline char get_mode() const
    {return mode;} 

  inline void set_mode(char md) 
    {mode = ((md == FIXED || md == EXPAND) ? md : FIXED);}
  
  /**
   ** member
   **/
 
 public:
 
  T & operator[] (lidia_size_t);              
  const T & operator[] (lidia_size_t) const;  
                                                
  const T & member(lidia_size_t) const;

  /**
   ** value array
   **/

 public:

  void set_data(const T *, lidia_size_t);    
  T *get_data() const;   

#ifdef __GNUG__
 private:
#else
 public:
#endif

#ifndef HEADBANGER
  inline T * get_data_address() const
    {return data;}                              /* returns a pointer to the internal elts of the vector */
#endif

  /**
   ** END: access functions
   **/ 

  /**
   ** assignment 
   **/

 public: 

  base_vector < T > & operator = (const base_vector < T > & v);  

  void assign(lidia_size_t, const base_vector< T > &, lidia_size_t, lidia_size_t);

#ifndef HEADBANGER
  friend void assign(base_vector < T > &v, const base_vector < T > &w)
    {v.assign(w);}
  void assign(const base_vector < T > &);
#endif
     
  /**
   ** reverse 
   **/

 public:

  void reverse();     
  void reverse(const base_vector < T > &b);
  
  /**
   ** swap functions
   **/

 public:

  inline friend void swap(base_vector < T > &a, base_vector < T > &b)
    {a.swap(b);}      

 protected:

  void swap(base_vector < T > &);
  
  /**
   ** concat functions 
   **/
 
 public:
  
  void concat(const base_vector < T > &, const base_vector < T > &);
  
  /**
   ** shift functions
   **/

 public:

  void shift_left(lidia_size_t, lidia_size_t);
  void shift_right(lidia_size_t, lidia_size_t);
  
  /**
   ** remove functions
   **/
 
  void remove_from(lidia_size_t, lidia_size_t l = 1);

  /**
   ** insert functions
   **/

  void insert_at(const T &, lidia_size_t);

};

#ifdef LIDIA_INCLUDE_C
#include <LiDIA/base_vector.c>
#endif 

#endif














