Category : C++ Source Code
Archive   : BLFMATH.ZIP
Filename : MATRIX.MTH

 
Output of file : MATRIX.MTH contained in archive : BLFMATH.ZIP
/////////////////////////////////////////////////////////////
// matrix.mth: Matrix class template methods
// Copyright(c) 1993 Azarona Software. All rights reserved.
/////////////////////////////////////////////////////////////

template
void Matrix::Copy(const Matrix &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 sc(m.data.start, m.colstride);
VecPtr 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 sr(0, m.rowstride);
VecPtr 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 // 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 *tr = *sr;
tr++; // Next column
sr++; // Ditto
}
tc++; // Next row
sc++; // Ditto
}
nrows = nr; // New size of matrix, may be smaller
ncols = nc;
}

template
void Matrix::Share(const Matrix &m)
// Shares data with another matrix.
{
data.Share(m.data);
nrows = m.nrows; ncols = m.ncols;
colstride = m.colstride; rowstride = m.rowstride;
}


template
Matrix::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
Matrix::Matrix(const Matrix &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
Matrix::Matrix(const Matrix &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(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(m, SHARED, sr, sc, nrows, ncols));
}
}
}

template
Matrix Matrix::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 temp(nrows, ncols);
temp.Copy(*this);
return temp;
}

template
int Matrix::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 &c = Clone(); // Attempt to copy
if (c.IsNull()) return 0; // Couldn't copy
Share(c); // Share with copy
}
return 1;
}


template
Matrix Matrix::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 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
unsigned Matrix::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
unsigned Matrix::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
TYPE &Matrix::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
const TYPE &Matrix::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
Matrix &Matrix::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 tc(data.start, colstride);
VecPtr tr(data.start, rowstride);
for (unsigned i = 0; i tr = tc; // Remember strides aren't assigned!
for (unsigned j = 0; j *tr = x;
tr++; // Next column
}
tc++; // Next row
}
return *this;
}


template
Vector Matrix::Row(unsigned r, SliceType styp)
// Return a row slice of a matrix. Remember, either colstride
// or rowstride is 1.
{
return Vector(data, styp,
ncols, rowstride, CHECKROW(r)*colstride);
}

template
const Vector Matrix::Row(unsigned r, SliceType styp) const
// Return a row slice of a matrix. Remember, either colstride
// or rowstride is 1.
{
return Vector(data, styp,
ncols, rowstride, CHECKROW(r)*colstride);
}

template
Vector Matrix::Col(unsigned c, SliceType styp)
// Return a column slice of a matrix. Remember, either colstride
// or rowstride is 1.
{
return Vector(data, styp,
nrows, colstride, CHECKCOL(c)*rowstride);
}

template
const Vector Matrix::Col(unsigned c, SliceType styp) const
// Return a column slice of a matrix. Remember, either colstride
// or rowstride is 1.
{
return Vector(data, styp,
nrows, colstride, CHECKCOL(c)*rowstride);
}

template
Vector Matrix::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(data, styp, dlen, diag_stride, 0);
}

template
const Vector Matrix::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(data, styp, dlen, diag_stride, 0);
}

template
Vector Matrix::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(data, styp, nrows * ncols, 1, 0);
else return Vector(); // A null vector
}


template
const Vector Matrix::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(data, styp, nrows * ncols, 1, 0);
else return Vector(); // A null vector
}


  3 Responses to “Category : C++ Source Code
Archive   : BLFMATH.ZIP
Filename : MATRIX.MTH

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/