11,573,084 members (64,487 online)

# A generic, reusable, and extendable matrix class

, 19 Apr 2006 236.8K 6.1K 94
 Rate this:
An article describing the use of a generic matrix class and how it is implemented.

## Introduction

There are times when it is necessary to store data in a matrix so as to make programming easier. This is especially true in scientific programming where matrices are often used in calculations. However, there is no built-in Matrix type in C++.

There are several ways to implement a matrix in C++. The easiest involve arrays or pointers. For example, to create a simple matrix using an array, just do `double matrix[10][10];` to create a variable ‘matrix’ that has 10 rows and 10 columns. Programming books will tell you that the data isn't exactly stored in a two-dimensional form, but that is of no interest to us. What is important is that we can easily access the elements in the matrix; for example, to access the element in row 2 and column 5, we do `matrix[1][4]` taking into account that arrays start from 0. For ease of explaining, for now on, all matrices start from zero, thus if I refer to row 2 and column 5, it is matrix[2][5]. The disadvantage of using arrays as matrices is that the size of the rows and columns must be fixed at compile-time.

To dynamically adjust the size of the matrix, we can create a matrix using pointers. We can use:

`double* matrix = new double[100]`

or

```double** matrix = new double*[10];
for(int i=0; i<10;++i)
matrix[i] = new double[10];```

The first form is a special type of matrix in that, to access an element in row `i` and column `j`, you need to do `matrix[i*10+j]`. This is obviously not as intuitive as `matrix[i][j]`. However, it has its own merits in that the matrix is simpler to create. The second form is slightly harder to create a matrix, but accessing an element is the same as in the array, i.e. `matrix[i][j]`. The disadvantage of using pointers is that you must remember to call `delete[]` on the matrix after using it, otherwise there will be a memory leak.

A third way of creating a matrix is to use STL containers like vectors. We can nest two vectors together, like `vector<vector<double> > matrix`. To access an element, we can still use `matrix[i][j]`. In addition, we can get the size of the matrix relatively easily, through the `size` function of the vector container. We can also easily increase the size of the matrix by using the `resize` function. Another advantage of using STL containers is it is not prone to memory leaks unlike pointers.

Mathematical operations are harder to perform on matrices implemented using arrays, pointers, or STL containers. For example, to add two matrices together, you can't write "`matrixA + matrixB`". Instead, you must write two loops to add the individual elements together. To enable ease of calculations and also to provide useful functions for manipulating matrices, we can create a matrix class. Many programmers have created their own matrix classes. Among the more notable are the simple matrix class implemented for use in Numerical Recipes in C++1, the Matrix Template Library (MTL) developed by Open Systems Laboratory at Indiana University2, and the Matrix Expression Template implemented by Masakatsu Ito3.

Since there are already excellent matrix classes available, why is there a need to create another one? There are several motivations for creating a new matrix class which is the focus of this article. First, the available matrix classes doesn't have all the features that I need. To add extra functions to these matrix classes will require an understanding of the implementation of the classes, which is time-consuming. Second, as an amateur programmer, creating a new matrix class will improve my programming skills as I will have to consider the implementation problems thoroughly. The third reason is that I will not have to spend time learning about how to use the other matrix classes. Although some are quite straightforward, some are not. Implementing my own matrix will eliminate this learning curve.

The matrix class that I have implemented is not perfect. It is not meant to be the best matrix class. Before proceeding further, the deficiencies of the matrix class are listed below:

1. Only dense matrix storage type has been implemented. Other storage types like sparse matrix, triangular matrix, diagonal matrix etc., have not been implemented.
2. The performance of the matrix is not the fastest among the available matrix classes. Although I have not done extensive comparison tests, I believe that my matrix class is not the fastest in terms of calculations.
3. The number of functions available for manipulating matrices is less than that in some available matrix classes.
4. The most important deficiency is that this class can only be compiled by compilers that are compliant to the C++ standard. I have only tested the present version on Visual C++ 2005.

Other than the motivations for creating this matrix class, my matrix class hase advantages over other matrix classes. Otherwise, I would not have published this class. The advantages are:

1. The matrix can be used to store numerical types as well as non-numerical types. When storing non-numerical types, the mathematical functions are not available for use, and will give compiler errors if accidentally used, instead of causing errors during runtime.
2. The functions available for performing matrix calculations are intuitive to use, unlike those in some matrix classes.
3. Although other storage types are not implemented, they can be created relatively easily by the user by following the `MatrixStorageTemplate` provided.
4. STL-like functions and typedefs are available for users familiar with STL containers. Certain STL algorithms can also be performed on the matrix.

For those who have decided that this class may be suitable for them or who wishes to learn certain programming techniques like using policies with templates and expression templates, the rest of the article is divided into the following sections. The first section gives an overview of the functions available. The second section gives an example of how to use the matrix class. The third section discusses the implementation of the matrix class, giving details of using policies for generic programming and the use of expression templates to speed up certain matrix calculations.

## Available Matrix Functions

The only class that the user needs to use is the template `Matrix<ValueT,MatrixTypeP,MathP>` class. `ValueT` is a type name for the type of data that will be stored in the matrix. It can be numerical types like int, double, or complex, or numerical types like `char*`, or even user-defined classes. `MatrixTypeP` is a template class policy for the data storage type. At the present moment, only `DenseMatrix` is available. `MathP` is a template class policy for mathematical functions. Three choices are available: `MathMatrix`, `MathMETMatrix`, and `NonMathMatrix`.

No matter what type of matrix is created, the following are common for all types of matrixes:

### STL-like typedefs:

 `value_type` type of data stored in matrix. `reference` reference to type of data stored in matrix. `const_reference` const reference to type of data stored in matrix. `pointer` pointer to type of data stored in matrix. `const_pointer` const pointer to type of data stored in matrix. `difference_type` difference types for pointer calculations. `size_type` size type.

### Constructors, destructor, copy constructors, and assignment:

 `Matrix` Default constructor `Matrix(size_type sizeRow, size_type sizeCol, value_type x=value_type)` Constructor requiring number of rows, columns, and initial value for elements. `Matrix(size_type sizeRow, size_type sizeCol, value_type* am)` Constructor requiring number of rows, columns, and a 1D array containing initial values for elements. `Matrix(size_type sizeRow, size_type sizeCol, value_type** am)` Constructor requiring number of rows, and a 2D array containing initial values for elements. `~Matrix` Destructor. `Matrix(const Matrix& m)` Copy constructor. `template class MatrixTypePT, template class MathPT>` `Matrix(const Matrix& m)` Copy constructor taking any matrix of inter-convertible `ValueT`. `Matrix& operator=(Matrix m)` Assignment operator taking the same type of matrix. `template class MatrixTypePT,template class MathPT>` `Matrix& operator=(Matrix m)` Assignment operator taking any matrix of inter-convertible `ValueT`. `Matrix& operator=(const value_type* am)` Copy a 1D array into the matrix. The number of array elements must be equal or larger than the number of matrix elements, and the sequence of array elements must be a concatenation of rows to be put into the matrix. `Matrix& operator=(const value_type** am)` Copy a 2D array into the matrix. The size of the array must be the same as the matrix.

### Matrix member functions

 `void clear` Erase matrix. `bool empty const` Check if matrix is empty. `void resize(size_type sizeRow, size_type sizeCol, value_type x=value_type)` Resize matrix, filling new elements with supplied or default values and removing extra elements. `void swap(Matrix& m)` Swap the contents of another matrix with the present matrix. The matrix to be swapped must be of the same type. `void swaprows(size_type i1, size_type i2)` Swap two rows in the matrix. `void swapcols(size_type j1, size_type j2)` Swap two columns in the matrix. `bool operator==(const Matrix& m) const` `bool operator!=(const Matrix& m) const` Comparison operators. `void Update` Update matrix. `const_reference operator(size_type posRow, size_type posCol)` `const reference operator(size_type posRow, size_type posCol)` `const_reference at(size_type posRow, size_type posCol)` `const reference at(size_type posRow, size_type posCol)` Member accessor functions

### Row and Column iterator functions

 `size_type size() const` Return the total number of rows/columns. `template void insert(size_type rowNo, const ForwardIterator& first)` Insert row/column at specified row/column. `void erase(size_type rowNo)` Erase row/column at specific row/column. `template void push_back(const ForwardIterator& first)` Add row/column at end of matrix. `template void push_front(const ForwardIterator& first)` Add row/column at beginning of matrix. `void pop_back()` Remove row/column at end of matrix. `void pop_front()` Remove row/column at beginning of matrix. `iterator begin()` `const_iterator begin() const` `iterator end()` `const_iterator end() const` `reverse_iterator rbegin()` `const_reverse_iterator rbegin() const` `reverse_iterator rend()` `const_reverse_iterator rend() const` Functions to obtain iterators to data in matrix.

### Functors operating on Matrix

 `MatrixT Transpose()(const MatrixT& matrix)` `void Transpose()(const MatrixT& matrix, MatrixT& transposedMatrix)` Get the transpose of a matrix, i.e., swap rows with columns and vice versa. The first form returns the transposed matrix. The second saves the transposed matrix into a variable which is passed in. `MatrixT Diagonal()(const MatrixT& matrix)` `void Diagonal()(const MatrixT& matrix, MatrixT& diagonalMatrix)` Get the main diagonal of a matrix, or put a vector into the main diagonal of a matrix. The first form returns the diagonal matrix. The second saves the diagonal matrix into a variable which is passed in. `MatrixT ovariance()(const MatrixT& matrix)` `void Covariance()(const MatrixT& matrix, MatrixT& covarianceMatrix)` Get the covariance of a matrix. The first form returns the covariance matrix. The second saves the covariance matrix into a variable which is passed in. `MatrixT Power()(const MatrixT& matrix, const value_type& power)` `void Power()(const MatrixT& matrix, MatrixT& powerMatrix, const value_type& power)` Get a matrix with all its elements raised to a defined power. The first form returns the powered matrix. The second saves the powered matrix into a variable which is passed in. `MatrixT Mean()(const MatrixT& matrix)` `void Mean()(const MatrixT& matrix, MatrixT& meanMatrix)` Get a row vector with the mean of each column of a matrix. The first form returns the row vector. The second saves the row vector into a variable which is passed in. `MatrixT Median()(const MatrixT& matrix)` `void edian()(const MatrixT& matrix, MatrixT& medianMatrix)` Get a row vector with the median of each column of a matrix. The first form returns the row vector. The second saves the row vector into a variable which is passed in. `MatrixT Sum()(const MatrixT& matrix)` `void Sum()(const MatrixT& matrix, MatrixT& sumMatrix)` Get a row vector with the sum over each column of a matrix. The first form returns the row vector. The second saves the row vector into a variable which is passed in. `MatrixT CumulativeSum()(const MatrixT& matrix)` `void CumulativeSum()(const MatrixT& matrix, MatrixT& cumulativeSumMatrix)` Get the cumulative sum of elements of a matrix. The first form returns the cumulative sum matrix. The second saves the cumulative sum matrix into a variable which is passed in.

## Matrix Class Example

```##include <span class="code-keyword"><string>
</span>
#include <span class="code-string">"Matrix.hpp"
</span>

using namespace std;
using namespace YMatrix;

int main(int argc, char* argv[])
{
// typedef for non-mathematical matrix with string as datatype.
typedef Matrix<string,DenseMatrix,NonMathMatrix> MatrixNM;
// typedef for normal mathematical matrix with double as datatype.
typedef Matrix<double,DenseMatrix,MathMatrix> MatrixM;
// typedef for mathematical matrix implementing expression template.
typedef Matrix<double,DenseMatrix,MathMETMatrix> MatrixEM;
// typedef for normal mathematical row vector with double as datatype.
typedef RowVector<double,DenseMatrix,MathMatrix> RVectorM;
// typedef for normal mathematical col vector with double as datatype.
typedef ColVector<double,DenseMatrix,MathMatrix> CVectorM;

int i, j;

// construct a 3 x 4 matrix and fill it with 'Hello' for all elements.
MatrixNM stringMatrix(3, 4, "Hello");
// resize matrix to 2,5 and fill new elements with 'World'
stringMatrix.resize(2, 5, "World");
// print matrix.
cout << "First way to print matrix\n";
for (i=0; i<stringMatrix.row.size(); ++i)
{
for (j=0; j<stringMatrix.col.size(); ++j)
{
cout << stringMatrix(i,j) << "\t";
}
cout << "\n";
}
cout << endl;

vector<string> s(5, "New");
stringMatrix.row.insert(1, s.begin());
stringMatrix.col.insert(2, s.begin());
// another way to print matrix
cout << "Second way to print matrix\n";
for (i=0; i<stringMatrix.row.size(); ++i)
{
copy (stringMatrix.row(i).begin(),
stringMatrix.row(i).end(),
ostream_iterator<string>(cout, "\t"));
cout << "\n";
}
cout << endl;

stringMatrix.col.erase(0);
// another way to print matrix
cout << "Third way to print matrix\n";
cout << stringMatrix;

// erase matrix.
cout << "Deleting contents of matrix\n";
stringMatrix.clear();
// check if matrix is empty
cout << (stringMatrix.empty() ?
"Matrix is empty\n" : "Matrix is not empty\n");

// prepare two 3 x 3 arrays
double a1[9] = {1,2,3, 4,5,6, 7,8,9};
double** a2 = new double*[3];
for (i=0; i<3; ++i) a2[i] = new double[3];
for (i=0; i<3; ++i)
{
for (j=0; j<3; ++j)
{
a2[i][j] = 9 - (i*3+j);
}
}

// construct three 3 x 3 matrix with no initial value
MatrixM mathMatrix1(3,3), mathMatrix2(3,3), mathMatrix3;
// fill matrices with array
mathMatrix1 = a1;
mathMatrix2 = a2;
cout << "First matrix:\n" << mathMatrix1;
cout << "Second matrix:\n" << mathMatrix2;
cout << "Element(1,2) of first matrix: " << mathMatrix1.at(1,2) << endl;

// perform mathematical operations on matrix and print the results
cout << "Some mathematical operations\n";
mathMatrix3 = mathMatrix1 + mathMatrix2; cout << mathMatrix3;
mathMatrix3 = mathMatrix1 - mathMatrix2; cout << mathMatrix3;
mathMatrix3 = mathMatrix1 * mathMatrix2; cout << mathMatrix3;
mathMatrix3 = mathMatrix1 * 2; cout << mathMatrix3;
mathMatrix3 = mathMatrix1 + mathMatrix2 * mathMatrix2;
cout << mathMatrix3;
mathMatrix3 += mathMatrix1; cout << mathMatrix3;
mathMatrix3 -= mathMatrix1; cout << mathMatrix3;
mathMatrix3 *= mathMatrix1; cout << mathMatrix3;
mathMatrix3 *= mathMatrix1 + mathMatrix2; cout << mathMatrix3;
mathMatrix3 *= 2; cout << mathMatrix3;

// swap mathMatrix1 and mathMatrix2
mathMatrix1.swap(mathMatrix2);
cout << "Swapping first and second matrix:\n";
cout << "First matrix:\n" << mathMatrix1;
cout << "Second matrix:\n" << mathMatrix2;

// swap row 0 and 1 of mathMatrix1
cout << "Swapping first and second row of first matrix:\n";
mathMatrix1.swaprows(0,1); cout << mathMatrix1;

// swap column 0 and 2 of mathMatrix1
cout << "Swapping first and third column of first matrix:\n";
mathMatrix1.swapcols(0,2); cout << mathMatrix1;

// print transpose of mathMatrix1
cout << "Transpose\n" << Transpose<MatrixM>()(mathMatrix1);

// print diagonal of mathMatrix1
cout << "Diagonal\n" << Diagonal<MatrixM>()(mathMatrix1);

// print covariance of mathMatrix1
cout << "Covariance\n" << Covariance<MatrixM>()(mathMatrix1);

// print power 2 of mathMatrix1
cout << "Power 2\n" << Power<MatrixM>()(mathMatrix1, 2);

// print mean of mathMatrix1
cout << "Mean\n" << Mean<MatrixM>()(mathMatrix1);

// print median of mathMatrix1
cout << "Median\n" << Median<MatrixM>()(mathMatrix1);

// print sum of mathMatrix1
cout << "Sum\n" << Sum<MatrixM>()(mathMatrix1);

// print cumulative sum of mathMatrix1
cout << "CumulativeSum\n" << CumulativeSum<MatrixM>()(mathMatrix1);

// construct three 3 x 3 matrix using the two arrays and mathMatrix1
MatrixEM mathEmatrix1(3, 3, a1);
MatrixEM mathEmatrix2(3, 3, a2);
MatrixEM mathEmatrix3(mathMatrix1);
cout << "First matrix:\n" << mathEmatrix1;
cout << "Second matrix:\n" << mathEmatrix2;
// perform mathematical operations on matrix and print the results
cout << "Some mathematical operations\n";
mathEmatrix3 = mathEmatrix1 + mathEmatrix2; cout << mathEmatrix3;
mathEmatrix3 = mathEmatrix1 - mathEmatrix2; cout << mathEmatrix3;
mathEmatrix3 = mathEmatrix1 * mathEmatrix2; cout << mathEmatrix3;
mathEmatrix3 = mathEmatrix1 * 2; cout << mathEmatrix3;
mathEmatrix3 = mathEmatrix1 + mathEmatrix2 * mathEmatrix2;
cout << mathEmatrix3;
mathEmatrix3 += mathEmatrix1; cout << mathEmatrix3;
mathEmatrix3 -= mathEmatrix1; cout << mathEmatrix3;
mathEmatrix3 *= mathEmatrix1; cout << mathEmatrix3;
mathEmatrix3 *= 2; cout << mathEmatrix3;
// invalid mathematical operation (compare with above)
// mathEmatrix3 *= mathEmatrix1 + mathEmatrix2; cout << mathMatrix3;
// demonstrate speed of expression template
// (can't tell unless timing is done)
mathEmatrix3 = mathEmatrix1 + mathEmatrix2 -
mathEmatrix1 + mathEmatrix2;
cout << mathMatrix3;
// demonstrate interchangably of matrices
mathEmatrix3 = mathMatrix1 + mathEmatrix2; cout << mathEmatrix3;
// get transpose of mathEmatrix3
MatrixEM mathEmatrix3Transposed;
Transpose<MatrixEM>()(mathEmatrix3, mathEmatrix3Transposed);
cout << "Transposed:\n" << mathEmatrix3Transposed;

RVectorM rv(5, 3.0);
cout << rv;
rv.push_back(8); cout << "push_back 8\n" << rv;
rv.push_front(1); cout << "push_front 1\n" << rv;
rv.pop_back(); cout << "pop_back\n" << rv;
rv.pop_front(); cout << "pop_front\n" << rv;
cout << endl;

CVectorM cv(5, 2.6);
cout << cv;
cv.push_back(3.5); cout << "push_back 3.5\n" << cv;
cv.push_front(8.5); cout << "push_front 8.5\n" << cv;
cv.pop_back(); cout << "pop_back\n" << cv;
cv.pop_front(); cout << "pop_front\n" << cv;
cout << endl;
}```

## Implementation Details

### Introduction

This matrix class was designed to be generic and with reusability in mind. The inspiration for this design comes from Andrei Alexandrescu4. Since the matrix was to be generic, templates are essential for the implementation. The matrix must be able to store different types of data, not just numerical data. Thus, a `typename ValueT` must be present to indicate the type of data that is stored.

There are different types of matrices: dense matrix, sparse matrix, triangular matrix, diagonal matrix, etc. Each differs in how the matrix is organized, and how the data is stored. Thus, there should be a policy which determines how the matrix is stored and how the data can be accessed. Hence, a separate class for each kind of matrix should be created. This class will handle the storage and access of the data. The second element in the matrix class template parameter is thus `template<typename> class MatrixTypeP`. At the present moment, `MatrixTypeP` can only be `DenseMatrix`.

The third thing that must be considered when designing the matrix class is that for the matrix to be useful in scientific programming, the matrix should have mathematical operations. However, if the matrix contains non-numerical types, mathematical operations should not be available. This problem can be solved by using a mathematical policy. By implementing a mathematical policy, matrices containing non-numerical types cannot perform mathematical operations and will give compiler-error if this is attempted, whereas mathematical operations will be available for numerical types. Initially, two classes are created to achieve this policy: `MathMatrix` and `NonMathMatrix`, and the third element in the matrix class template parameter is the `template<typename,typename>` class `MathP`. In the initial version of the matrix class, `MathP` was derived from `MatrixTypeP`, and then the matrix class was derived from either of the math classes. This was later changed to the present version where the matrix class was derived from both `MatrixTypeP` and `MathP`, and `MathP` no longer derived from `MatrixTypeP`. In addition, a third math class, `MathMETMatrix`, was created which implements expression templates to increase the performance when performing certain types of matrix calculations. The use of expression templates will be discussed later.

Thus, the skeleton of the matrix class is formed. The matrix class will take in three template arguments which denote the type of data which will be stored, the policy for storing and accessing the data, and the policy for determining whether mathematical operations are available for the matrix. The only thing which was not considered was the dimension of the matrix. The matrix was assumed to be 2-dimensional. Multi-dimensional matrixes were not considered as this would increase the difficulty of the implementation.

The operations of the matrix class was designed to be similar to a STL container. The matrix class implements the various STL-like typedefs like `value_type`, `size_type`, etc. Iterators for iterating through the elements in the matrix were also implemented. Certain common STL container functions like `clear`, `empty`, `resize`, and `swap` were implemented. Others like `assign`, `erase`, `insert`, `front`, `back`, `push_back`, `push_front`, `pop_back`, `pop_front`, `begin`, and `end` were implemented in the row and column iterators.

### Implementation of MatrixTypeP

There are a few basic public functions that any `MatrixTypeP` matrix must have. There must be a default constructor which takes in no argument. There should be constructors which take in the initial size of the matrix as well as the initial values. The initial values can be a default value for all the elements, or from a matrix implemented using arrays or pointers. A copy constructor is essential because of the presence of a raw pointer as a member variable. There should be an assignment operator for copying another similar `MatrixTypeP` matrix, and an assignment operator for copying any matrix class. The `MatrixTypeP` matrix must also implement the resize, swap, and comparison operators. In addition, an `Update` function was added to allow the user to inform the matrix to update itself whenever data is changed. This `Update` function is not used by `DenseMatrix` but it may be necessary for other `MatrixTypeP`.

There are other basic public functions which can theoretically be placed in the final matrix class instead of the `MatrixTypeP` matrix. They are `clear`, `empty`, the various member accessor functions, `operator()`, and `at`, etc. They can theoretically be placed in the final matrix class because their code doesn’t need to be changed for all `MatrixTypeP` matrices. Their implementation is based on common member variables and functions that will be present in all `MatrixTypeP` matrices. However, they are still placed in the `MatrixTypeP` matrix at the present moment, because they provide functions which may be useful for the `MatrixTypeP` matrix to use in the implementation of other functions.

There are two more private functions which should be present in a `MatrixTypeP` matrix. They are `ResizeIterators` and `UpdateIterators`. `ResizeIterators` is used to resize the four private member variables: `rowIteratorStart`, `rowIteratorFinish`, `colIteratorStart`, and `colIteratorFinish`. `UpdateIterators` is used to update the data stored by these four member variables. Initially, there is only `UpdateIterators`. The resizing of the four private member variables is done inside `UpdateIterators`. Later on, the resizing is separate from `UpdateIterators` to form `ResizeIterators` in order to increase the performance of the matrix. The four private member variables are raw pointers which keep information on the iterators which point to the start and end of each row and column. By storing these iterators, the member accessor functions and the various iterator functions can be speeded up and made generic for all `MatrixTypeP`. Initially, the four private member variables were implemented using the STL vector. Then it was changed to use raw pointers, to increase performance.

Finally, each `MatrixTypeP` matrix must implement a row iterator class and a column iterator class. The row iterator is responsible for iterating through a row in the matrix, and the column iterator for iterating through a column. These two iterator classes are the most important aspects of the implementation of a `MatrixTypeP` matrix. I will try to give a detailed explanation on how to implement the iterator classes.

Since the iterator classes are to be similar to an STL container, it should have the various STL-like typedefs. Thus, `iterator_category`, `value_type`, reference, pointer, `size_type`, and `difference_type` are defined.

The iterator should have appropriate constructors. It must have a default constructor which takes in no arguments. It should have a constructor which takes in an iterator (`VectorTypeIterator`) which iterates through a row or column of the type which stores the matrix data. For example, in `DenseMatrix`, the matrix data is stored by a raw pointer of type `value_type*`. Thus, the `VectorTypeIterator` should be of type `value_type*`. If the matrix data is stored by an STL vector, then the `VectorTypeIterator` is of type `std::vector::iterator`. If the matrix data is stored by an STL `deque<deque>`, then the `VectorTypeIterator` is of type `std::deque::iterator`. This `VectorTypeIterator` is stored in a member variable for use in various functions. In addition to the `VectorTypeIterator`, the constructor may take in any variable which may help in the operation of the iterator. For example, the constructor in the column iterator of the `DenseMatrix` takes in the total number of columns in the matrix. It uses this information in its `Subtract`, `Increment`, `Decrement`, and `Advance` functions.

Since the default constructor may be used to construct the iterator, there should be an assignment operator which takes in `VectorTypeIterator`. This is to allow the update of the member variable which stores the `VectorTypeIterator`. Other functions to allow updates of any variables which is necessary for the iterator operation should also be available. For example, there is a `SetCols` function to update the total number of column variables in the column iterator of `DenseMatrix`.

The type of functions which should be present in the iterator will depend on the type of the iterator, i.e., input, output, bidirectional, or random. All types of iterators should implement the `operator*` to allow dereferencing, and `operator->` to allow accessing of matrix elements’ member variables or functions. Friend comparison functions must also be implemented for all types of iterators.

For a random access iterator, it should have pre- and post increment and decrement operators. It should also have `operator-` to determine the distance between two similar iterators. In addition, it should implement `operator+=`, `operator-=`, `operator+`, and `operator-` to allow the iterator to increase or decrease by a certain distance. These functions can be made generic by delegating the jobs to other functions like `Subtract`, `Increment`, `Decrement`, and `Advance`. A random access iterator should also implement the `operator[]` to allow it to act like an array.

#### template<typename ValueT> class DenseMatrix

The implementation of dense matrix has gone through several stages. Initially, `deque<deque<ValueT> >` was used to store the matrix elements. Then, `deque<ValueT>` was used. In the end, `ValueT*` was used to increase the performance of the matrix as the use of STL containers slow matrix calculations greatly. However, the usage of raw pointers in the storage increases the difficulty of implementing the `DenseMatrix` class, slightly. Care must be taken during the implementation to avoid memory leaks. Also, memory leaks may occur when exceptions occur. Since performance is crucial in scientific programming, this disadvantage of using raw pointers is overlooked in this case.

The implementation of iterators is slightly different from that of the template described above. The column iterator uses the template above for implementation, but the row iterator uses a raw pointer `ValueT*`. In the initial version, a class following the template format was used to create the row iterator. Later, it was found that in matrix calculations, repeated use of functions in the row iterator class actually slows down the calculations. Since the storage of data allows the use of raw pointers for the row iterators, raw pointers are used to increase the speed of matrix calculations. The same cannot be done for the column iterator because iterating through a column requires knowledge of the total number of columns in the matrix, and this information needs to be stored and used. Thus, a proper class is needed for the column iterator. Since using the row iterator is faster than using the column iterator, the row iterator should be used when using the `DenseMatrix` storage policy unless it is absolutely necessary to use the column iterator so as to increase the efficiency of the matrix.

Approximate analysis of the speed of matrix calculations using the `DenseMatrix` storage policy indicates that it is nowhere as fast as hand-written loops involving raw pointers or arrays. This is to be expected since the underlying matrix elements are stored under many layers of code, which add a significant overhead. In order to make this matrix class appealing to scientific programmers who require the fast speed of raw pointers, three member variables and a function, which normally should be private or protected, is made public. This is against the principle of encapsulation, but the end justifies the means. The three variables are `rows_` and `cols_`, which contain the total number of rows and columns in the matrix, respectively, and `matrix_` which is a raw pointer `ValueT*` containing the matrix elements. The function which is made public is the `ResizeIterators`. Scientific programmers who desire speed, yet convenience, can make use of the various functions of the matrix class to help maintain the matrix, and when doing calculations, can directly access the matrix storage variable, `matrix_`, to perform fast lookup, assignment, or calculations, by using it as an ordinary raw pointer. The `ResizeIterators` is exposed so that if the programmer ever resizes the `matrix_` or points the `matrix_` to another matrix manually, the internal iterators can be updated so that the structure of the matrix is maintained.

### Implementation of MathP

The functions which are to be implemented in a `MathP` class must support addition, subtraction, dot multiplication, and scalar multiplication of the matrix when the data is of numerical type. When the data is of non-numerical type, all these functions should not be available. There are two `MathP` classes which provide mathematical operations, and one which does not. The two that does, implement the `operator+=`, `operator+`, `operator-=`, `operator-`, `operator*=`, and `operator*`.

The implementation of a `MathP` class presents a unique problem. The `MathP` class is a base class from which the final matrix class inherits from. It is separated from the storage class, thus it has no idea of how the matrix elements are stored. Since the storage class is also in charge of providing accessor functions, the `MathP` class effectively has no way of accessing the matrix elements. But to perform matrix calculations, it has to have access to the matrix elements. The way to overcome this problem is to pass in a pointer representing the final matrix class to the `MathP` class so that it can have access to the matrix elements. The `MathP` class must maintain a pointer variable that points to its child matrix. Thus, the final declaration of a `MathP` class is `template<typename ValueT, typename MatrixT>`, where `MatrixT` is the type of the final matrix class. Since the `MathP` class cannot exist without a pointer to its child matrix, there is no default constructor for a `MathP` class which takes in no arguments. There is only a constructor which requires a pointer to the child matrix.

#### template<typename ValueT, typename MatrixT> class MathMatrix

The `MathMatrix` class is a relatively simple class. The main function of this class is to provide mathematical operators to the final matrix class so that matrix calculations can be done intuitively using mathematical operators.

The mathematical operators are implemented in such a way that the `operator+` and `operator-` calls the functions `operator+=` and `operator-=` respectively to perform their functions. This technique is also used to implement the `operator*=` and `operator*` for scalar multiplication. However, for dot multiplication, the situation is reversed. The `operator*=` calls the functions `operator*` to perform its function. The reason for this reversal is because it is more efficient. During matrix dot multiplication, a temporary matrix is created to store the results of the multiplication. If this code resides in `operator*=` instead of in `operator*`, when using `operator*`, three temporary matrices will be created, instead of the usual two, in `operator+` and `operator-`. This reduces the efficiency of the matrix dot multiplication. By putting the code in `operator*`, only two temporary matrixes are created, so it is more efficient. Approximate analysis reveals that this does not degrade the performance of the `operator*=`, so there is no need to duplicate the multiplication code in `operator*=`.

The `MathMatrix` class implements the checking of the matrix sizes before performing the various matrix calculations. It will return an exception if the two matrixes cannot be added, subtracted, or dot multiplied together because of wrong sizes. This checking does not slow down the matrix calculations appreciably, but can be removed if really necessary for performance.

#### template<typename ValueT, typename MatrixT> class MathMETMatrix

`MathMETMatrix` uses a technique called expression templates to increase the performance of certain types of matrix addition and subtraction. Expression templates was introduced by Todd Veldhuizen5. To explain expression templates, consider the problem below.

A, B, C, D, E, F are matrices. Consider the code `A = B + C + D + E + F;`. To perform matrix calculations, the compiler will first add `B` and `C` together, then add the results to `D`, then the results to `E`, and the results to `F`, before putting the final result into `A`. Thus, several temporay matrices are created during the addition, and this decreases the performance greatly. What expression templates hope to achieve is to eliminate all these unnecessary temporary matrices by creating code equivalent to the following:

```for (size_t i=0; i<rows; ++i)
{
for (size j=0; j<cols; ++j)
{
A(i,j) = B(i,j) + C(i,j) + D(i,j) +E(i,j) + F(i,j);
}
}```

To achieve the above, templates are used, and several supporting classes are needed. I will not go into the theory of expression templates. Rather, I will explain the creation of the various supporting template classes.

The first template class that is needed is a wrapping class for the Operations type. It is named MET. In the `MathMETMatrix` class, there is only one type of Operations, that is `METElementBinaryOp`, which perform binary operations on the elements in the matrix. The MET main job is to wrap around `METElementBinaryOp`, providing access to the functions present in `METElementBinaryOp`. To do that, it maintains a variable for the template class `METElementBinaryOp`. MET is necessary because it helps to bind different `METElementBinaryOp` template classes together. Without MET, the whole concept of expression templates cannot work.

The next template class is the Operations types. Presently, there is only `METElementBinaryOp`. `METElementBinaryOp` takes in two template variables in its constructor, and saves them in pointers that point to the data in those variables. The two template variables can either be a matrix class or a MET template class. `METElementBinaryOp` template argument also takes in an operator type class. This operator type class determines the kind of operation to perform on the two template variables.

There are three operator types present in `MathMETMatrix`: `METAdd`, `METSubtract`, and `METMultiply`. `METMultiply` is not used yet because a good algorithm implementing expression templates for performing dot multiplication has not been found. `METAdd` and `METSubtract` are structures which provide a static function `Evaluate`. `Evaluate` takes in two matrix elements and returns the results of their addition or subtraction.

To implement expression templates, the `operator+` and `operator-` are overloaded so that it will return an instance of a MET object. There is a `operator+` and `operator-` which perform operations between a `MathMETMatrix` derived matrix and any other matrix. There are also friend `operator+` and `operator-` which perform operations between any matrix and any MET object, and between two MET objects. Each operator overload will return a MET object which contains information on the Operations types to do (only `METElementBinaryOp` at the present moment), the operator types to perform (`METAdd` for `operator+` and `METSubtract` for `operator-`), and the variables to perform the operator types on (a matrix or an expression).

Thus, when the compiler meets the code above: `A = B + C + D + E + F;`, it will generate the following code:

```A = MET< METElementBinaryOp< METAdd<value_type>, Matrix,
Matrix>, Matrix>(& MET< METElementBinaryOp<
Matrix>(& MET< METElementBinaryOp<
Matrix, Matrix> >, Matrix>,
Matrix>(& MET< METElementBinaryOp<
Matrix, Matrix> >, Matrix>(& MET<
Matrix, Matrix> >(METElementBinaryOp<
&C)), &D)), &E)), &F)); &C)), &D)), &E)), &F))```

Don’t worry about the above code. What it basically does is that it generates a MET object which encapsulates all the information required for doing `B + C + D + E + F`. All that is required now is to implement the calculation of the results and put it in matrix `A`.

To implement the calculation, the assignment operator (`operator=`) was overloaded in the final matrix class. The assignment operator will take in a MET object as its argument. Since there are many different types of MET objects, the `operator=` has to be a template function. The resulting code is as follows:

```template<typename ExprT> Self& operator=(MET<ExprT> expr)
{
size_t sizeRow = expr.rowsize;
size_t sizeCol = expr.colsize;

Self tempMatrix(sizeRow,sizeCol);

for (size_t i=0; i<sizeRow; ++i)
{
for (size_t j=0; j<sizeCol; ++j)
{
tempMatrix(i,j) = expr(i,j);
}
}
swap(tempMatrix);
Update;
return *this;
}```

The code is relatively simple to understand. What it does is that it gets the required total number of rows and columns from the MET object and creates a temporary matrix to hold the results of the matrix calculations. Then it loops through each individual element, and finds the results for the calculation. Using the example above, the results of the calculation is the result of `B(i,j) + C(i,j) + D(i,j) +E(i,j) + F(i,j)`. The temporary matrix is then swapped with the current matrix (which is matrix `A`, in the example) so that the results of the calculation is now assigned to the current matrix.

To digress slightly, this function is slower than that of the Matrix Expression Template3 because of the creation of the temporary matrix. However, this temporary matrix is necessary to make the operation more intuitive, i.e., it doesn’t matter what the size of matrix `A` is before the calculation, because it will be resized to the correct size required by the matrix calculation of `B + C + D + E + F`. This is not the case for the Matrix Expression Template class. In that class, matrix `A` is required to be the same size as B, C, D, E, and F, otherwise the operation will fail. The present matrix class can achieve better efficiency than the Matrix Expression Template if the same stance was adopted. The temporary matrix just needs to be removed, and substitute `tempMatrix(i,j)` with `(*this)(i,j)`. However, this was not done because it is more essential for the operation to be intuitive in this case than for it to be fast.

Now, let’s go back to our discussion on expression templates. From the `operator=` code, it can be seen that there is a need to implement some functions in the various expression template supporting classes. Two functions, `row.size` and `col.size` need to be implemented to find out the total number of rows and columns needed for the matrix receiving the results. There is also a need to implement an operator which takes in the matrix element position and outputs the results of the mathematical operation.

For the MET class, it is simple to implement these three functions. These three functions are just passed on to the `METElementBinaryOp` for processing.

`METElementBinaryOp` implements `row.size` and `col.size` by passing it on to one of its two template variables. The variable `left_` is chosen. There is no reason why the variable `right_` cannot be chosen. If `left_` is a matrix, it will have the functions `row.size` and `col.size`, and thus will return the number of rows and columns respectively. If `left_` is a MET object, it will pass it on to `METElementBinaryOp`, which will pass in on to `left_` recursively and so forth, until it reaches a matrix.

`METElementBinaryOp` implements an operator by applying it on the `left_` and `right_` variables. If `left_` and `right_` are matrices, they will return the element at position (i,j). If they are a MET object, they will pass it on to `METElementBinaryOp` until it finally reaches a matrix and the element at position (i,j) is returned. The returned elements are then sent to the `Evaluate` function of the operator type which will then add or subtract them and return the results. Thus, the innocently looking `expr(i,j)` actually performs all the necessary calculations on the individual elements (e.g., `B(i,j) + C(i,j) + D(i,j) + E(i,j) + F(i,j)`).

That concludes the discussion on the implementation of expression templates for the matrix class. One problem which can be seen is that there is no proper way to ensure that all the matrices are of the same size, before the matrix calculation is done. Thus, it is up to the user to ensure that the matrices are of the same size, before performing the calculations. Otherwise, unexpected errors may arise. Another problem is that expression templates may not speed up all matrix addition or subtraction. For short additions like `A = B + C;`, using expression templates may actually slow down the calculation. Thus, the user should experiment with both `MathMatrix` and `MathMETMatrix` to determine the best mathematical matrix to use for each situation. Both contains code to interconvert one form to another, and both types of matrices can be used in the same calculation, so there is no penalty incurred in having both types available for use in the final matrix class. There is currently no good algorithm for implementing dot multiplication using expression templates. Thus, at the present moment, dot multiplication for `MathMETMatrix` is using the same code as `MathMatrix`.

#### template<typename ValueT, typename MatrixT> NonMathMatrix

This is the simplest of the three `MathP` classes. It contains the bare essential functions so that it presents the same interface as `MathMatrix` and `MathMETMatrix`. Other than that, it does not contain any mathematical operators so that a matrix deriving from it cannot perform any mathematical operations and will give a compiler error if tried.

### Implementation of the Matrix

#### template<typename ValueT, template<typename> class MatrixTypeP, template<typename, typename> class MathP> class Matrix

We have reached the most important class, the `Matrix` class. It is the class that the user interacts with. The final functions that are present in this class is dependent on which storage policy and which mathematical policy that it inherits from.

Even though `Matrix` inherits most of its functions from `MatrixTypeP` and `MathP`, constructors, the destructor, copy constructors, and assignment operators are not inherited. Thus, it needs to implement these. Since it is to be a STL-like container, it has to define various STL-like typedefs. These typedefs are obtained from `MatrixTypeP` by redefining them. The `MathP` policy does not have any constructor or assignment operator which must be mirrored by `Matrix`, thus `Matrix` only has to define constructors, copy constructors, and assignment operators which are present in `MatrixTypeP` and pass the operations to it. Hence, there must be a default constructor which takes in no arguments. There should be constructors which take in the initial size of the matrix as well as the initial values. The initial values can be a default value for all elements, or from a matrix implemented using arrays or pointers. A copy constructor should also be present. There should be an assignment operator for copying another similar matrix, and an assignment operator for copying any matrix class.

In addition, `Matrix` implements one additional copy constructor which is not found in `MatrixTypeP`. This copy constructor takes in any matrix class. The code is implemented by passing the matrix to be copied to the template `operator=` in `MatrixTypeP` instead of a similar copy constructor in `MatrixTypeP`. The reason for this is that if there is a copy constructor in `MatrixTypeP` which can take in all matrix classes, it will prevent the normal copy constructor in `Matrix` from working properly because all the matrixes passed into `MatrixTypeP` will be processed by the template version of the copy constructor instead of the normal version. The reason for this is simple. The construct of the normal copy constructor in `Matrix` is `Matrix(const Self& m) : MathBase(this), StorageBase(m)`. As can be seen, `StorageBase` is passed a const reference to `m`. If there is no template version of the copy constructor in `StorageBase`, `m` will be processed by the normal copy constructor in `StorageBase`. However, if a template version is present in `StorageBase`, the `StorageBase` will use the template version to process `m` since `m` is of type `Matrix`, so it does not fit into the normal copy constructor which requires the type `StorageBase`. Hence, a template version of the copy constructor should not be present in `StorageBase`, otherwise all copies may result in slow operations or error. However, a template version of the copy constructor will be useful since there could be different `Matrix` types each differing only in their `MatrixTypeP` or `MathP`, and it should be possible to copy one type to another. Thus, a template version of the copy constructor is created only in the `Matrix` class, and it passes the operation to a template `operator=` in the `MatrixTypeP` which normally should perform a copy of the matrix using the common functions available to all matrices.

`Matrix` also implements an additional assignment operator (`operator=`) which takes in a MET object. The reason is discussed above in `MathMETMatrix`.

Two other functions which are useful for all matrices but are not essential for `MatrixTypeP` operations are implemented in `Matrix`. They are `swaprows` and `swapcols`. These two functions use only iterators for their operations so that they can be applicable to all types of `MatrixTypeP` matrices.

## Implementation of RowVector and ColVector

#### template<typename ValueT,template<typename> class MatrixTypeP,template<typename,typename> class MathP> class ColVector

Both `RowVector` and `ColVector` are derived from the `Matrix` class. Their existence is almost unnecessary as the `Matrix` class can be a row vector or a column vector, by setting the number of rows or columns to 1, respectively. Also, STL already implements three useful and powerful 1-dimensional containers. So, why is there a need for `RowVector` and `ColVector`? The initial idea for creating them is for performance and ease of use.

`RowVector` and `ColVector` can be faster than STL containers when they use the `DenseMatrix` class as a storage policy. As mentioned earlier, `DenseMatrix` exposes its storage mechanism to performance-hungry users. Thus, users can directly access the elements in the matrix using the exposed variable instead of passing through accessor functions. STL containers do not expose their storage mechanism, thus the only way to access their elements is through accessor functions. This adds overhead and slows down performance.

For variables destined to be a vector throughout their lifetime, `RowVector` and `ColVector` are easier to use than the `Matrix` class. For these variables, either their number of rows or columns is always 1. Thus, the flexibility offered by the `Matrix` class in accessing the elements or obtaining iterators is unnecessary. To enable ease of use, `RowVector` and `ColVector` implement several functions present in STL containers:` operator[]`, `at`, `push_back`, `resize`, `size`, `begin`, `end`, `rbegin`, and `rend`. `RowVector` and `ColVector` also implement constructors requiring only a single size variable instead of the two in the `Matrix` class (one for the number of rows and one for the number of columns).

Although `RowVector` and `ColVector` have simplified functions for accessing and modifying its elements and iterators, they retain all the functions available in the `Matrix` class in order to be compatible with the `Matrix` class. They are also inter-convertible with the `Matrix` class. However, the user must ensure that when copying or assigning a `Matrix` class to a `RowVector` or `ColVector` class, the matrix class must be either a row vector or column vector (i.e. either its number of rows or columns must be 1) respectively. Otherwise, the `RowVector` or `ColVector` may end up being a matrix instead. This will not cause any errors when using the class, and the user may not even notice it, but it is logically wrong as a row vector or column vector should not store a matrix.

### Functions Operating On Matrix

#### template<typename MatrixT> struct Transpose

`Transpose` is a functor which finds the transpose of a matrix (a transposed matrix is a matrix where the rows and columns are swapped). It has two overloaded operators, the first taking in a matrix to be transposed and returns the transposed matrix, the second taking in both a matrix to be transposed and a matrix to hold the transposed matrix. The first operator is suitable to use in matrix calculations where it can be used intuitively, or in any appropriate STL algorithms. The second operator is faster, and should be used when the transpose of a matrix needs to be found but need not be used immediately in calculations.

#### template<typename MatrixT> struct Diagonal

`Diagonal` is a functor which finds the main diagonal of a matrix or puts a vector into the main diagonal of a matrix. It has two overloaded operators, the first taking in a matrix and returns the diagonal matrix, the second taking in both a matrix and a matrix to hold the diagonal matrix. The first operator is suitable to use in matrix calculations where it can be used intuitively or in any appropriate STL algorithms. The second operator is faster, and should be used when the diagonal of a matrix needs to be found but need not be used immediately in calculations.

#### template<typename MatrixT> struct Covariance

`Covariance` is a functor which finds the covariance of a matrix. It has two overloaded operators, the first taking in a matrix and returns the covariance matrix, the second taking in both a matrix and a matrix to hold the covariance matrix. The first operator is suitable to use in matrix calculations where it can be used intuitively, or in any appropriate STL algorithms. The second operator is faster, and should be used when the covariance of a matrix needs to be found but need not be used immediately in calculations.

#### template<typename MatrixT> struct Power

`Power` is a functor which calculates the matrix with all its elements raised to a defined power. It has two overloaded operators, the first taking in a matrix and returns the powered matrix, the second taking in both a matrix and a matrix to hold the powered matrix. The first operator is suitable to use in matrix calculations where it can be used intuitively, or in any appropriate STL algorithms. The second operator is faster, and should be used when the powered matrix needs to be found but need not be used immediately in calculations.

#### template<typename MatrixT> struct Mean

`Mean` is a functor which finds a row vector with the mean of each column of a matrix. It has two overloaded operators, the first taking in a matrix and returns the row vector, the second taking in both a matrix and a matrix to hold the row vector. The first operator is suitable to use in matrix calculations where it can be used intuitively, or in any appropriate STL algorithms. The second operator is faster, and should be used when the row vector needs to be found but need not be used immediately in calculations.

#### template<typename MatrixT> struct Median

`Median` is a functor which finds a row vector with the median of each column of a matrix. It has two overloaded operators, the first taking in a matrix and returns the row vector, the second taking in both a matrix and a matrix to hold the row vector. The first operator is suitable to use in matrix calculations where it can be used intuitively, or in any appropriate STL algorithms. The second operator is faster, and should be used when the row vector needs to be found but need not be used immediately in calculations.

#### template<typename MatrixT> struct Sum

`Sum` is a functor which finds a row vector with the sum over each column of a matrix. It has two overloaded operators, the first taking in a matrix and returns the row vector, the second taking in both a matrix and a matrix to hold the row vector. The first operator is suitable to use in matrix calculations where it can be used intuitively, or in any appropriate STL algorithms. The second operator is faster, and should be used when the row vector needs to be found but need not be used immediately in calculations.

#### template<typename MatrixT> struct CumulativeSum

`CumulativeSum` is a functor which finds a matrix with the cumulative sum of the elements of a matrix. It has two overloaded operators, the first taking in a matrix and returns the cumulative sum matrix, the second taking in both a matrix and a matrix to hold the cumulative sum matrix. The first operator is suitable to use in matrix calculations where it can be used intuitively, or in any appropriate STL algorithms. The second operator is faster, and should be used when the cumulative sum matrix needs to be found but need not be used immediately in calculations.

## Conclusions

This concludes the discussion on the `Matrix` class. The `Matrix` class makes use of concepts like policies and expression templates in its implementation. It is designed to be generic, reusable, and easily extendable. Though some of the concepts may not be implemented correctly or in the best possible ways, it is an attempt to consolidate various C++ techniques together. This article serves as an example of how to use the `Matrix` class, a documentation for all the various classes and functions, and also a documentation of all the various phases and thoughts in the design and implementation of the classes. It is hoped that this article will provide sufficient information for all who wish to use, modify, or extend this class. It is also hoped that the brief explanations on policies, iterators, and expression templates will spur those who are interested to read more about these techniques and use them in their own work.

## References

1. William H. Press, Numerical recipes in C++: the art of scientific computing (Cambridge University Press, 2002).
2. Matrix Template Library.
3. Matrix Expression Template.
4. Andrei Alexandrescu, Modern C++ Design (Addison-Wesley, 2001).
5. Todd Veldhuizen, Expression Templates: C++ Report, Vol 7, No. 5, June 1995, pg 26-31.

## Change logs

• Version 1.1
• Removed the identity matrix implementation because it was not well implemented.
• Version 1.2
• Added `RowVector` and `ColVector` classes.
• Fixed errors involving reverse iterators.
• Changed function `empty()`.
• Version 1.3
• Added member spaces `row` and `col` to StoragePolicy and Expression Templates.
• Replaced `rowsize`, `colsize`, `rowbegin`, `rowend`, `colbegin`, and `colend` with `row::size`, `col::size`, `row(i).begin`, `row(i).end`, `col(i).begin`, and `col(i).end`.
• Added `row::insert`, `row::erase`, `row::push_back`, `row::pop_back`, `col::insert`, `col::erase`, `col::push_back`, and `col::pop_back`.
• Added `pop_back` for `RowVector` and `ColVector`.
• Version 1.4
• Changed member spaces `row` and `col` to `Row` and `Col` to prevent conflicts causing `row(i)` not to work when `RowVector` or `ColVector` is declared.
• Version 1.5 (16 April 2006)
• Fixed code so that it is no longer dependent on STLport and will work on Visual Studio 2005, and GCC 3.3.2.
• Because of the fix, the constancy of the row and col iterators may not really work.
• Added `row::push_front`, `row::pop_front`, `col::push_front`, and `col::pop_front`.
• Added `push_front` and `pop_front` for `RowVector` and `ColVector`.

A list of licenses authors might use can be found here

## Share

 Researcher Singapore
No Biography provided

## You may also be interested in...

 First Prev Next
 matrix[i*10+j] JDarS14-Sep-13 2:46 JDarS 14-Sep-13 2:46
 Super slow compared to boost::ublas. Use boost instead! physicsd00d12-Jul-12 10:28 physicsd00d 12-Jul-12 10:28
 Totally cool ... this project compiles on VS2010 with zero complaint. [modified] RedDK14-Jan-11 8:34 RedDK 14-Jan-11 8:34
 compiles with g++ and icc with slight modification rajeshFeb0224-Jul-09 6:24 rajeshFeb02 24-Jul-09 6:24
 Fails under icc and g++ compiler but works with sunCC rajeshFeb0222-Jul-09 19:16 rajeshFeb02 22-Jul-09 19:16
 How to use it under VC++ 6.0 cai_jing4-Aug-08 0:32 cai_jing 4-Aug-08 0:32
 Fails Kuryn1-Jun-08 16:07 Kuryn 1-Jun-08 16:07
 Fails to run on GCC-4.2.4 =(
 matrix nazaninznd3-May-08 1:56 nazaninznd 3-May-08 1:56
 matrix nazaninznd3-May-08 1:55 nazaninznd 3-May-08 1:55
 Congratulations vasu23512-Dec-07 5:29 vasu235 12-Dec-07 5:29
 VS2005 warnings Bartosz Bien8-Oct-06 3:41 Bartosz Bien 8-Oct-06 3:41
 good work, but why not boost::ublas? lxwde26-Apr-06 22:00 lxwde 26-Apr-06 22:00
 Re: good work, but why not boost::ublas? Yap Chun Wei27-Apr-06 17:19 Yap Chun Wei 27-Apr-06 17:19
 Re: Don't waste your time on it v2.020-Apr-06 1:00 v2.0 20-Apr-06 1:00
 Re: Don't waste your time on it Yaroslav Sterkhov18-Sep-06 14:16 Yaroslav Sterkhov 18-Sep-06 14:16
 form Oriocat29-Jul-04 9:30 Oriocat 29-Jul-04 9:30
 resize the matrix?? Anonymous8-Jul-04 9:57 Anonymous 8-Jul-04 9:57
 Re: resize the matrix?? Yap Chun Wei8-Jul-04 20:23 Yap Chun Wei 8-Jul-04 20:23
 beginer,help!!! dnqhung12-Jun-04 20:24 dnqhung 12-Jun-04 20:24
 Re: beginer,help!!! Yap Chun Wei14-Jun-04 18:10 Yap Chun Wei 14-Jun-04 18:10
 The matrix class (for Visual Studio 7.1 users - without STLport and Intel Compiler) Edberg3-May-04 6:09 Edberg 3-May-04 6:09
 Re: The matrix class (for Visual Studio 7.1 users - without STLport and Intel Compiler) huahuaniu27-Jun-05 8:52 huahuaniu 27-Jun-05 8:52
 Help, looking for Matrix functions~! Vincent Sim2-Feb-04 20:33 Vincent Sim 2-Feb-04 20:33
 Re: Help, looking for Matrix functions~! Yap Chun Wei9-Feb-04 21:11 Yap Chun Wei 9-Feb-04 21:11
 Re: Help, looking for Matrix functions~! Potsie19-Apr-06 22:20 Potsie 19-Apr-06 22:20
 Problem of low level languages jirisoler11-Feb-03 21:51 jirisoler 11-Feb-03 21:51
 another way bweep11-Feb-03 7:32 bweep 11-Feb-03 7:32
 Re: another way Yaroslav Sterkhov18-Sep-06 14:23 Yaroslav Sterkhov 18-Sep-06 14:23
 So much for so little.. [nt] Julien Koenen7-Feb-03 4:03 Julien Koenen 7-Feb-03 4:03
 Re: So much for so little.. [nt] Yap Chun Wei7-Feb-03 14:20 Yap Chun Wei 7-Feb-03 14:20
 Re: So much for so little.. [nt] jslavin24-Jul-04 6:55 jslavin 24-Jul-04 6:55
 Did I miss something? Andreas Saurwein5-Feb-03 1:21 Andreas Saurwein 5-Feb-03 1:21
 Re: Did I miss something? Yap Chun Wei5-Feb-03 14:12 Yap Chun Wei 5-Feb-03 14:12
 Re: Did I miss something? Andreas Saurwein5-Feb-03 23:29 Andreas Saurwein 5-Feb-03 23:29
 Re: Did I miss something? Yap Chun Wei6-Feb-03 14:11 Yap Chun Wei 6-Feb-03 14:11
 Re: Did I miss something? hhemken15-Jun-04 7:19 hhemken 15-Jun-04 7:19
 Re: Did I miss something? jhwurmbach21-Jul-04 5:21 jhwurmbach 21-Jul-04 5:21
 A suggestion Jonathan de Halleux4-Feb-03 23:33 Jonathan de Halleux 4-Feb-03 23:33
 Re: A suggestion Yap Chun Wei5-Feb-03 14:25 Yap Chun Wei 5-Feb-03 14:25
 Re: A suggestion jamesm11-Feb-03 18:08 jamesm 11-Feb-03 18:08
 Last Visit: 31-Dec-99 18:00     Last Update: 2-Jul-15 3:58 Refresh 1