/* CS 203. Correction de la feuille 3 */
/* Credit : certains des programmes presentes ici ont ete realises par Pierre Cohort */

#include <stdio.h>

/* exercice 1 */
/* commentaire : il faut passer l'adresse de lamdba et mu pour que la fonction
   puisse modifier effectivement ces variables. */

void LameLambdaMu(double Young, double Poisson, double* Lambda, double* Mu)
{
  *Lambda=Young*Poisson/((1.+Poisson)*(1.-2.*Poisson));
  *Mu=Young/(2.*(1.+Poisson));
}

/* exercice 2 */
void crible(int maxcrible)
{
  int Tableau[maxcrible-1]; 
  int n, i;

  /* Le tableau des entiers. Attention : la case i reprente l'entier i+2 */
  /* a la fin de la procedure Tableau[n-2]=1 si n est premier et 0 sinon */

  for (i=0;i<=maxcrible-2;i++)
    Tableau[i]=1; 
  /* Tout entier est presume premier jusqu'a ce que la preuve de sa non primalite soit
     apportee au cours de la bouble suivante */


  for (n=2;n<=sqrt(maxcrible);n++)
    if (Tableau[n-2]==1)           // Si n est premier...
      for (i=2;i<=maxcrible/n;i++) // ... alors n*2, n*3, ...
      	Tableau[i*n-2]=0;          // ... ne le sont pas !

  for (n=2;n<=maxcrible;n++)
    if (Tableau[n-2]==1)
      printf("%d ",n);
  printf("\n");
}


/* exercice 3*/
/* question 3.1 */
typedef struct compl {
  float re, im;
} complexe;

complexe CreerComplexe (float a, float b)
     /* Creation d'un nombre complexe
	ENTREE : a partie reelle et b partie imaginaire de type float
	SORTIE : a+ib de type complexe
     */
{
  complexe z;
  z.re=a;
  z.im=b;
  return z;
}

float PartieReelle (complexe z)
     /* Partie reelle d'un nombre complexe
	ENTREE : z de type complexe
	SORTIE : partie reelle de z, de type float
     */
{
  return(z.re);
}

float PartieImaginaire (complexe z)
     /* Partie imaginaire d'un nombre complexe
	ENTREE : z de type complexe
	SORTIE : partie imaginaire de z, de type float
     */
{
  return(z.im);
}

complexe SommeComplexe (complexe z1, complexe z2)
     /* Somme de deux nombres complexes
	ENTREE : z1 et z2 de type complexe
	SORTIE : z1+z2 de type complexe
     */
{
  float a, b;
  complexe z;
  a=PartieReelle(z1)+PartieReelle(z2);
  b=PartieImaginaire(z1)+PartieImaginaire(z2);
  z=CreerComplexe(a,b);
  return z;
}

complexe ProduitComplexe (complexe z1, complexe z2)
     /* Produit de deux nombres complexes
	ENTREE : z1 et z2 de type complexe
	SORTIE : z1*z2 de type complexe
     */
{
  float a, b;
  complexe z;
  a=(PartieReelle(z1))*(PartieReelle(z2))-(PartieImaginaire(z1))*(PartieImaginaire(z2));
  b=(PartieReelle(z1))*(PartieImaginaire(z2))+(PartieImaginaire(z1))*(PartieReelle(z2));
  z=CreerComplexe(a,b);
  return z;
}

float ModuleComplexe (complexe z)
     /* Module d'un nombre complexe
	ENTREE : z de type complexe
	SORTIE : |z| de type float
     */
{
  return(sqrt((PartieReelle(z))*(PartieReelle(z))+(PartieImaginaire(z))*(PartieImaginaire(z))));
}

void AfficherComplexe (complexe z)
     /* Affichage d'un nombre complexe
	ENTREE : z de type complexe
	EFFET : affichage du complexe sur stdout
     */
{
  if (PartieImaginaire(z)>0)
    printf("%.5f+%.5fi\n",PartieReelle(z),PartieImaginaire(z));
  if (PartieImaginaire(z)<0)
    printf("%.5f-%.5fi\n",PartieReelle(z),fabs(PartieImaginaire(z)));
  if (PartieImaginaire(z)==0)
    printf("%.5f\n",PartieReelle(z));
}

/* question 3.2*/
int EstDansM (complexe K)
     /* Fonction indicatrice de l'ensemble de Mandelbrot
	ENTREE : un complexe K
	SORTIE : 1 si K est dans l'ensemble de Mandelbrot, 0 sinon.
	REMARQUE : On suppose qu'une suite de complexes est bornee ssi 
	les modules des 250 premiers termes sont inferieurs a 4
     */
{
  complexe z; // contient le zn 
  float module, MaxModule; // module et plus grand module
  int n; // variable de boucle

  z=CreerComplexe(0.0,0.0); 
  MaxModule=0.0;
  for (n=1;n<=250;n++)
    {
      z=SommeComplexe(ProduitComplexe(z,z),K);
      module=ModuleComplexe(z);
      if (module>MaxModule) MaxModule=module;
    }
  return (MaxModule<=4);
}

/* question 3.3*/
int main_exercice3()
{
  float x1, x2, y1, y2;
  int n1, n2, j, l;
  complexe z;

  printf("Entrez x1 x2 y1 et y2 separes par des espaces\n");
  scanf("%f %f %f %f",&x1,&x2,&y1,&y2);
  printf("Entrez n1 et n2 separes par des espaces\n");
  scanf("%d %d",&n1,&n2);
  
  for (l=0;l<=n2;l++)
    for (j=0;j<=n1;j++)
      {
	z=CreerComplexe(x1+j*(x2-x1)/n1,y1+l*(y2-y1)/n2);
	if (EstDansM(z))
	  AfficherComplexe(z);
      }
  
  return 0;
}

/* exercice 4 */
/* question 4.1 */
int exercice4_question1()
{
  int x;
  int *y;
  int **z;
  x=1;
  y=&x; // y pointe vers x
  z=(int**)malloc(2*sizeof(int*));
  z[0]=y; // Le premiere case du tableau z pointe vers un pointeur vers x
  x=2; // maintenant x vaut 2 donc *y=2 et x[0] pointe vers un pointeur vers 2
  z[1]=y; // // La deuxieme case du tableau z pointe vers un pointeur vers x
  printf("%d %d\n",*(z[0]),*(z[1])); // Affichage de x deux fois soit 2 et 2
  return(0);
}

/* question 4.2 */
int exercice4_question2()
{
  int x, y;
  int *T;
  x=1;
  y=2;
  T=(int*)malloc(2*sizeof(int));
  T[0]=++x; // La premiere case de T recoit 2 car x est incremente avant l'affectation
  T[1]=y; // La deuxieme case de T recoit 2
  x+=5; // les modifications sur x et y n'affecteront pas T
  y--;
  printf("%d %d\n",T[0],T[1]); // Affichage de 2 et 2
  return(0);
}


/* exercice 5 */
void exercice5_expression1()
{
  int n=2;
  int* p;
  p=&n;

  printf("n=%d\n",n);
  *(&(*p))=4;
  /* *p est la variable pointee par p, soit n car on a initialise p avec 
     l'adresse de n. Donc &(*p) vaut &n et finalement *(&(*p)) designe l'entier n.
     On a donc n=4 en fin d'execution. */
  printf("n=%d\n",n);
}

void exercice5_expression2()
{
  int n=2;
  int* p;
  p=&n;

  printf("n=%d\n",n);
  (*p)++;
  /* ici, on incremente la variable pointee par p, soit n. L'entier n vaut
     donc 3 en fin d'execution */
  printf("n=%d\n",n);
}


int main()
{
  printf("Exercice 1\n");
  {
    double E=1.,nu=0.7,lambda,mu;
    LameLambdaMu(E,nu,&lambda,&mu);
    printf("Lamdba=%f Mu=%f\n",lambda,mu);
  }
  printf("\n\n\n");

  printf("Exercice 2\n");
  crible(1000);
  printf("\n\n\n");

  printf("Exercice 3\n");
  main_exercice3();
  printf("\n\n\n");

  printf("Exercice 4\n");
  exercice4_question1();
  exercice4_question2();
  printf("\n\n\n");

  printf("Exercice 5\n");
  exercice5_expression1();
  exercice5_expression2();
  printf("\n\n\n");

  return 0;
}