/*************************************************************************
			     TD de C
			    EXERCICE 3

	      Olivier SANNIER
	      Denis   VANPEPERSTRAETE
	      2Šme ann‚e, groupe C2
************************************************************************/
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>

/*----------------------------------------------------------------------
  aff_tab : affiche la matrice pass‚e en paramŠtre
-----------------------------------------------------------------------*/
void aff_tab(float **tab, int m, int n)
{
  int i,j;
  for (i=0;i<m;i++)
   {for (j=0;j<n;j++)
      printf(" %7.3f ",tab[i][j]);
    printf("\n");
   }
}

/*----------------------------------------------------------------------
  creation : alloue et saisie une nouvelle matrice.
	     renvoie un pointeur sur cette matrice.
-----------------------------------------------------------------------*/
float **creation(int m, int n)
{
 float **temp;
 int i,j;
 float inter;
 temp=(float **)malloc(m*sizeof(float *));

 for (i=0;i<m;i++)
  {
   temp[i]=(float *)malloc(n*sizeof(float));
   for (j=0;j<n;j++)
    {
     printf("\nLigne nř%d, colonne nř%d :",i,j);
     scanf("%f",&inter);
     temp[i][j]=inter;
     fflush(0);
    }
  }
return(temp);
}

/*----------------------------------------------------------------------
  libre : equivalent de free mais pour un pointeur de matrice.
-----------------------------------------------------------------------*/
void libre(float **tab, int n)
{
 int i;
 for (i=0;i<n;i++)
   free(tab[i]);
 free(tab);
}

/*----------------------------------------------------------------------
  unite : alloue une matrice unit‚ de dimension m.
	  renvoie un pointeur sur cette matrice.
-----------------------------------------------------------------------*/
float **unite(int m)
{
 float **temp;
 int i,j;

 temp=(float **)malloc(m*sizeof(float *));

 for (i=0;i<m;i++)
  {
   temp[i]=(float *)malloc(m*sizeof(float));
   for (j=0;j<m;j++)
    {
     if (i==j)
       temp[i][j]=1;
     else
       temp[i][j]=0;
    }
  }
return(temp);
}

/*----------------------------------------------------------------------
  transpo : calcule la transpos‚e de la matrice pass‚e en paramŠtre.
	    renvoie un pointeur sur la matrice r‚sultat nouvellement
	    allou‚e.
-----------------------------------------------------------------------*/
float **transpo(float **tab, int m,int n)
{
 float **temp;
 int i,j;

 temp=(float **)malloc(n*sizeof(float *));

 for (i=0;i<n;i++)
  {
   temp[i]=(float *)malloc(m*sizeof(float));
   for (j=0;j<m;j++)
    {
     temp[i][j]=tab[j][i];
    }
  }
return(temp);
}

/*----------------------------------------------------------------------
  add_mat : effectue une addition entre les deux matrices pass‚es en
	    paramŠtre.
	    renvoie un pointeur sur la matrice r‚sultat nouvellement
	    allou‚e.
-----------------------------------------------------------------------*/
float **add_mat(float **A, float **B, int m, int n)
{
 int i,j;
 float **temp;


 temp=(float **)malloc(n*sizeof(float *));

 for (i=0;i<n;i++)
  {
   temp[i]=(float *)malloc(m*sizeof(float));
   for (j=0;j<m;j++)
     temp[i][j]=A[i][j]+B[i][j];
  }

return temp;
}

/*----------------------------------------------------------------------
  mul_mat : effectue une multiplication entre les deux matrices pass‚es
	    en paramŠtre.
	    renvoie un pointeur sur la matrice r‚sultat nouvellement
	    allou‚e.
-----------------------------------------------------------------------*/
float **mul_mat(float **A, float **B, int n, int p, int q, int r)
{
 int i,j,k;
 float **temp;

  if (p!=q)
  {
    printf("Impossible de multiplier les deux matrices");
    return NULL;
  }
  else
  {
    temp=(float **)malloc(n*sizeof(float *));

    for (i=0;i<n;i++)
    {
      temp[i]=(float *)malloc(r*sizeof(float));
      for (j=0;j<r;j++)
      {
	temp[i][j] = 0;
	for(k=0; k<p;k++)
	  temp[i][j]=temp[i][j]+A[i][k]*B[k][j];
      }
    }

    return temp;
  }
}


/*----------------------------------------------------------------------
  main : fonction principale g‚rant le menu.
-----------------------------------------------------------------------*/
void main(void)
{
 float **A;
 float **B;
 float **C;
 int m,n,p,q,r,i;
 char choix;

do{
 clrscr();

 printf("Op‚rations sur les matrices : \n");
 printf("1 : Matrice unit‚\n");
 printf("2 : Transpos‚e\n");
 printf("3 : Addition\n");
 printf("4 : Multiplication\n");
 printf("5 : Puissance\n");
 printf("q : Quitter\n");
 printf("\nVotre choix ? ");
 fflush(0);
 scanf("%c", &choix);

 switch (choix)
 {
   case '1' : clrscr();
	      printf("Matrice unit‚\n");
	      printf("Dimension\n");
	      scanf("%d",&m);

	      clrscr();
	      C=unite(m);
	      aff_tab(C,m,m);
	      getch();
	      libre(C,n);


	      break;
   case '2' : clrscr();
	      printf("Transpos‚e d'une matrice\n");
	      printf("nb de lignes\n");
	      scanf("%d",&m);
	      printf("nb de colonnes\n");
	      scanf("%d",&n);

	      printf("\nSaisie de la matrice");
	      A=creation(m,n);

	      C=transpo(A, m, n);

	      clrscr();
	      printf("Transpos‚e de \n");
	      aff_tab(A,m,n);
	      printf("\t=\n");

	      aff_tab(C,n,m);
	      getch();
	      libre(A,n);
	      libre(C,m);

	      break;
   case '3' : clrscr();
	      printf("Addition de 2 matrices\n");
	      printf("nb de lignes\n");
	      scanf("%d",&m);
	      printf("nb de colonnes\n");
	      scanf("%d",&n);

	      printf("\nSaisie de la premiŠre matrice");
	      A=creation(m,n);
	      printf("\nSaisie de la deuxiŠme matrice");
	      B=creation(m,n);

	      C=add_mat(A, B, m, n);

	      clrscr();
	      aff_tab(A,m,n);
	      printf("\t+\n");
	      aff_tab(B,m,n);
	      printf("\n\t=\n\n");
	      aff_tab(C,m,n);
	      getch();
	      libre(A,n);
	      libre(B,n);
	      libre(C,n);

	      break;
   case '4' : clrscr();
	      printf("Multiplication de 2 matrices\n");
	      printf("Premiere matrice\n");
	      printf("nb de lignes\n");
	      scanf("%d",&n);
	      printf("nb de colonnes\n");
	      scanf("%d",&p);

	      printf("Deuxieme matrice\n");
	      printf("nb de lignes\n");
	      scanf("%d",&q);
	      printf("nb de colonnes\n");
	      scanf("%d",&r);

	      if (p==q)
	      {
		printf("\nSaisie de la premiŠre matrice");
		A=creation(n,p);
		printf("\nSaisie de la deuxiŠme matrice");
		B=creation(q,r);

		C=mul_mat(A, B, n, p, q, r);

		clrscr();
		aff_tab(A,n,p);
		printf("\t*\n");
		aff_tab(B,q,r);
		printf("\n\t=\n\n");
		aff_tab(C,n,r);
		getch();
		libre(A,n);
		libre(B,q);
		libre(C,n);
	      }
	      else
		printf("Impossible de multiplier les deux matrices");

	      break;
   case '5' : clrscr();
	      printf("Puissance d'une matrice carr‚e\n");
	      printf("Dimension\n");
	      scanf("%d",&m);
	      printf("Puissance\n");
	      scanf("%d",&p);

	      printf("\nSaisie de la matrice :");
	      A=creation(m,m);

	      C=unite(m);
	      for(i=0;i<p;i++)
		C=mul_mat(C, A, m, m, m ,m);

	      clrscr();
	      aff_tab(A,m,m);
	      printf("puissance %d\n \t=\n", p);
	      aff_tab(C,m,m);
	      getch();
	      libre(A,m);
	      libre(C,m);

	      break;
   case 'q' :
   case 'Q' : break;
   default : printf("mauvais choix");
	     getch();
 }

}while((choix!='q')&&(choix!='Q'));
/* printf("nb de lignes\n");
 scanf("%d",&n);
 printf("nb de colonnes\n");
 scanf("%d",&m);

 tab=creation(m,n);
 aff_tab(tab,m,n);
 getch();
 libre(tab,n);  */
}
