I have written a Matrix library that contains all the main properties of matrices. It's a relatively long project, I am hoping it is ok to post here since I really want to have it reviewed.
The project is compiled in GCC 9.2.0 and Boost 1.71.0, from https://nuwen.net/mingw.html, environment codeblocks windows 10.
Utility.h
#ifndef UTILITY_H_INCLUDED
#define UTILITY_H_INCLUDED
#include <iostream>
#include <math.h>
#include <conio.h>
#include <vector>
#include "Fraction.h"
#include <boost/multiprecision/cpp_int.hpp>
using boost::multiprecision::cpp_int;
using namespace std;
namespace utilities
{
void swapRows(vector<vector<Fraction>>& mx, int row1, int row2,
int columns)
{
for (int i = 0; i < columns; i++ )
{
std::swap( mx[ row1 ][ i ], mx[ row2 ][ i ] );
}
}
bool pivotEqualTo_one_Found(std::vector<vector<Fraction>>& mx, int pivot_row, int pivot_col,
int cols_num, int& alternative_pivot_row )
{
for (int i = pivot_row + 1; i < cols_num; ++i)
{
if(mx[ i ][ pivot_col ] == 1)
{
alternative_pivot_row = i;
return true;
}
}
return false;
}
bool pivotNot_zero_Found(vector<vector<Fraction>> mx, int pivot_row, int pivot_col,
int cols_num, int& col_dif_zero )
{
Fraction fr(0, 0);
for (int i = pivot_row + 1; i < cols_num; ++i)
{
if(mx[ i ][ pivot_col ] != fr)
{
col_dif_zero = i;
return true;
}
}
return false;
}
bool firstNumberNot_zero(vector<vector<Fraction>> mx, int row_num, int columms,
int& num_coluna_num_dif_zero)
{
for (int i = 0; i < columms; ++i)
{
if (mx[row_num] [ i ] != 0)
{
num_coluna_num_dif_zero = i;
return true;
}
}
return false;
}
void changePivotTo_one(vector<vector<Fraction>>& mx, int row_num, int columms, Fraction constant)
{
Fraction fr(0, 1);
for(int i = 0; i < columms; ++i)
if (mx[ row_num ][ i ].num == 0)
mx[ row_num ][ i ] = mx[ row_num ][ i ];
else
mx[ row_num ][ i ] = (mx[ row_num ][ i ] / constant);
}
void zeroOutTheColumn(vector<vector<Fraction>>& mx, int row_num, int num_pivot_row,
int columms, Fraction constant)
{
for(int i = 0; i < columms; ++i)
{
mx[ row_num ][ i ] = mx[ row_num ][ i ] - (constant * mx[num_pivot_row][i]);
}
}
}
#endif // UTILITY_H_INCLUDED
Fraction.h
#ifndef FRACTION_H_INCLUDED
#define FRACTION_H_INCLUDED
#include <ostream>
#include <boost/multiprecision/cpp_int.hpp>
using boost::multiprecision::cpp_int;
class Fraction
{
cpp_int lcd(cpp_int a, cpp_int b);
cpp_int gcf(cpp_int a, cpp_int b);
void simplify();
public:
cpp_int num;
cpp_int den;
Fraction () : num(0), den(1) {}
Fraction (cpp_int n)
{
num = n;
den = 1;
}
Fraction(cpp_int _num, cpp_int _den) : num(_num), den(_den) {}
friend std::ostream& operator<< (std::ostream& os, const Fraction& fr);
bool operator== (const Fraction& fr)
{
return (this->num == fr.num && this->den == fr.den);
}
bool operator== (int n)
{
return ((this->num / this->den) == n);
}
bool operator!= (const Fraction& fr)
{
return (this->num != fr.num || this->den != fr.den);
}
bool operator!= (int n)
{
return ((this->num / this->den) != n);
}
Fraction operator+(const Fraction& fr) const;
Fraction operator/(const Fraction& fr) const;
Fraction operator-(const Fraction& fr) const;
Fraction operator*(const Fraction& fr) const;
friend Fraction operator+(const Fraction& fr, cpp_int n);
friend Fraction operator+(cpp_int n, const Fraction& fr);
friend Fraction operator-(const Fraction& fr, cpp_int n);
friend Fraction operator-(cpp_int n, const Fraction& fr);
friend Fraction operator/(const Fraction& fr, cpp_int n);
friend Fraction operator/(cpp_int n, const Fraction& fr);
friend Fraction operator*(const Fraction& fr, cpp_int n);
friend Fraction operator*(cpp_int n, const Fraction& fr);
friend void operator+= (Fraction& f, const Fraction& fr);
friend void operator-= (Fraction& f, const Fraction& fr);
friend void operator/= (Fraction& f, const Fraction& fr);
friend void operator*= (Fraction& f, const Fraction& fr);
friend void operator+=(Fraction& fr, cpp_int n);
friend void operator-=(Fraction& fr, cpp_int n);
friend void operator*=(Fraction& fr, cpp_int n);
friend void operator/=(Fraction& fr, cpp_int n);
};
#endif // FRACTION_H_INCLUDED
Fraction.cpp
#include "Fraction.h"
using namespace std;
std::ostream& operator << (std::ostream& os, const Fraction& fr)
{
if(fr.num % fr.den == 0)
{
cpp_int res = fr.num / fr.den;
os << res;
}
else
os << fr.num << "/" << fr.den;
return os;
}
cpp_int Fraction::gcf(cpp_int a, cpp_int b)
{
if( b == 0)
return abs(a);
else
return gcf(b, a%b);
}
cpp_int Fraction::lcd(cpp_int a, cpp_int b)
{
cpp_int n = gcf(a, b);
return (a / n) * b;
}
void Fraction::simplify()
{
if (den == 0 || num == 0)
{
num = 0;
den = 1;
}
// Put neg. sign in numerator only.
if (den < 0)
{
num *= -1;
den *= -1;
}
// Factor out GCF from numerator and denominator.
cpp_int n = gcf(num, den);
num = num / n;
den = den / n;
}
Fraction Fraction::operator - (const Fraction& fr) const
{
Fraction sub( (num * fr.den) - (fr.num * den), den * fr.den );
sub.simplify();
return sub;
}
Fraction Fraction::operator+(const Fraction& fr) const
{
Fraction add ((num * fr.den) + (fr.num * den), den * fr.den );
add.simplify();
return add;
}
Fraction Fraction::operator*(const Fraction& fr) const
{
Fraction mult(num * fr.num, den * fr.den);
mult.simplify();
return mult;
}
Fraction Fraction::operator / (const Fraction& fr) const
{
Fraction sub(num * fr.den, den * fr.num);
sub.simplify();
return sub;
}
Fraction operator+(const Fraction& fr, cpp_int n)
{
return (Fraction(n) + fr);
}
Fraction operator+(cpp_int n, const Fraction& fr)
{
return (Fraction(n) + fr);
}
Fraction operator-(const Fraction& fr, cpp_int n)
{
return (Fraction(n) - fr);
}
Fraction operator-(cpp_int n, const Fraction& fr)
{
return (Fraction(n) - fr);
}
Fraction operator/(const Fraction& fr, cpp_int n)
{
return (Fraction(n) / fr);
}
Fraction operator/(cpp_int n, const Fraction& fr)
{
return (Fraction(n) / fr);
}
Fraction operator*(const Fraction& fr, cpp_int n)
{
return (Fraction(n) * fr);
}
Fraction operator*(cpp_int n, const Fraction& fr)
{
return (Fraction(n) * fr);
}
void operator+=(Fraction& f, const Fraction& fr)
{
f = f + fr;
}
void operator-=(Fraction& f, const Fraction& fr)
{
f = f - fr;
}
void operator/=(Fraction& f, const Fraction& fr)
{
f = f / fr;
}
void operator*=(Fraction& f, const Fraction& fr)
{
f = f * fr;
}
void operator+=(Fraction& fr, cpp_int n)
{
fr = fr + n;
}
void operator-=(Fraction& fr, cpp_int n)
{
fr = fr - n;
}
void operator*=(Fraction& fr, cpp_int n)
{
fr = fr * n;
}
void operator/=(Fraction& fr, cpp_int n)
{
fr = fr / n;
}
Matrix.h
#ifndef MATRIX_H_INCLUDED
#define MATRIX_H_INCLUDED
#include <vector>
#include <ostream>
#include <assert.h>
#include "Fraction.h"
#include <boost/multiprecision/cpp_int.hpp>
using boost::multiprecision::cpp_int;
class Matrix
{
private:
int rows_num;
int cols_num;
std::vector <std::vector<Fraction>> data;
public:
Matrix () = default;
Matrix(int r, int c) : rows_num(r), cols_num(c)
{
assert(r > 0 && c > 0);
data.resize(r, std::vector<Fraction>( c, {0} ) );
}
Matrix(int r, int c, cpp_int n) : rows_num(r), cols_num(c)
{
assert(r > 0 && c > 0);
data.resize(r, std::vector<Fraction>( c, {n} ) );
}
friend std::ostream& operator<<(std::ostream& out, const Matrix& mx);
friend std::ostream& operator<<(std::ostream& out, const std::vector<Fraction>& diag);
bool operator== (Matrix& mx);
bool operator!= (Matrix& mx);
Matrix operator+(const Matrix& mx);
Matrix operator-(const Matrix& mx);
Matrix operator*(const Matrix& mx);
void operator+=(const Matrix& mx);
void operator-=(const Matrix& mx);
void operator*=(const Matrix& mx);
friend Matrix operator*(const Matrix& mx, cpp_int n);
friend Matrix operator*(cpp_int n, const Matrix& mx);
friend void operator*=(Matrix& mx, cpp_int n);
Fraction& operator()(int r, int c)
{
return data[r][c];
}
int size()
{
return rows_num * cols_num;
}
void resize(int r, int c)
{
data.clear();
data.resize(r, std::vector<Fraction>( c, {0} ) );
rows_num = r;
cols_num = c;
}
int rows()
{
return rows_num;
}
int cols()
{
return cols_num;
}
static Matrix IDENTITY(int n);
static Matrix CONSTANT(int r, int c, cpp_int n);
bool is_square()
{
return rows_num == cols_num;
}
bool is_identity();
bool is_symmetric();
bool is_skewSymmetric();
bool is_diagonal();
bool is_null();
bool is_constant();
bool is_orthogonal();
bool is_invertible();
bool is_upperTriangular();
bool is_lowerTriangular();
Matrix transpose();
Fraction determinant();
Matrix inverse();
Matrix gaussJordanElimination();
};
#endif // MATRIX_H_INCLUDED
Matrix.cpp
#ifndef MATRIX_H_INCLUDED
#define MATRIX_H_INCLUDED
#include <vector>
#include <ostream>
#include <assert.h>
#include "Fraction.h"
#include <boost/multiprecision/cpp_int.hpp>
using boost::multiprecision::cpp_int;
class Matrix
{
private:
int rows_num;
int cols_num;
std::vector <std::vector<Fraction>> data;
public:
Matrix () = default;
Matrix(int r, int c) : rows_num(r), cols_num(c)
{
assert(r > 0 && c > 0);
data.resize(r, std::vector<Fraction>( c, {0} ) );
}
Matrix(int r, int c, cpp_int n) : rows_num(r), cols_num(c)
{
assert(r > 0 && c > 0);
data.resize(r, std::vector<Fraction>( c, {n} ) );
}
friend std::ostream& operator<<(std::ostream& out, const Matrix& mx);
friend std::ostream& operator<<(std::ostream& out, const std::vector<Fraction>& diag);
bool operator== (Matrix& mx);
bool operator!= (Matrix& mx);
Matrix operator+(const Matrix& mx);
Matrix operator-(const Matrix& mx);
Matrix operator*(const Matrix& mx);
void operator+=(const Matrix& mx);
void operator-=(const Matrix& mx);
void operator*=(const Matrix& mx);
friend Matrix operator*(const Matrix& mx, cpp_int n);
friend Matrix operator*(cpp_int n, const Matrix& mx);
friend void operator*=(Matrix& mx, cpp_int n);
Fraction& operator()(int r, int c)
{
return data[r][c];
}
int size()
{
return rows_num * cols_num;
}
void resize(int r, int c)
{
data.clear();
data.resize(r, std::vector<Fraction>( c, {0} ) );
rows_num = r;
cols_num = c;
}
int rows()
{
return rows_num;
}
int cols()
{
return cols_num;
}
static Matrix IDENTITY(int n);
static Matrix CONSTANT(int r, int c, cpp_int n);
bool is_square()
{
return rows_num == cols_num;
}
bool is_identity();
bool is_symmetric();
bool is_skewSymmetric();
bool is_diagonal();
bool is_null();
bool is_constant();
bool is_orthogonal();
bool is_invertible();
bool is_upperTriangular();
bool is_lowerTriangular();
Matrix transpose();
Fraction determinant();
Matrix inverse();
Matrix gaussJordanElimination();
};
#endif // MATRIX_H_INCLUDED
Matrix.cpp
#include "Matrix.h"
#include "Utility.h"
#include <iostream>
#include <assert.h>
#include <boost/format.hpp>
using namespace std;
using namespace utilities;
using namespace boost;
ostream& operator<<(ostream& os, const Matrix& mx)
{
// a little hack I came up with to my output formatting
vector<int> vec;
for(int i = 0; i < mx.rows_num; ++i)
for(int j = 0; j < mx.cols_num; ++j)
{
int n = static_cast<int>(mx.data[i][j].num);
int d = static_cast<int>(mx.data[i][j].den);
string s = to_string(n);
int width = s.size();
s = to_string(d);
width += s.size();
vec.push_back(width);
}
int width = *max_element(vec.begin(), vec.end()) + 4;
string w = "%";
w += to_string(width) + "s";
int len = mx.data.size();
for (int i = 0; i < len; i++)
{
int len_ = mx.data[i].size();
for (int j = 0; j < len_; j++)
os << format(w.c_str()) % mx.data[i][j];
os << endl;
}
return os;
}
bool Matrix::operator==(Matrix& mx)
{
if(rows_num != mx.rows_num || cols_num != mx.cols_num)
return false;
for(int i = 0; i < rows_num; ++i)
for(int j = 0; j < cols_num; ++j)
if(data[i][j] != mx.data[i][j])
return false;
return true;
}
bool Matrix::operator!=(Matrix& mx)
{
if(rows_num != mx.rows_num || cols_num != mx.cols_num)
return true;
for(int i = 0; i < rows_num; ++i)
for(int j = 0; j < cols_num; ++j)
if(data[i][j] != mx.data[i][j])
return true;
return false;
}
Matrix Matrix::operator+(const Matrix& mx)
{
assert(rows_num == mx.rows_num && cols_num == mx.cols_num);
Matrix add(rows_num, cols_num);
for(int i = 0; i < rows_num; ++i)
for(int j = 0; j < cols_num; ++j)
add.data[ i ][ j ] = data[ i ][ j ] + mx.data[ i ][ j ];
return add;
}
Matrix Matrix::operator-(const Matrix& mx)
{
assert(rows_num == mx.rows_num && cols_num == mx.cols_num);
Matrix sub(rows_num, cols_num);
for(int i = 0; i < rows_num; ++i)
for(int j = 0; j < cols_num; ++j)
sub.data[ i ][ j ] = data[ i ][ j ] - mx.data[ i ][ j ];
return sub;
}
Matrix Matrix::operator*(const Matrix& mx)
{
assert(cols_num == mx.rows_num);
Matrix mult(rows_num, mx.cols_num);
for(int i = 0; i < rows_num; ++i)
for (int j = 0; j < mx.cols_num; ++j)
for(int x = 0; x < cols_num; ++x)
mult.data[ i ][ j ] += data[ i ][ x ] * mx.data[ x ][ j ];
return mult;
}
void Matrix::operator*=(const Matrix& mx)
{
assert(cols_num == mx.rows_num);
*this = (*this * mx);
}
void Matrix::operator-=(const Matrix& mx)
{
assert(rows_num == mx.rows_num && cols_num == mx.cols_num);
*this = (*this - mx);
}
void Matrix::operator+=(const Matrix& mx)
{
assert(rows_num == mx.rows_num && cols_num == mx.cols_num);
*this = (*this + mx);
}
Matrix operator*(const Matrix& mx, cpp_int n)
{
Matrix mult(mx.rows_num, mx.cols_num);
for(int i = 0; i < mx.rows_num; ++i)
for(int j = 0; j < mx.cols_num; ++j)
mult.data[i][j] = mx.data[i][j] * n;
return mult;
}
Matrix operator*(cpp_int n, const Matrix& mx)
{
Matrix mult(mx.rows_num, mx.cols_num);
for(int i = 0; i < mx.rows_num; ++i)
for(int j = 0; j < mx.cols_num; ++j)
mult.data[i][j] = mx.data[i][j] * n;
return mult;
}
void operator*=(Matrix& mx, cpp_int n)
{
mx = mx * n;
}
Matrix Matrix::IDENTITY(int n)
{
assert(n > 0);
Matrix mx(n,n);
for(int i = 0; i < n; ++i)
mx.data[i][i] = {1};
return mx;
}
Matrix Matrix::CONSTANT(int r, int c, cpp_int n)
{
vector <std::vector<Fraction>> vec(r, vector<Fraction>( c, {n} ) );
Matrix mx(r,c);
mx.data = vec;
return mx;
}
bool Matrix::is_identity()
{
if(! is_square())
return false;
for(int i = 0; i < rows_num; ++i)
for(int j = 0; j < cols_num; ++j)
{
if(i != j && data[ i ][ j ] != 0)
return false;
if(i == j && data[ i ][ j ] != 1)
return false;
}
return true;
}
bool Matrix::is_symmetric()
{
if(! is_square())
return false;
for(int i = 0; i < rows_num; ++i)
for(int j = 0; j < cols_num; ++j)
if(data[ i ][ j ] != data[ j ][ i ])
return false;
return true;
}
bool Matrix::is_skewSymmetric()
{
if(! is_square())
return false;
for(int i = 0; i < rows_num; ++i)
for(int j = 0; j < cols_num; ++j)
if(i != j)
if( data[ i ][ j ] != ( data[ j ][ i ]*(-1) ) )
return false;
return true;
}
bool Matrix::is_diagonal()
{
if(! is_square())
return false;
for(int i = 0; i < rows_num; ++i)
for(int j = 0; j < cols_num; ++j)
if(i != j)
if( data[ i ][ j ] != 0 )
return false;
return true;
}
bool Matrix::is_null()
{
for(int i = 0; i < rows_num; ++i)
for(int j = 0; j < cols_num; ++j)
if( data[ i ][ j ] != 0 )
return false;
return true;
}
bool Matrix::is_constant()
{
for(int i = 0; i < rows_num; ++i)
for(int j = 0; j < cols_num; ++j)
if( data[ i ][ j ] != data[0][0] )
return false;
return true;
}
bool Matrix::is_orthogonal()
{
if(! is_square())
return false;
Matrix identity = Matrix::IDENTITY(cols_num);
return (*this * this->transpose() == identity);
}
bool Matrix::is_invertible()
{
return this->determinant() != 0;
}
bool Matrix::is_lowerTriangular()
{
if(! is_square())
return false;
for(int i = 0; i < rows_num; ++i)
for(int j = 0; j < cols_num; ++j)
if( j > i && data[i][j] != 0)
return false;
return true;
}
bool Matrix::is_upperTriangular()
{
if(! is_square())
return false;
for(int i = 0; i < rows_num; ++i)
for(int j = 0; j < cols_num; ++j)
if( j < i && data[i][j] != 0)
return false;
return true;
}
Matrix Matrix::transpose()
{
Matrix trans(cols_num, rows_num);
for(int i = 0; i < rows_num; ++i)
for(int j = 0; j < cols_num; ++j)
trans.data[ j ][ i ] = data[ i ][ j ];
return trans;
}
Fraction Matrix::determinant()
{
assert(is_square());
if(is_null())
return {0};
if(is_constant())
return {0};
if(rows_num == 1)
return data[0][0];
if(is_identity())
return {1};
bool alternative_pivot_1_found;
bool pivot_not_zero_found;
int row_with_alternative_pivot;
int row_with_pivot_not_zero;
int pivot_row = 0;
int pivot_col = 0;
Matrix mx = *this;
vector<Fraction> row_mults;
int sign = 1;
while (pivot_row < (rows_num - 1))
{
alternative_pivot_1_found = pivotEqualTo_one_Found (mx.data, pivot_row, pivot_col,
rows_num, row_with_alternative_pivot);
pivot_not_zero_found = pivotNot_zero_Found(mx.data,
pivot_row, pivot_col, rows_num, row_with_pivot_not_zero);
if (mx.data[ pivot_row ] [ pivot_col ] != 1 && alternative_pivot_1_found )
{
swapRows(mx.data, pivot_row, row_with_alternative_pivot, cols_num);
sign *= (-1);
}
else if (mx.data[ pivot_row ] [ pivot_col ] == 0 && pivot_not_zero_found )
{
swapRows(mx.data, pivot_row, row_with_pivot_not_zero, cols_num );
sign *= (-1);
}
int col_dif_zero;
firstNumberNot_zero(mx.data, pivot_row, cols_num, col_dif_zero);
if (( mx.data[pivot_row] [col_dif_zero] ) != 1)
{
row_mults.push_back(mx.data[pivot_row] [col_dif_zero]);
changePivotTo_one(mx.data, pivot_row, cols_num,
mx.data[ pivot_row ][ col_dif_zero ]);
}
int n = pivot_row + 1;
while (n < rows_num)
{
Fraction constant = mx.data[ n ][ col_dif_zero ];
if(constant != 0)
zeroOutTheColumn(mx.data, n, pivot_row, cols_num, constant);
++n;
}
++pivot_row;
++pivot_col;
}
Fraction det(1);
for(int i = 0; i < rows_num; ++i)
det *= mx.data[i][i];
int len = row_mults.size();
for(int i = 0; i < len; ++i)
det = det * row_mults[i];
det *= sign;
return det;
}
Matrix Matrix::inverse()
{
assert(is_square());
if( ! is_invertible())
{
cout << "NOT INVERTIBLE\n";
return *this;
}
Matrix mx = *this;
Matrix inverse = Matrix::IDENTITY(rows_num);
bool alternative_pivot_1_found;
bool pivot_not_zero_found;
bool number_not_zero_found;
int row_with_alternative_pivot;
int row_with_pivot_not_zero;
int pivot_row = 0;
int pivot_col = 0;
//Gauss Elimination
while (pivot_row < (rows_num - 1))
{
alternative_pivot_1_found = pivotEqualTo_one_Found (mx.data, pivot_row, pivot_col,
rows_num, row_with_alternative_pivot);
pivot_not_zero_found = pivotNot_zero_Found(mx.data,
pivot_row, pivot_col, rows_num, row_with_pivot_not_zero);
if (mx.data[ pivot_row ] [ pivot_col ] != 1 && alternative_pivot_1_found )
{
swapRows(inverse.data, pivot_row, row_with_alternative_pivot, cols_num);
swapRows(mx.data, pivot_row, row_with_alternative_pivot, cols_num);
}
else if (mx.data[ pivot_row ] [ pivot_col ] == 0 && pivot_not_zero_found )
{
swapRows(inverse.data, pivot_row, row_with_pivot_not_zero, cols_num);
swapRows(mx.data, pivot_row, row_with_pivot_not_zero, cols_num );
}
int col_dif_zero;
number_not_zero_found = firstNumberNot_zero(mx.data, pivot_row, cols_num, col_dif_zero);
if(number_not_zero_found)
{
if (( mx.data[pivot_row] [col_dif_zero] ) != 1)
{
changePivotTo_one(inverse.data, pivot_row, cols_num,
mx.data[ pivot_row ][ col_dif_zero ]);
changePivotTo_one(mx.data, pivot_row, cols_num,
mx.data[ pivot_row ][ col_dif_zero ]);
}
}
int n = pivot_row + 1;
if(number_not_zero_found)
{
while (n < rows_num)
{
zeroOutTheColumn(inverse.data, n, pivot_row, cols_num, mx.data[ n ][ col_dif_zero ]);
zeroOutTheColumn(mx.data, n, pivot_row, cols_num, mx.data[ n ][ col_dif_zero ]);
++n;
}
}
++pivot_row;
++pivot_col;
}
//Jordan Elimination
while(pivot_row > 0)
{
int col_dif_zero;
number_not_zero_found = firstNumberNot_zero(mx.data, pivot_row, mx.cols_num, col_dif_zero);
if(number_not_zero_found)
{
if (( mx.data[pivot_row] [col_dif_zero] ) != 1)
{
changePivotTo_one(inverse.data, pivot_row, mx.cols_num, mx.data[ pivot_row ][ col_dif_zero ]);
changePivotTo_one(mx.data, pivot_row, mx.cols_num, mx.data[ pivot_row ][ col_dif_zero ]);
}
}
int n = pivot_row - 1;
if(number_not_zero_found)
{
while (n >= 0)
{
zeroOutTheColumn(inverse.data, n, pivot_row, mx.cols_num, mx.data[ n ][ col_dif_zero ]);
zeroOutTheColumn(mx.data, n, pivot_row, mx.cols_num, mx.data[ n ][ col_dif_zero ]);
--n;
}
}
--pivot_row;
}
return inverse;
}
Matrix Matrix::gaussJordanElimination()
{
Matrix mx = *this;
bool alternative_pivot_1_found;
bool pivot_not_zero_found;
bool number_not_zero_found;
int row_with_alternative_pivot;
int row_with_pivot_not_zero;
int pivot_row = 0;
int pivot_col = 0;
///Gauss Elimination
while (pivot_row < (rows_num - 1))
{
alternative_pivot_1_found = pivotEqualTo_one_Found (mx.data, pivot_row, pivot_col,
rows_num, row_with_alternative_pivot);
pivot_not_zero_found = pivotNot_zero_Found(mx.data,
pivot_row, pivot_col, rows_num, row_with_pivot_not_zero);
if (mx.data[ pivot_row ] [ pivot_col ] != 1 && alternative_pivot_1_found )
{
swapRows(mx.data, pivot_row, row_with_alternative_pivot, cols_num);
}
else if (mx.data[ pivot_row ] [ pivot_col ] == 0 && pivot_not_zero_found )
{
swapRows(mx.data, pivot_row, row_with_pivot_not_zero, cols_num );
}
int col_dif_zero;
number_not_zero_found = firstNumberNot_zero(mx.data, pivot_row, cols_num, col_dif_zero);
if(number_not_zero_found)
{
if (( mx.data[pivot_row] [col_dif_zero] ) != 1)
{
changePivotTo_one(mx.data, pivot_row, cols_num,
mx.data[ pivot_row ][ col_dif_zero ]);
}
}
int n = pivot_row + 1;
if(number_not_zero_found)
{
while (n < rows_num)
{
zeroOutTheColumn(mx.data, n, pivot_row, cols_num, mx.data[ n ][ col_dif_zero ]);
++n;
}
}
++pivot_row;
++pivot_col;
}
//Jordan Elimination
while(pivot_row > 0)
{
int col_dif_zero;
number_not_zero_found = firstNumberNot_zero(mx.data, pivot_row, mx.cols_num, col_dif_zero);
if(number_not_zero_found)
{
if (( mx.data[pivot_row] [col_dif_zero] ) != 1)
{
changePivotTo_one(mx.data, pivot_row, mx.cols_num, mx.data[ pivot_row ][ col_dif_zero ]);
}
}
int n = pivot_row - 1;
if(number_not_zero_found)
{
while (n >= 0)
{
zeroOutTheColumn(mx.data, n, pivot_row, mx.cols_num, mx.data[ n ][ col_dif_zero ]);
--n;
}
}
--pivot_row;
}
return mx;
}
main.cpp
#include <iostream>
#include "Matrix.h"
using namespace std;
using namespace boost;
int main()
{
const int m = 5, n = 5;
Matrix a(m,n), b(3,4,3), c;
a(0,0) = {-5};
a(0,1) = {5};
a(0,2) = {-6};
a(0,3) = {-1};
a(0,4) = {0};
a(1,0) = {0};
a(1,1) = {-5};
a(1,2) = {10};
a(1,3) = {-3};
a(1,4) = {3};
a(2,0) = {1};
a(2,1) = {11};
a(2,2) = {6};
a(2,3) = {1};
a(2,4) = {7};
a(3,0) = {4};
a(3,1) = {5};
a(3,2) = {-9};
a(3,3) = {9};
a(3,4) = {-7};
a(4,0) = {-5};
a(4,1) = {10};
a(4,2) = {0};
a(4,3) = {-4};
a(4,4) = {4};
cout << "The Matrix A:" << endl;
cout << a << endl;
cout << "The Determinant of Matrix A: " << a.determinant() << endl;
if(a.is_invertible())
{
cout << "The Inverse of Matrix A:" << endl;
cout << a.inverse() << endl;
}
else
cout << "The Matrix A is not Invertible" << endl;
cout << "The Transpose of Matrix A:" << endl;
cout << a.transpose() << endl;
Matrix x(5,5,4);
cout << "\nThe Matrx X:" << endl;
cout << x;
x *= a;
cout << "\nThe Matrx X After Multiplication:" << endl;
cout << x;
c = x * 4;
cout << "\nThe Matrx C:" << endl;
cout << c;
b(0,2) = {4};
b(1,2) = {5};
b(1,3) = {2};
b(2,0) = {-8};
b(2,3) = {9};
b(0,0) = {1};
b(0,1) = {2};
cout << endl << "The Matrix B:" << endl;
cout << b;
cout << endl << "The Matrix After Being Applied the Gauss-Jordan Elimination:" << endl;
cout << b.gaussJordanElimination() << endl;
Matrix mx(4,4,4);
cout << mx.determinant() << endl;
for(int i = 0; i < m; ++i)
for(int j = 0; j < n; ++j)
{
int x;
cout << "Mx[" << i + 1 << "][" << j + 1 << "]: ";
cin >> x;
a(i,j) = {x};
}
cout << "The Matrix A:" << endl;
cout << a << endl;
c = Matrix::IDENTITY(m);
// cout << a << endl;
// cout << a.transpose();
//cout << a.transpose().determinant() << endl << endl;
// cout << a.determinant();
//cout << c;
}
I use the brute-force method to determine the inverse, determinant and perform the Gauss-Jordan elimination as it is the method I learnt when doing them by hand. But they require too many computations and I am looking for better way (not partial pivoting) to do it.
Edit: I had the link to my GitHub page with this project but I have updated the project based on the first review. Updated Project on GitHub.