A matrix class with serialization and advanced input/output functions






4.53/5 (15 votes)
A Matrix class derived from CObject with serialization and operator overloading
Overview
Matrices, do you hate them? I do, and they turn up all over the place in the projects I work with. So over time
I have developed a class CMatrix
to handle all the things we need, and some I expect to need in the future.
How the data is handled
First lets take an overview of how the class handles the data. The matrix data is allocated in
a flat array of double
s with an integer reference counter at the end of the array. As the matrix is dynamic, we
use a reference count system to avoid efficiency hits when assigning/copying one matrix into another. Two object can point to
the same data, and they only diverge when one of them changes the data, getting its own copy of the data at that point.
The data is only deleted when the last reference to it is being deleted. This has advantages for objects returned by function
calls by value, and which are assigned by operator=
, as there is little penalty in assigning a pointer compared to
a new
/copy operation.
Serialization
The CMatrix
class inherits directly from CObject
and is full serialization compatible.
CMatrixHelper
A small helper class has been added to allow a simulated CMatrix::operator[][]
to work. I stole
this idea shamelessly from Alex Chirokov's article 2D Matrix
Container with [][] indexing. A nice way of doing it. Note also that you should not be creating any objects of this type in your
own code. It is used for this purpose only.
Robustness
In DEBUG mode, the code compiles with 0 warnings/errors and has extensive ASSERTion checking through out, so it should catch any problems that you have (or I have) in code. Most of the functionality has been thoroughly checked, but I would recommend checking your results, just in case!
Constructors
You can construct a matrix object using the following methods:
CMatrix()
Constructs a 1 * 1 array, this is the default constructor.CMatrix(CMatrix& other)
Copy constructorCMatrix(nCols, nRows)
Constructs a matrix ofnCols * nRows
dimensions. All data is 0.CMatrix(size, diagonal)
Constructs a square matrix with or without 1's on the diagonal.CMatrix(VARIANT)
Constructs aCMatrix
object from a 2 dimensionSAFEFARRAY
variant.
As a note, any non-initialized matrix elements will be set to 0 on construction.
Operators overloaded
The following operators have been overloaded:
operator=(CMatrix)
For standard assignment.
Arithmatic
operator+(CMatrix)
Adds 2 matrices together, must be the same sizeoperator-(CMatrix)
Subtracts 1 matrix from another, must be the same sizeoperator*(CMatrix)
Multiples 2 matrices together, the two inner dimensions must be the same, e.g. 3*2 by 2*3operator+=(CMatrix)
Adds one matrix onto the current matrix, must have same dimensions.operator-=(CMatrix)
Subtracts one matrix from the current matrix, must have same dimensions.operator*=(CMatrix)
Mutiples the current matrix by the other matrixoperator*=(double)
Multiples all matrix elements by the given valueoperator*(CMatrix, double)
Multiples all elements by the given value, returning a new matrix
Comparison
operator==(CMatrix)
For matrix comparison, returnstrue
if identical,false
otherwise.
Element access
operator[](int)
Works with the classCMatrixHelper
to simulate aoperator[][]
.
Get/Set functions
Two standard access function are provided.:
GetElement(nCol, nRow)
returns the given element valueSetElement(nCol, nRow, value)
Sets the given element to a different value
Other matrix functions
GetNumColumns()
Returns the matrices columns dimensionGetNumRows()
Returns the matrices rows dimensionSumColumn(column)
Returns the sum of all elements in the given columnSumRow(row)
Returns the sum of all elements in the given rowSumColumnSquared(column)
Same asSumColumn()
but the return value is squaredSumRowSquared(row)
Same asSumRow()
but the return value is squaredGetNumericRange(min, max)
Returns the lower and upper values of elements in the matrixGetSafeArray()
Returns aVARIANT
with a copy of theCMatrix
data in aSAFEARRAY
. Note that theVARIANT
should be cleared usingVariantClear(var)
unless you pass theVARIANT
to a different program (e.g. a COM component/VB) as it becomes their responsibility.CopyToClipboard()
Places theCMatrix
data in the clipboard as CSV text, use this when debugging etcWriteAsCSVFile(filename)
Writes the matrix to a CSV fileReadFromCSVFile(const CString& filename)
Creates a new matrix from a CSV file.Dump()
TRACEs the matrix content to the debug streamAssertValid()
ASSERTs if the object is in an invalid state
Transposition
GetTransposed()
Returns a new matrix which is a Transpose of the one called onTranspose()
Transposes the current matrix
Inversion
GetInverted()
Returns the inversion of the current matrixInvert()
Inverts the current matrix
Covariant (A' * A)
Covariant()
Returns the Covariant of the current matrix
Normalisation
GetNormalised(min, max)
Returns the matrix with all values scaled between min and maxNormalise(min, max)
Normalizes all values in the matrix between min and max
Concatenation
GetConcatinatedColumns(CMatrix)
Returns a new matrix with the other matrix added onto the right hand sideConcatinateColumns(CMatrix)
Concatenates the additional columns onto the current matrixGetConcatenatedRows(CMatrix)
Returns a new matrix with the other matrix added onto the bottom of the current matrixConcatinateRows(CMatrix)
Concatenates the additional rows onto the current matrixAddColumn(double*)
Adds a new column onto the current matrixAddRow(double*)
Adds a new row onto the current matrix
Extraction/substitution
ExtractSubMatrix(x, y, x_size, y_size)
Extract a sub matrix from a larger matrixSetSubMatrix(x, y, CMatrix)
Substitutes a larger matrices elements with those from another matrixExtractDiagonal()
Returns a x * 1 matrix with the values from the diagonal - square matrices onlyGetSquareMatrix()
Returns a square matrix of the smaller dimension, by stepping over rows/columns to make the matrix squareMakeSquare()
Squares the current matrix by stepping over rows/columns
Other notes
All the code to handle the allocation/deallocation of matrix data and the reference counting is not covered here in the class interface
as they are all private
functions. You can see the documentation in the source code comments. (wow comments....:-D)
If you find any bugs or have some enhancements for the class, I would be happy if you would pass them along, and I will endeavour to keep the class fully up to date here.
Updates
13th August 2002
- A small problem with
CMatrixHelper
when usingoperator[][]
for element read access was fixed by making the return objectconst
. - An invalid ASSERTion error in
ExtractSubMatrix
was fixed. - The
operator=
forCMatrixHelper
now copies all member variables across into the target object.
2nd July 2002
- A small typo in
CMatrix::Invert()
was fixed. Thanks to Jamie Plowman for spotting it. - As suggested, I made the class
CMatrixHelper
constructorsprotected
and madeCMatrix
afriend
so that onlyCMatrix
can construct objects, not a user.
Enjoy!