#include <stdio.h>
#include <assert.h>
#include "Q.h"


#define min(a,b) ((a)<(b)?(a):(b))


Q creerQ (int numint den)
     /* ENTREE : le numerateur num et le denominateur den!=0
        SORTIE : le nombre rationnel num/den */

{
  Q resultat;
  assert(den!=0);
  resultat.N=num;
  resultat.D=den;
  return(resultat);
}

void afficherQ (Q r)
     /* ENTREE : le nombre rationnel r
        Affichage de r sur le standard output */

{
  printf("%d/%d",r.N,r.D);
  /* Le buffer n'est pas flushe pour permettre l'ecriture de plusieur */
  /* nombres rationnels sur une meme ligne, si necessaire. */
}

double approximerQ (Q r)
     /* ENTREE : le nombre rationnel r
        SORTIE : une approximation reele de r */

{
  return((double)r.N/r.D); 
  /* Attention a ne pas oublie le type casting  */
  /* pour ne pas faire une division entiere */
}

int egalQ (Q r1Q r2)
     /* ENTREE : deux nombres rationnels r1 et r2
        SORTIE : 1 si r1=r2 et 0 sinon */

{
  return(r1.N*r2.D==r1.D*r2.N);
  /* Attention a bien faire les produits croises et ne pas simplement */
  /* comparer numerateurs et denomniateurs (2/3=4/6) */
}

Q produitQ (Q r1Q r2)
     /* ENTREE : deux nombres rationnels r1 et r2
        SORTIE : r1*r2 */

{
  Q resultat;
  resultat.N=r1.N*r2.N;
  resultat.D=r1.D*r2.D;
  return(resultat);
}

Q divisionQ (Q r1Q r2)
     /* ENTREE : deux nombres rationnels r1 et r2!=0
        SORTIE : r1/r2 */

{
  Q resultat;
  assert(r2.N!=0);
  resultat.N=r1.N*r2.D;
  resultat.D=r1.D*r2.N;
  return(resultat);
}

Q sommeQ (Q r1Q r2)
     /* ENTREE : deux nombres rationnels r1 et r2
        SORTIE : r1+r2 */

{
  Q resultat;
  resultat.D=r1.D*r2.D/* on met au meme denominateur */
  resultat.N=r2.N*r1.D+r1.N*r2.D;
  return(resultat);
}

Q irreductibleQ (Q r)
     /* ENTREE : un nombre rationnel r
        SORTIE : r sous forme irreductible */

{
  int n;

  /* On commence par regarder si 2 est un facteur commun 
     au numerateur et au denominateur */

  n=2

  while (n<=min(r.N,r.D)) {
    if ((r.N%n==0)&&(r.D%n==0))
      {
        /* si c'est le cas on simplifie */
        r.N/=n;
        r.D/=n;
      }
    /* sinon on passe a l'entier suivant  */
    /* (le nombre premier suivant serait suffisant) */
    else n++;
  }

  return r;
}