/**************************************************************************\
MODULE: matrix
SUMMARY:
Matrix templates.
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
\**************************************************************************/
template<class T>
class Mat {
typedef typename Vec<T>::value_type value_type;
typedef typename Vec<T>::reference reference;
typedef typename Vec<T>::const_reference const_reference;
Mat(); // initially 0 x 0
Mat(const Mat<T>& a);
Mat& operator=(const Mat<T>& a);
~Mat();
Mat(INIT_SIZE_TYPE, long n, long m);
// Mat(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.
reference operator()(long i, long j);
const_reference operator()(long i, long j) const;
// access element (i, j), both indices starting at 1
const_reference get(long i, long j) const;
// access element (i, j), both indices starting at 0
void put(long i, long j, const T& a);
// same as M[i].put(j, a)
template <class U>
void put(long i, long j, const U& a);
// same as M[i].put(j, a)
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).
};
template<class T>
const Vec< Vec<T> >& rep(const Mat<T>& a);
// read-only access to underlying representation
template<class T>
void swap(Mat<T>& X, Mat<T>& Y);
// swaps X and Y (by swapping pointers)
template<class T>
void MakeMatrix(Mat<T>& x, const vec_vec_T& a);
// copies a to x, checking that it is "rectangular"
/**************************************************************************\
Input/Output
\**************************************************************************/
template<class T>
istream& operator>>(istream&, Mat<T>&);
template<class T>
ostream& operator<<(ostream&, const Mat<T>&);
/**************************************************************************\
Equality Testing
\**************************************************************************/
template<class T>
long operator==(const Mat<T>& a, const Mat<T>& b);
template<class T>
long operator!=(const Mat<T>& a, const Mat<T>& b);