#include<iostream>
#include<conio.h>

using namespace std;

# define MAX 10

void transpose(float *A, int m, int n);
void inverse(float *AT, int ra, int ca);
void multiply(
	int* A, //first matrix 
	int ra, //first matrix rows 
    int* B, //second matrix 
	int cb, //second matrix columns 
    int sh, //SHARED DIMENSION as 'first' columns and 'second' rows MUST BE THE SAME 
    int* X //to store the result
     );

void get_mat(float*& m, int& X, int& c);
void disp(float* m, int X, int c);
void multiply(int* AI, int ra, int* B, int cb, int sh, int* X);

float a[10][10];
float b[10][10];
float c[10][10];

int main()
{
        float *A,*AI, *AT, *B, *X;
        int ra, ca;  // rows and columns for matrix ai
        int rb, cb;  // rows and columns for matrix b
		int i,j;
        cout << "First matrix size(rows columns) = ";
        cin >> ra >> ca;

        cout << "Second matrix size(rows columns) = ";
        cin >> rb >> cb;
       
		//if (ca != rb){
		//	cout << "Error: The matrices cannot be multilplied, size mismatch.";
		//	return 0;  
		//}

        A = new float[ra*ca];
		AT = new float[ra*ca];
		AI = new float[ra*ca];
        B = new int[rb*cb];
        X = new int[ra*cb];
       

        get_mat(A,ra,ca);
        get_mat(B,rb,cb);
		cout<<"Original matrix\n";
		disp(A,ra,ca);


		for(i=0; i<ca; i++)
		for(j=0; j<ra; j++)
		{
			a[i][j]=A[ca*i+j];
			cout <<a[i][j]<<"\n";
		
		}

//TRANSPOSE		
		transpose(A,ra,ca);
  
		cout<<"Transposed matrix\n";

		for(i=0; i<ca; i++)
		for(j=0; j<ra; j++)
		{
			AT[ca*i+j]=a[j][i];
			cout <<AT[ca*i+j]<<"\n";
		
		}
//INVERSE
		inverse(AT,ra,ca);

		cout<<"Inverse matrix\n";

		for(i=0; i<ca; i++)
		for(j=0; j<ra; j++)
		{
			AI[ca*i+j]=b[i][j];
			cout <<AI[ca*i+j]<<"\n";

		
		}
//MULTIPLY
        multiply(AI,ra,B,cb,ca,X);

        cout << "\n\nResult = \n";
        disp(X,ra,cb);
        cout << "\n\Result Transpose = \n";
		disp(AT,ra,ca);
		cout << "\n\Result Inverse = \n";
		disp(AI,ra,ca);

        cout << "Press any key to exit...";
        getch();
		delete[] A;
		delete[] AT;
		delete[] AI;
        

        return 0;
}

void transpose(float *A, int m, int n)
{
	int i,j;

	for(i=0; i<n; i++)
	for(j=0; j<m; j++)
	{
			a[i][j]=A[n*i+j];
			cout <<a[i][j]<<"\n";	
	}

	cout<<endl<<"Displaying Matrix Transpose: "<<endl<<endl;
   	for(i=0;i<m;i++)
	{
		for(j=0;j<n;j++)
		{
			 cout<<a[j][i]<<" ";
		}
		cout<<endl<<endl;
	}
	
    getch();
}


void inverse(float *AT, int ra, int ca)
{

	float d,m;
	int i,j,k;
 
	for(i=0; i<ra; i++)
	for(j=0; j<ca; j++)
	{
			a[i][j]=AT[ca*i+j];
			cout <<a[i][j]<<"\n";	
	}

  
	for(i=0;i<ca;i++)
	{
		for(j=0;j<ra;j++)
		{
		  if(i==j)
			  b[i][j]=1;
		  else
			  b[i][j]=0;
		}
	}

	if(a[0][0]==0)
	{
		 for(j=0;j<ca;j++)
		 { 
		   c[0][j]=b[1][j];
		   c[0][j]=a[1][j];
		   a[1][j]=a[0][j];
		   a[0][j]=c[0][j];
		   b[1][j]=b[0][j];
		   b[0][j]=c[0][j];
		 }
	}

	for(i=0;i<ca;i++)
	{
		d=a[i][i];
		
		for(j=0;j<ra;j++)
		{
			a[i][j]=a[i][j]/d;
			b[i][j]=b[i][j]/d;
		}

		for(k=0;k<ca;k++)
		{
			if(k!=i)
			{
				m=a[k][i];
				for(j=0;j<ra;j++)
				{
					a[k][j]=a[k][j]-(a[i][j]*m);
					b[k][j]=b[k][j]-(b[i][j]*m);
				}
			}
		}
	}

	printf("\nInverse of matrix is:\n");
	for(i=0;i<ca;i++)
	{
	for(j=0;j<ra;j++)
		printf(" %f ",b[i][j]);
	
	printf("\n");
		
	}
 getch();
}

void get_mat(float*& m, int& X, int& c)
{
	cout << "Enter [" << X << "x" << c << "] Matrix :\n";
    for (int i=0; i<X*c; i++)
		cin >> m[i];
}

void multiply(int* AI, int ra, int* B, int cb, int sh, int* X)
{
    for(int i=0; i<ra*cb; ++i)
	{
		X[i] = 0;
		for (int j=0; j<sh; ++j)
			X[i] += AI[(i/cb)*sh+j] * B[i%cb+j*cb];
			if (X[i] > 1)
			{
				X[i] = 1;
			}
    }
}

void disp(float* m, int X, int c)
{
    for (int i=0; i<X*c; i++)
	{
		!(i%c) && cout << endl;
		cout << m[i] << '\t';
    }
	cout << endl;
}

//*/