
/**************************************************************************\

MODULE: matrix

SUMMARY:

Macros are deined providing template-like classes for dynamic-sized,
recatngular matrices.

The macro NTL_matrix_decl(T,vec_T,vec_vec_T,mat_T) declares a new class
mat_T representing matrices over T, where vec_T and vec_vec_T are
classes representing "NTL vectors" over T and vec_T, respectively.

The implementation of mat_T can be instantiated with 
NTL_matrix_impl(T,vec_T,vec_vec_T,mat_T).

If T supports I/O and/or equluality testing, then mat_T
can also be made to support these.

For example, the declaration 

   mat_T M;

creates a 0 x 0 matrix.  We can make it have 10 rows and 20 columns like this:

   M.SetDims(10, 20);

A row can be accessed as M[i], indexing from 0, or as M(i), indexing from 1.
A matrix entry can be accessed as M[i][j], indexing from 0, or as
M(i, j), indexing from 1.

A matrix is represented as a vec_vec_T: a vector of rows, where
each row is a vec_T.  Any attempt to resize one of the rows so
as to create a non-rectangular matrix will result in a run-time 
error.

The dimensions of an existing matrix may be changed.  If the number of
columns does not change, then the matrix is just "resized" like a vector,
and no information is lost.  Otherwise, if the number of columns changes,
the matrix is completely destroyed, and a new matrix is created


\**************************************************************************/

class mat_T {
   mat_T(); // initially 0 x 0

   mat_T(const mat_T& a);
   mat_T& operator=(const mat_T& a);
   ~mat_T();

   mat_T(INIT_SIZE_TYPE, long n, long m); 
   // mat_T(INIT_SIZE, n, m) initializes an n x m matrix, invoking
   // the default constructor for T to initialize entries.

   void SetDims(long n, long m); 
   // M.SetDims(n, m) makes M have dimension n x m.  If the number of
   // columns (m) changes, previous storage is freed, and space for M
   // is reallocated and initialized; otherwise, more rows are
   // allocated as necessary (when number of rows increases), 
   // excess rows are retained (when number of rows decreases),
   // and--importantly--the contents do not change.

   void kill(); free storage and make 0 x 0

   long NumRows() const;
   // M.NumRows() returns the number of rows of M

   long NumCols() const;
   // M.NumCols() returns the number of columns of M

   vec_T& operator[](long i);
   const vec_T& operator[](long i) const;
   // access row i, initial index 0.  Any attempt to change the length
   // of this row will raise an error.

   vec_T& operator()(long i);
   const vec_T& operator()(long i) const;
   // access row i, initial index 1.  Any attempt to change the length
   // of this row will raise an error.

   T& operator()(long i, long j);
   const T& operator()(long i, long j) const; 
   // access element (i, j), both indices starting at 1

   long position(const vec_T& a) const;
   // returns index of a in matrix, or -1 if not present;
   // equivalent to rep(*this).position(a).


   long position1(const vec_T& a) const;
   // returns index of a in matrix, or -1 if not present;
   // equivalent to rep(*this).position1(a).


};

const vec_vec_T& rep(const mat_T& a);
// read-only access to underlying representation

void swap(mat_T& X, mat_T& Y);
// swaps X and Y (by swapping pointers)

void MakeMatrix(mat_T& x, const vec_vec_T& a);
// copies a to x, checking that it is "rectangular"

/**************************************************************************\

                            Input/Output

The I/O operators can be declared with 
NTL_io_matrix_decl(T,vec_T,vec_vec_T,mat_T), and
implemented using NTL_io_matrix_impl(T,vec_T,vec_vec_T,mat_T).  
I/O is implemented using the underlying I/O operators for vec_vec_T.

\**************************************************************************/


istream& operator>>(istream&, mat_T&);
ostream& operator<<(ostream&, const mat_T&); 

/**************************************************************************\

                              Equality Testing

The equality testing operators == and != can be declared
NTL_eq_matrix_decl(T,vec_T,vec_vec_T,mat_T), and
implemented using NTL_eq_matrix_impl(T,vec_T,vec_vec_T,mat_T).  
Equality testing is implemented using the underlying 
equality operators for vec_vec_T.


\**************************************************************************/


long operator==(const mat_T& a, const mat_T& b);
long operator!=(const mat_T& a, const mat_T& b);

