/**************************************************************************\
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
\**************************************************************************/
// EXCEPTIONS: all functions below do not throw any exceptions,
// except as noted
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);
// copy constructor
// EXCEPTIONS: may throw
Mat& operator=(const Mat<T>& a);
// assignment
// EXCEPTIONS: may throw, weak ES (but dimensions of LHS
// will be either that of old LHS or RHS)
~Mat();
// destructor
Mat(Mat&& other) noexcept;
#ifndef NTL_DISABLE_MOVE_ASSIGN
Mat& operator=(Mat&& other) noexcept;
#endif
// move semantics (C++11 only)
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.
// EXCEPTIONS: may throw
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.
// EXCEPTIONS: strong ES (although underlying vector representation
// may be reallocated)
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.
// Even if one has read/write access to a row, any attempt
// to change its length will raise an error.
// EXCEPTIONS: may throw if range checking is turned on
Vec<T>& operator()(long i);
const Vec<T>& operator()(long i) const;
// access row i, initial index 1.
// Even if one has read/write access to a row, any attempt
// to change its length will raise an error.
// of this row will raise an error.
// EXCEPTIONS: may throw if range checking is turned on
reference operator()(long i, long j);
const_reference operator()(long i, long j) const;
// access element (i, j), both indices starting at 1
// EXCEPTIONS: may throw if range checking is turned on
const_reference get(long i, long j) const;
// access element (i, j), both indices starting at 0
// EXCEPTIONS: may throw if range checking is turned on
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).
long alias(const Vec<T>& a) const;
// returns 1 if a aliases a row of the matrix, and 0 otherwise.
void swap(Mat<T>& other);
// quick swap *this and other
void move(Mat<T>& other);
// quick move other to *this
};
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);
// quick swap of X and Y
template<class T>
void MakeMatrix(Mat<T>& x, const vec_vec_T& a);
// copies a to x, checking that it is "rectangular"
// EXCEPTIONS: may thow, weak ES (but dimensions of x either
// remain unchanged or are set to the new dimensions implied by a)
/**************************************************************************\
Input/Output
\**************************************************************************/
template<class T>
istream& operator>>(istream&, Mat<T>&);
// EXCEPTIONS: may throw, weak ES
template<class T>
ostream& operator<<(ostream&, const Mat<T>&);
// EXCEPTIONS: may throw, weak ES
/**************************************************************************\
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);