Page MenuHomec4science

Matrix.cpp
No OneTemporary

File Metadata

Created
Tue, May 28, 09:42

Matrix.cpp

#include <cmath>
#include <iostream>
#include <cassert>
#include <string>
#include "Matrix.hpp"
#include "Exception.hpp"
// Overridden copy constructor
// Allocates memory for new matrix, and copies
// entries of other matrix into it
double** AllocateMemory(int rows, int cols){
/*Allocates memory for matrix A*/
double** A;
A=new double* [rows];
for (int i=0;i<cols;i++){
A[i]=new double[cols];
}
return A;
}
Matrix::Matrix(const Matrix& otherMatrix)
{
/* Copying of Matrix size*/
mNumCols = otherMatrix.NumberOfColumns();
mNumRows = otherMatrix.NumberOfRows();
/*Allocation of memory for copy of matrix*/
mData=AllocateMemory(mNumRows,mNumCols) ;
/* Copying of class data*/
for (int i=0; i<mNumRows; i++){
for (int j=0;j<mNumCols;j++){
mData[i][j]=otherMatrix.mData[i][j];
}
}
}
// Constructor for matrix of a given size
// Allocates memory, and initialises entries
// to zero
Matrix::Matrix(int rows, int cols){
assert(rows > 0 && cols>0);
mNumCols = cols;
mNumRows=rows;
mData=AllocateMemory(mNumRows,mNumCols) ;
for (int i=0; i<mNumRows; i++) {
for (int j = 0; j < mNumCols; j++) {
mData[i][j] = 0.0;
}
}
}
// Constructor for a square matrix of a given size
// Allocates memory, and initialises entries
// to zero
Matrix::Matrix(int size){
assert(size > 0);
mNumCols = size;
mNumRows=size;
mData=AllocateMemory(mNumRows,mNumCols) ;
for (int i=0; i<mNumRows; i++) {
for (int j = 0; j < mNumCols; j++) {
mData[i][j] = 0.0;
}
}
}
// Default constructor
Matrix::Matrix() = default;
// Overridden destructor to correctly free memory
Matrix::~Matrix()
{
for (int i=0;i<mNumRows;i++){
delete[] mData[i];
}
delete[] mData;
}
// Method to get the number of rows of a matrix
int Matrix::NumberOfRows() const
{
return mNumRows;
}
// Method to get the number of columns of a matrix
int Matrix::NumberOfColumns() const
{
return mNumCols;
}
// Method to check if index is out of bounds
// Method to check if index is out of bounds
int Matrix::CheckIndex(int i) const{
try {
if (i<=-1 || i>=mNumRows){
throw (Exception("Index","Index is out of bounds"));
} else {
return i;
}
} catch (Exception& error){
error.PrintDebug();
std::cout<<"\nGive an alternative index value\n\n";
int j;
std::cin>>j;
while (j<=-1 || j>=mNumRows){
std::cout<<"\nIndex is still out of bounds, give an alternative value ...\n";
std::cin>>j;
}
return j;
}
}
// Read-only variant of [][]
// Note that this uses ‘zero-based’ indexing,
// and a check on the validity of the index
double Matrix::Read(int i, int j) const
{
return mData[CheckIndex(i)][CheckIndex(j)];
}
// Overloading round brackets
// Note that this uses ‘one-based’ indexing,
// and a check on the validity of the index
double& Matrix::operator()(int i, int j)
{
return mData[CheckIndex(i-1)][CheckIndex(j-1)];
}
// Overloading the assignment operator
Matrix& Matrix::operator=(const Matrix& otherVector)
{
if(mNumRows == otherVector.mNumRows && mNumCols==otherVector.mNumCols){
}else {
/* Copying of Matrix size*/
mNumCols = otherVector.NumberOfColumns();
mNumRows = otherVector.NumberOfRows();
/*Allocation of memory for copy of matrix*/
mData = AllocateMemory(mNumRows, mNumCols);
}
for (int i=0; i<mNumRows; i++)
{
for (int j=0;j<mNumCols;j++)
{
mData[i][j] = otherVector.mData[i][j];
}
}
return * this;
}
// Overloading the unary + operator
Matrix Matrix::operator+() const {
Matrix A(mNumRows, mNumCols);
for (int i = 0; i < mNumRows; i++) {
for (int j = 0; j < mNumCols; j++) {
A(i + 1, j + 1) = mData[i][j];
}
}
return A;
}
// Overloading the unary - operator
Matrix Matrix::operator-() const {
Matrix A(mNumRows, mNumCols);
for (int i = 0; i < mNumRows; i++) {
for (int j = 0; j < mNumCols; j++) {
A(i + 1, j + 1) = -mData[i][j];
}
}
return A;
}
// Overloading the binary + operator
Matrix Matrix::operator+(const Matrix& B) const
{
assert(mNumRows == B.mNumRows && mNumCols==B.mNumCols);
Matrix A(mNumRows, mNumCols);
for (int i = 0; i < mNumRows; i++) {
for (int j = 0; j < mNumCols; j++) {
A.mData[i][j] = mData[i][j]+B.mData[i][j];
}
}
return A;
}
// Overloading the binary - operator
Matrix Matrix::operator-(const Matrix& B) const
{
assert(mNumRows == B.mNumRows && mNumCols==B.mNumCols);
Matrix A(mNumRows, mNumCols);
for (int i = 0; i < mNumRows; i++) {
for (int j = 0; j < mNumCols; j++) {
A.mData[i][j] = mData[i][j]-B.mData[i][j];
}
}
return A;
}
// Overloading the binary * operator
Matrix Matrix::operator*(const Matrix& B) const
{
assert(mNumRows == B.mNumRows && mNumCols==B.mNumCols);
Matrix A(mNumRows, mNumCols);
for (int i=0;i<mNumRows;i++){
for (int j=0;j<B.mNumCols;j++){
for (int k=0;k<B.mNumCols;k++){
A.mData[i][j]+=mData[i][k]*B.mData[k][j];
}
}
}
return A;
}
// Overloading the output << operator
std::ostream& operator<<(std::ostream& output, const Matrix& A){
/*Prints to terminal values of a matrix A*/
for (int i=0;i<A.mNumRows;i++){
for (int j=0;j<A.mNumCols;j++){
std::cout<<A.mData[i][j]<<" ";
}
std::cout<<std::endl;
}
std::cout<<std::endl;
}
// Overloading scalar multiplication
Matrix Matrix::operator *(double a) const
{
Matrix A(mNumRows, mNumCols);
for (int i=0;i<mNumRows;i++){
for (int j=0;j<mNumCols;j++){
A.mData[i][j]=mData[i][j]*a;
}
}
return A;
}
void ReduceMatrix(double** A,int size,int col, double** &A_hat){
/*Resizing of matrix A for determinant computation*/
for (int row = 1; row < size; ++row) {
for (int k = 0; k < col; ++k) {
A_hat[row - 1][k] = A[row][k];
}
for (int k = col + 1; k < size; ++k) {
A_hat[row - 1][k - 1] = A[row][k];
}
}
}
void Matrix::FreeMemory(double** A,int rows) const{
/*Frees memory of matrix A*/
for (int i=0;i<rows;i++){
delete[] A[i];
}
delete[] A;
}
/*Computation of determinant : direct formula for 2x2, recursive otherwise*/
double Matrix::Determinant(double** A, int size) const
{
if (size==2){
return A[0][0]*A[1][1]-A[1][0]*A[0][1];
} else {
double det=0;
for (int j = 0; j < size; ++j) {
double** A_hat=AllocateMemory(size-1,size-1);
ReduceMatrix(A,size,j,A_hat);
det +=A[0][j]*std::pow(-1.0,j)*Determinant(A_hat,size-1);
FreeMemory(A,size);
}
return det;
}
}
void TerminalPrint(Matrix A,std::string msg) {
/*Prints to terminal values of a vector v and a message */
std::cout<<std::endl<<msg<<std::endl<<A;
}

Event Timeline