Adding addition, subtraction, and multiplication to the matrix class

by Trent Guidry22. June 2009 14:43
This post is the second part of a series about creating a matrix class in C#. In this post I will add matrix addition, subtraction, multiplication, and scalar multiplication. Matrix creation, cloning, transposing, creating an identity matrix, and converting a matrix to and from an array were previously covered in the first part of this series. In a future post I plan to add matrix equation solution through LU decomposition with pivoting (LUP), and matrix inversion.
I want to be able to take two matrices and add them. For those unfamiliar with this, there are reviews on Wikipedia Matrix Addition and Wolfram MathWorld Matrix Addition . For this I added the code below.
public static Matrix Add(Matrix leftMatrix, Matrix rightMatrix){Debug.Assert(leftMatrix.ColumnCount == rightMatrix.ColumnCount);Debug.Assert(leftMatrix.RowCount == rightMatrix.RowCount);Matrix resultMatrix = new Matrix(leftMatrix.RowCount, rightMatrix.ColumnCount);for (int i = 0; i < leftMatrix.RowCount; i++){for (int j = 0; j < leftMatrix.ColumnCount; j++){resultMatrix[i, j] = leftMatrix[i, j] + rightMatrix[i, j];}}return resultMatrix;}public static Matrix operator +(Matrix leftMatrix, Matrix rightMatrix){return Matrix.Add(leftMatrix, rightMatrix);}
The add method takes two matrices, mLeft and mRight and adds them together. It first checks to insure that the number of rows and columns in the matrix are the same for each matrix, otherwise matrix addition doesn’t really make sense. It then creates a new matrix with the same number of rows and columns as the matrices passed in. It then iterates over the rows and columns of the matrices, adds the elements from each matrix, and puts the results into the new matrix. The new matrix is then returned. I also added the addition operator overload to make matrix addition easier in code. This overload simply calls the Add method and passes in the two matrices.
 
Another thing that I want to be able to do is to take two matrices and subtract them. This is rather similar to matrix addition, except the values are subtracted instead of added. For this I added the code below.
public static Matrix Subtract(Matrix leftMatrix, Matrix rightMatrix){Debug.Assert(leftMatrix.ColumnCount == rightMatrix.ColumnCount);Debug.Assert(leftMatrix.RowCount == rightMatrix.RowCount);Matrix resultMatrix = new Matrix(leftMatrix.RowCount, rightMatrix.ColumnCount);for (int i = 0; i < leftMatrix.RowCount; i++){for (int j = 0; j < leftMatrix.ColumnCount; j++){resultMatrix[i, j] = leftMatrix[i, j] - rightMatrix[i, j];}}return resultMatrix;}public static Matrix operator -(Matrix leftMatrix, Matrix rightMatrix){return Matrix.Subtract(leftMatrix, rightMatrix);}
This code is quite similar to that for matrix addition, except that instead of adding the element values together, they are subtracted. As with matrix addition I added the subtraction operator overload to make matrix subtraction easier. The overload simple calls the Subtract method and passes in the two matrices.
The next thing that I want to be able to do is to take two matrices and multiply them. More information about matrix multiplication can be found on Wikipedia Matrix Multiplication and Wolfram MathWorld Matrix Multiplication For this I added the code below.
public static Matrix Multiply(Matrix leftMatrix, Matrix rightMatrix){Debug.Assert(leftMatrix.ColumnCount == rightMatrix.RowCount);Matrix resultMatrix = new Matrix(leftMatrix.RowCount, rightMatrix.ColumnCount);for (int i = 0; i < resultMatrix.ColumnCount; i++){for (int j = 0; j < leftMatrix.RowCount; j++){double value = 0.0;for (int k = 0; k < rightMatrix.RowCount; k++){value += leftMatrix[j, k] * rightMatrix[k, i];}resultMatrix[j, i] = value;}}return resultMatrix;}
The static Multiply function accepts two matrices and checks to ensure that the number of columns in the left matrix are equal to the number of columns in the right matrix. It then creates a new matrix with the number of rows equal to the number of rows in the left matrix and the number of columns equal to the number of columns in the right matrix. The multiplication starts with the first column in the left matrix and the first row in the right matrix. It creates and zeroes an accumulator dValue. It then multiplies the top most element in the first column of the right matrix by the left most element in the first row in the left matrix and adds the result to dValue. It then continues moving down the first column in the right matrix and across the first row in the left matrix multiplying the elements and adding it to dValue. After it reaches the end of the column and row, it stores the value of dValue into the newly created matrix. It then proceeds to repeat the process with the next row of the left matrix and the first column of the right matrix. After it passes the last row in the left matrix, it then moves to the next column in the right matrix and repeats. This process is continued until it reaches the last row in the left matrix and the last column in the right matrix, at which point the matrix multiplication is complete. The function then returns the new matrix that contains the multiplication result. As with matrix addition and subtraction, I added the multiplication operator overload to make matrix multiplication easier. The overload simple calls the Multiply method and passes in the two matrices.
 
The next thing that I want to be able to do is to multiply a matrix by a scalar. For this I added the code below.
public static Matrix Multiply(double left, Matrix rightMatrix){Matrix resultMatrix = new Matrix(rightMatrix.RowCount, rightMatrix.ColumnCount);for (int i = 0; i < resultMatrix.RowCount; i++){for (int j = 0; j < rightMatrix.ColumnCount; j++){resultMatrix[i, j] = left * rightMatrix[i, j];}}return resultMatrix;}public static Matrix operator *(double left, Matrix rightMatrix){return Matrix.Multiply(left, rightMatrix);}
This is a fairly simple function. It takes a double which represents the scalar and a matrix which is multiplied by the scalar. It creates a new matrix which has the same number of rows and columns as the matrix passed in. It then iterates over the rows and columns and sets the element value of the new matrix to the element value of the original matrix times the scalar. As with the above cases, I added the multiplication operator overload to make this matrix multiplication easier. The overload simply calls the Multiply method and passes in the scalar and matrix.
 
The next thing that I want to be able to do is to perform the above operation when the matrix and scalar orders are reveresed. For this I added the code below.
public static Matrix Multiply(Matrix leftMatrix, double right){Matrix resultMatrix = new Matrix(leftMatrix.RowCount, leftMatrix.ColumnCount);for (int i = 0; i < leftMatrix.RowCount; i++){for (int j = 0; j < leftMatrix.ColumnCount; j++){resultMatrix[i, j] = leftMatrix[i, j] * right;}}return resultMatrix;}public static Matrix operator *(Matrix leftMatrix, double right){return Matrix.Multiply(leftMatrix, right);}
This code operates very similar to the above section, with the only difference being that in this case the matrix is passed in as the first parameter and the scalar as the second. I also created an overloaded operator to make it easier to multiply a matrix by a scalar.
 
The next thing that I want to be able to do is to take a matrix and divide it by a scalar. For this I added the code below.
public static Matrix Divide(Matrix leftMatrix, double right){Matrix resultMatrix = new Matrix(leftMatrix.RowCount, leftMatrix.ColumnCount);for (int i = 0; i < leftMatrix.RowCount; i++){for (int j = 0; j < leftMatrix.ColumnCount; j++){resultMatrix[i, j] = leftMatrix[i, j] / right;}}return resultMatrix;}public static Matrix operator /(Matrix leftMatrix, double right){return Matrix.Divide(leftMatrix, right);}
This code works quite similar to the above multiplication of a matrix with a scalar, except this time the matrix elements are divided by the scalar instead of multiplied by them. As with the above cases, I also overrode the division operator to make division of a matrix by a scalar easier to do in code.
 
That wraps up this post in the series. In a future post I plan to add matrix equation solution using LU with pivoting decomposition and matrix inversion. The full code of this article plus the previous one in this series is shown below.
using System.Diagnostics;namespace NumericalMethods.SecondBlog
{public class Matrix{#region ctorpublic Matrix(){_values = new double[_rowCount, _columnCount];}public Matrix(int rowCount, int columnCount){_rowCount = rowCount;_columnCount = columnCount;_values = new double[_rowCount, _columnCount];}#endregion#region Row Column valuespublic double this[int row, int column]{get { return _values[row, column]; }set { _values[row, column] = value; }}#endregion#region F&Pprivate double[,] _values;private int _rowCount = 3;public int RowCount{get { return _rowCount; }}private int _columnCount = 3;public int ColumnCount{get { return _columnCount; }}#endregion#region basic single matrix stuffpublic static Matrix Identity(int size){Matrix resultMatrix = new Matrix(size, size);for (int i = 0; i < size; i++){for (int j = 0; j < size; j++){resultMatrix[i, j] = (i == j) ? 1.0 : 0.0;}}return resultMatrix;}public Matrix Clone(){Matrix resultMatrix = new Matrix(_rowCount, _columnCount);for (int i = 0; i < _rowCount; i++){for (int j = 0; j < _columnCount; j++){resultMatrix[i, j] = this[i, j];}}return resultMatrix;}public Matrix Transpose(){Matrix resultMatrix = new Matrix(_columnCount, _rowCount);for (int i = 0; i < _rowCount; i++){for (int j = 0; j < _columnCount; j++){resultMatrix[j, i] = this[i, j];}}return resultMatrix;}#endregion#region Binary Mathpublic static Matrix Add(Matrix leftMatrix, Matrix rightMatrix){Debug.Assert(leftMatrix.ColumnCount == rightMatrix.ColumnCount);Debug.Assert(leftMatrix.RowCount == rightMatrix.RowCount);Matrix resultMatrix = new Matrix(leftMatrix.RowCount, rightMatrix.ColumnCount);for (int i = 0; i < leftMatrix.RowCount; i++){for (int j = 0; j < leftMatrix.ColumnCount; j++){resultMatrix[i, j] = leftMatrix[i, j] + rightMatrix[i, j];}}return resultMatrix;}public static Matrix operator +(Matrix leftMatrix, Matrix rightMatrix){return Matrix.Add(leftMatrix, rightMatrix);}public static Matrix Subtract(Matrix leftMatrix, Matrix rightMatrix){Debug.Assert(leftMatrix.ColumnCount == rightMatrix.ColumnCount);Debug.Assert(leftMatrix.RowCount == rightMatrix.RowCount);Matrix resultMatrix = new Matrix(leftMatrix.RowCount, rightMatrix.ColumnCount);for (int i = 0; i < leftMatrix.RowCount; i++){for (int j = 0; j < leftMatrix.ColumnCount; j++){resultMatrix[i, j] = leftMatrix[i, j] - rightMatrix[i, j];}}return resultMatrix;}public static Matrix operator -(Matrix leftMatrix, Matrix rightMatrix){return Matrix.Subtract(leftMatrix, rightMatrix);}public static Matrix Multiply(Matrix leftMatrix, Matrix rightMatrix){Debug.Assert(leftMatrix.ColumnCount == rightMatrix.RowCount);Matrix resultMatrix = new Matrix(leftMatrix.RowCount, rightMatrix.ColumnCount);for (int i = 0; i < resultMatrix.ColumnCount; i++){for (int j = 0; j < leftMatrix.RowCount; j++){double value = 0.0;for (int k = 0; k < rightMatrix.RowCount; k++){value += leftMatrix[j, k] * rightMatrix[k, i];}resultMatrix[j, i] = value;}}return resultMatrix;}public static Matrix operator *(Matrix leftMatrix, Matrix rightMatrix){return Matrix.Multiply(leftMatrix, rightMatrix);}public static Matrix Multiply(double left, Matrix rightMatrix){Matrix resultMatrix = new Matrix(rightMatrix.RowCount, rightMatrix.ColumnCount);for (int i = 0; i < resultMatrix.RowCount; i++){for (int j = 0; j < rightMatrix.ColumnCount; j++){resultMatrix[i, j] = left * rightMatrix[i, j];}}return resultMatrix;}public static Matrix operator *(double left, Matrix rightMatrix){return Matrix.Multiply(left, rightMatrix);}public static Matrix Multiply(Matrix leftMatrix, double right){Matrix resultMatrix = new Matrix(leftMatrix.RowCount, leftMatrix.ColumnCount);for (int i = 0; i < leftMatrix.RowCount; i++){for (int j = 0; j < leftMatrix.ColumnCount; j++){resultMatrix[i, j] = leftMatrix[i, j] * right;}}return resultMatrix;}public static Matrix operator *(Matrix leftMatrix, double right){return Matrix.Multiply(leftMatrix, right);}public static Matrix Divide(Matrix leftMatrix, double right){Matrix resultMatrix = new Matrix(leftMatrix.RowCount, leftMatrix.ColumnCount);for (int i = 0; i < leftMatrix.RowCount; i++){for (int j = 0; j < leftMatrix.ColumnCount; j++){resultMatrix[i, j] = leftMatrix[i, j] / right;}}return resultMatrix;}public static Matrix operator /(Matrix leftMatrix, double right){return Matrix.Divide(leftMatrix, right);}#endregion#region Assorted Castspublic static Matrix FromArray(double[] left){int length = left.Length;Matrix resultMatrix = new Matrix(length, 1);for (int i = 0; i < length; i++){resultMatrix[i, 0] = left[i];}return resultMatrix;}public static implicit operator Matrix(double[] left){return FromArray(left);}public static double[] ToArray(Matrix leftMatrix){Debug.Assert((leftMatrix.ColumnCount == 1 && leftMatrix.RowCount >= 1) || (leftMatrix.RowCount == 1 && leftMatrix.ColumnCount >= 1));double[] result = null;if (leftMatrix.ColumnCount > 1){int numElements = leftMatrix.ColumnCount;result = new double[numElements];for (int i = 0; i < numElements; i++){result[i] = leftMatrix[0, i];}}else{int numElements = leftMatrix.RowCount;result = new double[numElements];for (int i = 0; i < numElements; i++){result[i] = leftMatrix[i, 0];}}return result;}public static implicit operator double[](Matrix leftMatrix){return ToArray(leftMatrix);}public static Matrix FromDoubleArray(double[,] left){int length0 = left.GetLength(0);int length1 = left.GetLength(1);Matrix resultMatrix = new Matrix(length0, length1);for (int i = 0; i < length0; i++){for (int j = 0; j < length1; j++){resultMatrix[i, j] = left[i, j];}}return resultMatrix;}public static implicit operator Matrix(double[,] left){return FromDoubleArray(left);}public static double[,] ToDoubleArray(Matrix leftMatrix){double[,] result = new double[leftMatrix.RowCount, leftMatrix.ColumnCount];for (int i = 0; i < leftMatrix.RowCount; i++){for (int j = 0; j < leftMatrix.ColumnCount; j++){result[i, j] = leftMatrix[i, j];}}return result;}public static implicit operator double[,](Matrix leftMatrix){return ToDoubleArray(leftMatrix);}#endregion}
}