//Programa eliminacion Gauss   con pivotado: matriz cuadrada y descomposicion LU
#include <iostream>
#include <cmath>
#include <iomanip>
#include <fstream>
using namespace std;

void gaussp(int n, double** m, double* v, double** l){
   
//Definir vector  permutacion    
int* per;
per=new int[n];
for (int i=1;i<n;i++) per[i]=i;  


for (int i=0;i<n; i++){
  l[i][i]=1;
  if (i<n-1) for(int j=i+1; j<n; j++) l[i][j]=0;
  }


//ciclo eliminacion  
for (int i=0;i<n;i++){
//search for the pivot
   double piv=abs(m[i][i]);;
   int ipiv=i;
   for (int j=i;j<n;j++){
     if( abs(m[j][i])>piv){ 
       ipiv=j;
       piv= abs(m[j][i]);
       }
      }
//Permutar filas i y  ipiv 
     for (int j=i;j<n;j++) {
     double temp=m[i][j];
     m[i][j]=m[ipiv][j];
     m[ipiv][j]=temp;
     }  
     double temp = v[i];
     v[i]=v[ipiv];
     v[ipiv]=temp;

//Permutar vector permutacion  
     int itemp=per[i];           
     per[i]=per[ipiv];
     per[ipiv]=itemp;
       
//Eliminacion
  for (int j=i+1; j<n; j++){
    double   piv=m[j][i]/m[i][i]; //m[j][i] se anula despues de la primera elim.
    l[j][i]=piv;
    for (int k=i; k<n; k++){     
      m[j][k]=m[j][k]- piv*m[i][k];
      }
      v[j]=v[j]- piv*v[i];
    }
  }    
}

void backsus(int n,double**m, double* v, double* x){
//solucion de un sistema triangular superior por sustitucion hacia atras
for (int i=n-1;i>=0;i--){
   x[i]=v[i];
  for (int j= n-1;j>i;j--)
    x[i]=x[i]-m[i][j]*x[j];
    x[i]=x[i]/m[i][i];
  }
}     

int  main(){
//definir data file
ifstream fin("gausslu.dat");
int n;
//leer dimension del sistema
fin>>n;
//Definir matriz  coefficientes 
double** mat;
mat = new double* [n];
for (int i=0;i<n;i++) mat[i]=new double [n];
//definir vector terminos independientes
double* b;
b = new double [n];
//Leer matriz coeficient;
for (int i=0; i<n; i++)
  for (int j=0;j<n; j++)
    fin>>mat[i][j];

//Leer vector terminos  independientes 
for (int i=0;i<n;i++)
  fin>>b[i];

// Verificar lectura de datos 

cout<<"Datos leidos"<<endl;
for (int i=0; i<n; i++){
cout<<endl;
  for (int j=0;j<n; j++)
    cout<<mat[i][j]<<"   ";  
   } 
cout <<endl<<endl;
   
for (int i=0; i<n;i++)
  cout<<b[i]<<"  ";   
cout<< endl<<endl;

//Definir matriz L
double** l;
l = new double* [n];
for (int i=0;i<n;i++) l[i]=new double [n];


gaussp(n,mat,b,l);

// Imprimir  sistema reducido 
cout<<"Sistema  reducido"<<endl;
 for (int i=0; i<n; i++){
cout<<endl;
  for (int j=0;j<n; j++)
    cout<<mat[i][j]<<"   ";  
   } 
cout <<endl<<endl;;
   
for (int i=0; i<n;i++)
  cout<<b[i]<<"  ";   
cout<< endl<<endl;; 


// Print l
cout<<" Matriz  L"<<endl;
 for (int i=0; i<n; i++){
cout<<endl;
  for (int j=0;j<n; j++)
    cout<<l[i][j]<<"   ";  
   } 
cout <<endl<<endl;

//Solucion del sistema por  substitucion hacia atras 
double* x;
x= new double [n];   
backsus(n,mat,b,x);

//Imprimir  solucion 

cout<<"Vector de  soluciones"<<endl; 
for (int i=0; i<n;i++)
  cout<<"x["<<i<<"]="<<x[i]<<"  ";   
cout<< endl; 

return 0;
}  
