home *** CD-ROM | disk | FTP | other *** search
- /////////////////////////////////////////////////////////////
- // matrix.mth: Matrix class template methods
- // Copyright(c) 1993 Azarona Software. All rights reserved.
- /////////////////////////////////////////////////////////////
-
- template<class TYPE>
- void Matrix<TYPE>::Copy(const Matrix<TYPE> &m)
- // Does a two-dimensional copy from m to this matrix,
- // copying as much data as possible without reallocating
- // this matrix. Assumes a worst case non-contiguous
- // submatrix.
- {
- // sc = column vector pointer to rows of s
- // tc = column vector pointer to rows of t
- VecPtr<const TYPE> sc(m.data.start, m.colstride);
- VecPtr<TYPE> tc(data.start, colstride);
-
- // sr = row vector pointer to columns of s
- // tr = row vector pointer to columns of t
- // We only need to initialize strides for now
- VecPtr<const TYPE> sr(0, m.rowstride);
- VecPtr<TYPE> tr(0, rowstride);
-
- unsigned nr = nrows;
- if (nr > m.nrows) nr = m.nrows;
- unsigned nc = ncols;
- if (nc > m.ncols) nc = m.ncols;
-
- for (unsigned i = 0; i<nr; i++) {
- // Note that only pointers are copied below, not the strides!
- tr = tc; // Point to current row of t
- sr = sc; // Point to current row of s
- for (unsigned j = 0; j<nc; j++) {
- *tr = *sr;
- tr++; // Next column
- sr++; // Ditto
- }
- tc++; // Next row
- sc++; // Ditto
- }
- nrows = nr; // New size of matrix, may be smaller
- ncols = nc;
- }
-
- template<class TYPE>
- void Matrix<TYPE>::Share(const Matrix<TYPE> &m)
- // Shares data with another matrix.
- {
- data.Share(m.data);
- nrows = m.nrows; ncols = m.ncols;
- colstride = m.colstride; rowstride = m.rowstride;
- }
-
-
- template<class TYPE>
- Matrix<TYPE>::Matrix(unsigned nr, unsigned nc, const TYPE *s)
- // Constructs a row-major matrix with nr rows and nc columns.
- // If size isn't zero, and s isn't zero, then we copy the
- // low-level C array s into the matrix. If null vector is
- // returned from data constructor, we set up the matrix
- // null as well.
- : data(nr * nc, s)
- {
- if (data.IsNull()) {
- nrows = 0; ncols = 0; colstride = 1; rowstride = 1;
- }
- else {
- nrows = nr; ncols = nc; colstride = nc; rowstride = 1;
- }
- }
-
- template<class TYPE>
- Matrix<TYPE>::Matrix(const Matrix<TYPE> &m)
- // Copy constructor that shares all of the matrix m.
- : data(m.data)
- {
- if (data.IsNull()) {
- nrows = 0; ncols = 0; colstride = 1; rowstride = 1;
- }
- else {
- nrows = m.nrows; ncols = m.ncols;
- colstride = m.colstride; rowstride = m.rowstride;
- }
- }
-
- template<class TYPE>
- Matrix<TYPE>::Matrix(const Matrix<TYPE> &m, SliceType styp,
- unsigned sr, unsigned sc,
- unsigned nr, unsigned nc)
- // Constructor that constructs a submatrix of matrix m.
- // If styp==SHARED, it means to share the data with m.
- // NOTE: If sharing, we initially create a null vector, and
- // then we immediately rebind to shared vector. If copying,
- // a row-major sub matrix is created, and if nr == 0,
- // then m.nrows is used. If nc == 0, then m.ncols is used.
- // WARNING: No checks are made on the consistency of the
- // input parameters. Caller beware.
- : data((styp == SHARED) ?
- 0 : ((nr ? nr : m.nrows) * (nc ? nc : m.ncols)))
- {
- unsigned start_ofs, n;
- if (nr) {
- nrows = nr;
- }
- else {
- nrows = m.nrows;
- sr = 0;
- }
- if (nc) {
- ncols = nc;
- }
- else {
- ncols = m.ncols;
- sc = 0;
- }
- if (styp == SHARED) { // Sharing
- // When sharing, strides are always same as parent strides
- colstride = m.colstride;
- rowstride = m.rowstride;
- // Compute length of underlying vector and offset
- // Either colstride or rowstride == 1.
- if (rowstride == 1) {
- n = colstride * (nrows-1) + ncols;
- }
- else {
- n = rowstride * (ncols-1) + nrows;
- }
- start_ofs = sr * colstride + rowstride * sc;
- data.Share(Vector<TYPE>(m.data, SHARED, n, 1, start_ofs));
- }
- else {
- if (data.IsNull()) {
- nrows = 0; ncols = 0; colstride = 1; rowstride = 1;
- }
- else {
- // Setup as a row-major matrix
- colstride = ncols; rowstride = 1;
- // Copy data from shared submatrix into allocated space
- // Note that the constructor is called recursively here,
- // to create a shared submatrix used for the copy.
- Copy(Matrix<TYPE>(m, SHARED, sr, sc, nrows, ncols));
- }
- }
- }
-
- template<class TYPE>
- Matrix<TYPE> Matrix<TYPE>::Clone() const
- // Return a clone of this matrix. This clone will
- // be unique, (with vector rep refcnt = 1), and
- // will be row-major. (THus, it's not precisely a clone.)
- // Note: If allocation fails, a null matrix is returned.
- {
- Matrix<TYPE> temp(nrows, ncols);
- temp.Copy(*this);
- return temp;
- }
-
- template<class TYPE>
- int Matrix<TYPE>::EnsureUnique()
- // Ensures that this matrix uniquely owns its matrix data.
- // (ie. the vector reference count is 1).
- // Might have to copy matrix data to ensure this.
- // Returns 1 if can make unique, 0 if can't (allocation
- // for copy failed.)
- {
- if (!IsUnique()) { // Need to copy to make unique
- Matrix<TYPE> &c = Clone(); // Attempt to copy
- if (c.IsNull()) return 0; // Couldn't copy
- Share(c); // Share with copy
- }
- return 1;
- }
-
-
- template<class TYPE>
- Matrix<TYPE> Matrix<TYPE>::Transpose()
- // Returns a transpose of this matrix. Does not have to move
- // the elements of the matrix around, just merely changes
- // interpretation between row-major and column-major ordering.
- {
- Matrix<TYPE> t(*this); // Remember, copy constructor shares
-
- // Interchange number of rows and cols
- unsigned temp = t.nrows;
- t.nrows = t.ncols;
- t.ncols = temp;
-
- // Interchange row stride and column stride
- temp = t.colstride;
- t.colstride = t.rowstride;
- t.rowstride = temp;
- return t;
- }
-
-
- #ifndef NO_RANGE_CHECK
-
- template<class TYPE>
- unsigned Matrix<TYPE>::CheckRow(unsigned i) const
- // Check for row index being in bounds. If not in
- // bounds, call the error handler.
- {
- if (i >= nrows) i = HandleRangeErr(i, nrows);
- return i;
- }
-
- template<class TYPE>
- unsigned Matrix<TYPE>::CheckCol(unsigned i) const
- // Check for column index being in bounds. If not
- // in bounds, call the error handler.
- {
- if (i >= ncols) i = HandleRangeErr(i, ncols);
- return i;
- }
-
- #endif
-
-
- template<class TYPE>
- TYPE &Matrix<TYPE>::operator()(unsigned r, unsigned c)
- // Two-dimensional subscripting for non-const matrices.
- // Note that either colstride or rowstride will be one.
- {
- return data.start[CHECKROW(r)*colstride + CHECKCOL(c)*rowstride];
- }
-
- template<class TYPE>
- const TYPE &Matrix<TYPE>::operator()(unsigned r, unsigned c) const
- // Two-dimensional subscripting for const matrices.
- // Note that either colstride or rowstride will be one.
- {
- return data.start[CHECKROW(r)*colstride + CHECKCOL(c)*rowstride];
- }
-
- template<class TYPE>
- Matrix<TYPE> &Matrix<TYPE>::operator=(const TYPE &x)
- // Set all elements in the matrix to the value x.
- // Assumes a worst case non-contiguous sub-matrix.
- {
- // tc = column vector pointer to rows of t
- // tr = row vector pointer to columns of t
- VecPtr<TYPE> tc(data.start, colstride);
- VecPtr<TYPE> tr(data.start, rowstride);
- for (unsigned i = 0; i<nrows; i++) {
- tr = tc; // Remember strides aren't assigned!
- for (unsigned j = 0; j<ncols; j++) {
- *tr = x;
- tr++; // Next column
- }
- tc++; // Next row
- }
- return *this;
- }
-
-
- template<class TYPE>
- Vector<TYPE> Matrix<TYPE>::Row(unsigned r, SliceType styp)
- // Return a row slice of a matrix. Remember, either colstride
- // or rowstride is 1.
- {
- return Vector<TYPE>(data, styp,
- ncols, rowstride, CHECKROW(r)*colstride);
- }
-
- template<class TYPE>
- const Vector<TYPE> Matrix<TYPE>::Row(unsigned r, SliceType styp) const
- // Return a row slice of a matrix. Remember, either colstride
- // or rowstride is 1.
- {
- return Vector<TYPE>(data, styp,
- ncols, rowstride, CHECKROW(r)*colstride);
- }
-
- template<class TYPE>
- Vector<TYPE> Matrix<TYPE>::Col(unsigned c, SliceType styp)
- // Return a column slice of a matrix. Remember, either colstride
- // or rowstride is 1.
- {
- return Vector<TYPE>(data, styp,
- nrows, colstride, CHECKCOL(c)*rowstride);
- }
-
- template<class TYPE>
- const Vector<TYPE> Matrix<TYPE>::Col(unsigned c, SliceType styp) const
- // Return a column slice of a matrix. Remember, either colstride
- // or rowstride is 1.
- {
- return Vector<TYPE>(data, styp,
- nrows, colstride, CHECKCOL(c)*rowstride);
- }
-
- template<class TYPE>
- Vector<TYPE> Matrix<TYPE>::Diag(SliceType styp)
- // Return a diagonal slice of a square matrix. If the
- // matrix isn't square, we use the smallest dimension
- // for the diagonal length.
- {
- unsigned dlen = (nrows <= ncols) ? nrows : ncols;
- unsigned diag_stride = (rowstride == 1) ? colstride : rowstride;
- diag_stride++;
- return Vector<TYPE>(data, styp, dlen, diag_stride, 0);
- }
-
- template<class TYPE>
- const Vector<TYPE> Matrix<TYPE>::Diag(SliceType styp) const
- // Return a diagonal slice of a square matrix. If the
- // matrix isn't square, we use the smallest dimension
- // for the diagonal length.
- {
- unsigned dlen = (nrows <= ncols) ? nrows : ncols;
- unsigned diag_stride = (rowstride == 1) ? colstride : rowstride;
- diag_stride++;
- return Vector<TYPE>(data, styp, dlen, diag_stride, 0);
- }
-
- template<class TYPE>
- Vector<TYPE> Matrix<TYPE>::All(SliceType styp)
- // Returns a 1D vector with all of the data for the matrix.
- // If it isn't possible for the 1D data to be contiguous,
- // (as will be the case for some submatrices), then a
- // null vector is returned.
- // ASSUMES either colstride or rowstride == 1.
- {
- if (ncols == colstride || nrows == rowstride)
- return Vector<TYPE>(data, styp, nrows * ncols, 1, 0);
- else return Vector<TYPE>(); // A null vector
- }
-
-
- template<class TYPE>
- const Vector<TYPE> Matrix<TYPE>::All(SliceType styp) const
- // Returns a 1D vector with all of the data for the matrix.
- // If it isn't possible for the 1D data to be contiguous,
- // (as will be the case for some submatrices), then a
- // null vector is returned.
- // ASSUMES either colstride or rowstride == 1.
- {
- if (ncols == colstride || nrows == rowstride)
- return Vector<TYPE>(data, styp, nrows * ncols, 1, 0);
- else return Vector<TYPE>(); // A null vector
- }
-