#include<stdio.h>

struct res{
  char undefined;
  double value;
};

typedef struct res risultato;


int get_linea (double a[][10],int riga,int colonna,int m,int n)
{
 int i, j;

 for(i=riga;i<m;i++)
   {
    if(a[i][colonna]!=0)
      {
        for(j=colonna+1;j<n;j++)
          { a[i][j] = a[i][j]/a[i][colonna]; }

        a[i][colonna]=1.0;
        return i;
      }
   }
 return -1;
}


void scambia_linee (double a[][10],int n, int prima, int seconda)
{
 double temp;
 int i;

 if(prima != seconda)
   {
     for(i=0;i<n;i++)
       {
	 temp = a[prima][i];
	 a[prima][i] = a[seconda][i];
	 a[seconda][i] = temp;
       }
   }
}


void normalizza_altri (double a[][10],int da,int col,int m,int n)
{
 int i, j;

 for(i=da+1;i<m;i++)
   {
     for(j=col+1;j<n;j++)
       { a[i][j] = a[i][j]-(a[i][col]*a[da][j]); }

     a[i][col] = 0;
   }
}


void ris_indietro (double a[][10], int m, int n, risultato x[])
{
 int i, j;
 double ris;

 for(i=m-1;i>=0;i--)
   {
     ris = a[i][n-1];

     for(j=n-m+i;j<n-1;j++)
       { ris = ris - a[i][j]*x[j].value; }

     x[i].value=ris;
   }
}


void print_m (double a[][10],int m,int n)
{
 int i, j;

 printf("\n");

 for(i=0;i<m;i++)
   {
     for(j=0;j<n;j++)
       { printf("%5.2lf ",a[i][j]); }

     printf("\n");
   }
}


void print_ris (risultato x[],int m)
{
 int i;

 printf("\n");

 for(i=0;i<m;i++)
   {
     printf("x%d: ",i+1);

     if(x[i].undefined)
       { printf("risultato indefinito\n"); }

     else
       { printf("%5.2lf\n",x[i].value); }
   }
}


void gauss (double a[][10],int m,int n,risultato x[])
{
 int i=0, col=0, linea;

 while(i<m && col<n-1)
   {
     linea = get_linea(a,i,col,m,n);

     if(linea == -1)
       { x[col].undefined = 1; }

     else 
       {
	 x[col].undefined = 0;
	 scambia_linee(a,n,i,linea);
	 normalizza_altri(a,i,col,m,n);
	 i++;
       }

     col++;
   }

 ris_indietro(a,m,n,x);
}


void get_coefficienti (double a[][10],int m,int n)
{
 int riga, colonna;

 for(riga=0;riga<=m-1;riga++)
    {
     printf("\n");
     for(colonna=0;colonna<=n-1;colonna++)
       {
	printf("a%d%d: ",riga+1,colonna+1); scanf("%lf",&a[riga][colonna]);
       }
    }
}


int controllo (double a[][10],int temp,int m,int n,risultato x[])
{
 int j, i, c;
 double ris;

 for(j=0;j<m;j++)
   {
    if(x[j].undefined)
      { return 0; break; }

    else
      {
       for(i=m;i<=(temp-1);i++)
	 {
	  for(c=0;c<=(n-2);c++)
	    { ris=ris+a[i][c]*x[c].value; }

	  if(ris!=a[i][n-1])
	    { return -1; break; }

	  else
	    { ris=0; }
	 }

       return 1;
      }
   }
}



void main(void)
{
 int risp;
 int n, m, temp, ok;
 double matrice[10][10];
 risultato ris[10];

printf("**Algoritmo di Gauss: Risoluzione di sistemi lineari**\n");
printf("******************************************************\n\n");

for(;;)
  {
   printf("Dare il numero di righe della matrice A (max 10): "); scanf("%d",&m);
   printf("Dare il numero di colonne della matrice A (max 10): "); scanf("%d",&n);

   if(m>10 || n>10)
     { printf("\n\n"); continue; }

   printf("Dare i coefficienti della matrice A:\n");

   get_coefficienti (matrice,m,n);

   if(m==(n-1))
     { break; }

   if(m>(n-1))
     { temp=m; m=n-1; break; }


   else
     { printf("\nERROR!!\n\n"); }

  }

 print_m (matrice,m,n);
 gauss(matrice,m,n,ris);
 print_m(matrice,m,n);

 ok=controllo(matrice,temp,m,n,ris); 

 if(ok==-1)
   { printf("\nERROR: Equazioni in disaccordo!!\n"); }

 else
   { print_ris(ris,m); }

 scanf("%d",&risp);
}
