Matrix Class

Math 5620 Software Manual

Routine Name: class Matrix

Author: Tanner Wheeler

Language: C++. The code can be compiled using the cMake compiler.

Description/Purpose: This class will create a matrix in which you can initialize it personally or using the different functions. It also initializes the 5-point stencil and 9-point stencil if needed.

Input: Matrix(std::vector initializer) - turns a vector into an mx1 matrix. Matrix(int M, int N, bool doLayout) - creates an mxn matrix. To initialize it yourself put true for the bool. Matrix() - Creates a 5x5 hilbert matrix. Matrix(int mesh) - Creates the 5 point stencil with the mesh. Matrix(int mesh, bool point_9) - Creates the 9 point stencil with the mesh. The bool does nothing. Matrix(int M, int N) - Creates a tridiagonal matrix with a mxn matrix.

Output: No output only creates a matrix you can manipulate.

Usage/Example: You must include the file in your file.

#include "Matrix.hpp"

Choose the type of Matrix you want to initialize. Here we will use the Hilbert Matrix.

Matrix myMatrix();

You can now use the functions how you need.

Implementation/Code: The following is the code for

#ifndef _MATRIX_HPP_
#define _MATRIX_HPP_

#include <iostream>
#include <vector>
#include <iomanip>
#include <string>

class Matrix
{
public:

	//
	// This will initialize your matrix from a vector.
	//
	Matrix(std::vector<double> initializer) : M(initializer.size()), N(1)
	{
		std::vector<std::vector<double>> test(M, std::vector<double>(N));
		layout = test;

		for (unsigned int i = 0; i < M; i++)
		{
			layout[i][0] = initializer[i];
		}
	}
	
	//
	//Regular Matrix
	//
	Matrix(int M, int N, bool doLayout) : M(M), N(N) 
	{
		std::vector<std::vector<double>> test(M, std::vector<double>(N));
		layout = test;

		std::string typing;

		if (doLayout)
		{
			for (unsigned int i = 0; i < M; i++)
			{
				std::cout << "Row " << i + 1 << "-- " << std::endl;

				for (unsigned int j = 0; j < N; j++)
				{
					std::cout << "\tPlace " << j + 1 << ": ";
					std::cin >> typing;

					layout[i][j] = std::stod(typing);
				}
			}
		}
	}

	//
	// Creates the hilbert matrix
	//
	Matrix() : M(5), N(5)
	{
		std::vector<std::vector<double>> test(M, std::vector<double>(N));
		layout = test;

		for (unsigned int i = 0; i < M; i++)
		{
			for (unsigned int j = 0; j < N; j++)
			{
				double value = 1 / static_cast<double>(i + j + 1);
				layout[i][j] = value;
			}
		}
	}

	//
	// Creates a matrix where every value equals the value parameter.
	//
	Matrix(int M, int N, int value) : M(M), N(N)
	{
		std::vector<std::vector<double>> test(M, std::vector<double>(N));
		layout = test;

		for (unsigned int i = 0; i < M; i++)
		{
			for (unsigned int j = 0; j < N; j++)
			{
				layout[i][j] = value;
			}
		}
	}

	//
	// Creates the 5 point stencil matrix
	//
	Matrix(int mesh) : M(mesh * mesh), N(mesh * mesh)
	{
		std::vector<std::vector<double>> test(M, std::vector<double>(N));
		layout = test;

		initDiagonal(-4);

		for (unsigned int i = 0; i < M - 1; i++)
		{
			if ((i + 1) < N && (i + 1) % mesh != 0)
			{
				layout[i][(i + 1)] = 1;
			}

			if ((i + mesh) < N)
			{
				layout[i][(i + mesh)] = 1;
			}
		}


		for (unsigned int i = 0; i < M - 1; i++)
		{
			if (i < N && (i + 1) % mesh != 0)
			{
				layout[(i + 1)][i] = 1;
			}

			if ((i + mesh) < M)
			{
				layout[(i + mesh)][i] = 1;
			}
		}

	}

	//
	// Creates a 9 point stencil matrix
	//
	Matrix(int mesh, bool point_9) : M(mesh * mesh), N(mesh * mesh)
	{
		std::vector<std::vector<double>> test(M, std::vector<double>(N));
		layout = test;

		initDiagonal(-20);

		for (unsigned int i = 0; i < M - 1; i++)
		{
			if ((i + 1) < N && (i + 1) % mesh != 0)
			{
				layout[i][(i + 1)] = 4;
			}

			if ((i + mesh) < N)
			{
				layout[i][(i + mesh)] = -4;
			}

			if ((i + mesh) < M && (i + mesh + 1) % mesh != 0)
			{
				layout[i + 1][i + mesh] = 1;
			}

			if ((i + mesh + 1) < N && (i + mesh + 1) % mesh != 0)
			{
				layout[i][i + mesh + 1] = 1;
			}
		}


		for (unsigned int i = 0; i < M - 1; i++)
		{
			if (i < N && (i + 1) % mesh != 0)
			{
				layout[(i + 1)][i] = 4;
			}

			if ((i + mesh) < M)
			{
				layout[(i + mesh)][i] = -4;
			}

			if ((i + mesh) < M && (i + mesh + 1) % mesh != 0)
			{
				layout[i + mesh][i + 1] = 1;
			}

			if ((i + mesh + 1) < M && (i + mesh + 1) % mesh != 0)
			{
				layout[i + mesh + 1][i] = 1;
			}
		}
	}


	//
	// Creates a matrix with the -2 down the diagonal and 1 on the diagonals
	// above and below it.
	//
	Matrix(int M, int N) : M(M), N(N)
	{
		std::vector<std::vector<double>> test(M, std::vector<double>(N));
		layout = test;

		initDiagonal(-2);
		initLowDiagonal(1);
		initUpDiagonal(1);
	}

	//
	// Copy constructor.
	//
	Matrix(const Matrix& error)
	{
		M = error.M;
		N = error.N;
		layout = error.layout;
	}


	//
	// Special Values of the class.  Probably should be private values.
	//
	int M;
	int N;

	int getM() { return M; }

	int getN() { return N; }

	std::vector<std::vector<double>> layout;

	//
	// Prints the Matrix.
	//
	void print()
	{
		for (unsigned int i = 0; i < M; i++)
		{
			std::cout << "|  ";
			for (unsigned int j = 0; j < N; j++)
			{
				std::cout << std::setw(7) << std::setprecision(4) << layout[i][j] << "  ";
			}
			std::cout << "|" << std::endl;
		}
		
		std::cout << "=======================================" << std::endl;
	}


	//
	// Initializes the Matrix's main diagonal
	//
	void initDiagonal(double d)
	{
		for (unsigned int i = 0; i < M; i++)
		{
			if (i < N)
			{
				layout[i][i] = d;
			}
		}
	}

	//
	// This initializes the matrix's diagonal above the main diagonal
	//
	void initUpDiagonal(double u)
	{
		for (unsigned int i = 0; i < M - 1; i++)
		{
			if ((i + 1) < N)
			{
				layout[i][(i + 1)] = u;
			}
		}
	}

	//
	// This initializes the matrix's diagonal below the main diagonal
	//
	void initLowDiagonal(double l)
	{
		for (unsigned int i = 0; i < M - 1; i++)
		{
			if (i < N)
			{
				layout[(i + 1)][i] = l;
			}
		}
	}

	//
	// This performs the multiplication of two matrix class objects
	//
	Matrix operator*(const Matrix& rhs)
	{
		if (this->N == rhs.M)
		{
			Matrix matrix(this->M, rhs.N, false);

			for (int i = 0; i < this->M; i++)
			{
				for (int j = 0; j < rhs.N; j++)
				{
					double sum = 0.0f;
					for (int k = 0; k < this->N; k++)
					{
						sum += static_cast<double>(this->layout[i][k]) * static_cast<double>(rhs.layout[k][j]);
					}

					matrix.layout[i][j] = (double)sum;  // Got rid of [(double)i][(double)j]
				}
			}

			return matrix;
		}
		else
		{
			std::cout << "Dimensions aren't compatible.  Left hand matrix returned. No multiplication performed." << std::endl;

			return *this;
		}
	}

	//
	// This performs multiplication of a matrix and a scalar.
	// Needs to be used as (if A was a matrix object) A * 9.
	//
	Matrix operator*(const double& rhs) 
	{
		Matrix matrix(this->M, this->N, false);

		for (int i = 0; i < this->M; i++)
		{
			for (int j = 0; j < this->N; j++)
			{
				double mult = this->layout[i][j];
				mult *= rhs;
				matrix.layout[i][j] = mult;
			}
		}

		return matrix;
	}


	//
	// This performs division of a matrix and a scalar.
	// Needs to be used as (if A was a matrix object) A / 9 = A * (1/9).
	//
	Matrix operator/(const double& rhs)
	{
		for (unsigned int i = 0; i < this->M; i++)
		{
			for (unsigned int j = 0; j < this->N; j++)
			{
				this->layout[i][j] /= rhs;
			}
		}

		return *this;
	}


	//
	// This performs division of a matrix and a scalar(magnitude of a 1x1 
	// Matrix.  Acts as though you were to multiply by 1 over the intended number.
	//
	Matrix operator/(const Matrix& rhs)
	{
		if(rhs.M == 1 && rhs.N == 1)
		for (unsigned int i = 0; i < this->M; i++)
		{
			for (unsigned int j = 0; j < this->N; j++)
			{
				this->layout[i][j] /= rhs.layout[0][0];
			}
		}

		return *this;
	}



	//
	// This adds two matrix objects together.
	//
	Matrix operator+(const Matrix& rhs)
	{
		if (this->M == rhs.M && this->N == rhs.N)
		{
			Matrix matrix(this->M, this->N, false);

			for (unsigned int i = 0; i < M; i++)
			{
				for (unsigned int j = 0; j < N; j++)
				{
					matrix.layout[i][j] = ((double)this->layout[i][j] + (double)rhs.layout[i][j]);
				}
			}

			return matrix;
		}
		else
		{
			std::cout << "Dimensions aren't compatible. Left hand matrix returned. No addition performed." << std::endl;

			return *this;
		}
	}

	
	//
	// This subtracts to matrix objects from each other.
	//
	Matrix operator-(const Matrix& rhs)
	{
		if (this->M == rhs.M && this->N == rhs.N)
		{
			Matrix matrix(this->M, this->N, false);

			for (unsigned int i = 0; i < M; i++)
			{
				for (unsigned int j = 0; j < N; j++)
				{
					matrix.layout[i][j] = ((double)this->layout[i][j] - (double)rhs.layout[i][j]);
				}
			}

			return matrix;
		}
		else
		{
			std::cout << "Dimensions aren't compatible. Left hand matrix returned. No addition performed." << std::endl;

			return *this;
		}
	}

	
	//
	// This returns the transpose of this matrix object.
	//
	Matrix transpose()
	{
		Matrix newMatrix(N, M, false);

		for (unsigned int i = 0; i < M; i++)
		{
			for (unsigned int j = 0; j < N; j++)
			{
				newMatrix.layout[j][i] = layout[i][j];
			}
		}

		return newMatrix;
	}


	//
	// This compares two matrix objects together to see if they are 
	// not equal to each other.
	//
	bool operator!=(const Matrix& rhs)
	{
		if (this->M == rhs.M && this->N == rhs.N)
		{
			for (unsigned int i = 0; i < M; i++)
			{
				for (unsigned int j = 0; j < N; j++)
				{
					if(this->layout[i][j] != rhs.layout[i][j])
					{
						return true;
					}
				}
			}

			return false;
		}
		else
		{
			return true;
		}
	}



	//
	// This compares two matrix objects together to see if they are
	// equal to each other.
	//
	bool operator==(const Matrix& rhs)
	{
		if (this->M == rhs.M && this->N == rhs.N)
		{
			for (unsigned int i = 0; i < M; i++)
			{
				for (unsigned int j = 0; j < N; j++)
				{
					if (this->layout[i][j] != rhs.layout[i][j])
					{
						return false;
					}
				}
			}

			return true;
		}
		else
		{
			return false;
		}
	}
	
	//
	// This finds the Infinity Matrix Norm of this matrix
	// object.
	//
	float infiMatrixNorm()
	{
		double maxSum = 0.0f;
		double sum = 0.0f;

		for (unsigned int i = 0; i < M; i++)
		{
			for (unsigned int j = 0; j < N; j++)
			{
				sum += layout[i][j];
			}

			if (sum > maxSum)
			{
				maxSum = sum;
			}
			
			sum = 0.0f;
		}

		return maxSum;
	}

	//
	// This finds the One Matrix Norm of this matrix
	// object.
	//
	float oneMatrixNorm()
	{
		double maxSum = 0.0f;
		double sum = 0.0f;

		for (unsigned int j = 0; j < N; j++)
		{
			for (unsigned int i = 0; i < M; i++)
			{
				sum += layout[i][j];
			}

			if (sum > maxSum)
			{
				maxSum = sum;
			}

			sum = 0.0f;
		}

		return maxSum;
	}

};

#endif

Last Modified: February/2018