/***************************************
*                                      *
*   Copyright (c) 1998 Jean-Eric Pin   *
*   All rights reserved.               *
*                                      *
*   TAB = 2 spaces                     *
*                                      *
***************************************/

/*-------------------------------------------------------------------
 * SortieLaTeX.c    Jean-Eric Pin 29/04/2007
 *-------------------------------------------------------------------
 */     

#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include "Globales.h"
#include "Main.h"
#include "Initialisation.h"
#include "DclassesIteratif.h"
#include "Inverses.h"
#include "Reduction.h"
#include "Syntactique.h"
#include "Zero.h"
#include "Sortie.h"
#include "InitLaTeX.h"
#include "SortieLaTeX.h"

extern unsigned long Periode, Seuil, NbRelations, NbRclasses, NbLclasses, NbDclasses, 
                     NbHclasses, CalculsEffectues;
extern unsigned short NbEtats, NbLettres, NbChiffresNbElements, LongueurMax, TypeCalcul, 
                      TypeSemigroupe, PossedeUnZero, PossedeUnNeutre, AvecNumero,
                      SemiReduit;
extern unsigned long NbElements, NbReelElements, NbIdempotents, nZero, DernierMot;
extern element *Generateurs, *TableDesValeurs;
extern element Identite;
extern long LongueurLaTeXMax;
extern info *Table;
extern info2 *Table2;
extern unsigned long *TableIdempotents;  /* La table des idempotents */
extern Sortie_ SortieElement;
extern SortieLaTeX_ SortieLaTeXElement;
extern char **Messages;
extern infoSommet **Graphe;  /* Le graphe syntactique */
extern ListeNumero *Inverses, *InversesFaibles;
extern long *TableauLongueurMots;

unsigned short NbLignes, NombreColonnes, CompteurColonnes, EndAlign;

/****************************************************
*
* Sortie Generale. OK
*
****************************************************/

void SortieLaTeXGenerale(FILE *fichier)
{
  fprintf(fichier, "\\noindent %s generated by the following ", TypeCalcul == Semigroupe ? "Semigroup" : "Monoid");
  switch (TypeSemigroupe)
  {
    case ParTransitions : case ParTransitionsPartielles :
      fprintf(fichier, "generators:\n");
    break;
      
    case MatricesBooleennes:
      fprintf(fichier, "Boolean matrices:\n");
    break;
      
    case MatricesMaxPlus: 
      fprintf(fichier, "$\\Max$-$+$-matrices:\n");
    break;
      
    case MatricesMinPlus: 
      fprintf(fichier, "$\\Min$-$+$-matrices:\n");
    break;
      
    case MatricesMaxPlusTropicales:
      fprintf(fichier, "tropical $\\Max$-$+$-matrices:\n");
    break;
      
    case MatricesMinPlusTropicales: 
      fprintf(fichier, "tropical $\\Min$-$+$-matrices:\n");
    break;
      
    case MatricesMaxPlusProjectives: 
      fprintf(fichier, "projective $\\Max$-$+$-matrices:\n");
    break;
      
    case MatricesEntieres:
      fprintf(fichier, "matrices over ");
      SortieLaTeXSemiAnneauZst(fichier);
    break;
      
    default:
    break;
  }
  SortieLaTeXGenerateurs(fichier);
  SortieLaTeXZero(fichier);
  fprintf(fichier, "\n\\noindent Number of elements: %1lu\n\n", NbReelElements);
  fprintf(fichier, "\\noindent Number of relations: %1lu\n\n", NbRelations);
  fprintf(fichier, "\\noindent Maximal length of the words: %1d\n\n", LongueurMax); 
  fprintf(fichier, "\\noindent Number of $\\cal D$-classes: %1lu\n\n", NbDclasses);    
  fprintf(fichier, "\\noindent Number of $\\cal R$-classes: %1lu\n\n", NbRclasses);    
  fprintf(fichier, "\\noindent Number of $\\cal L$-classes: %1lu\n\n", NbLclasses);    
  fprintf(fichier, "\\noindent Number of $\\cal H$-classes: %1lu\n\n", NbHclasses);  
  fprintf(fichier, "\n");
}


/****************************************************
*
* Sortie du semianneau. OK
*
****************************************************/

void SortieLaTeXSemiAnneauZst(FILE *fichier)
{
  fprintf(fichier, "the semiring ${\\mathbb Z}_{%ld, %ld}$ (threshold %ld, period %ld)\n", Seuil, Periode, Seuil, Periode);
  /* Le semianneau est Z_{s, t} */
}

/****************************************************
*
* Sortie des generateurs. OK
*
****************************************************/

void SortieLaTeXGenerateurs(FILE *fichier)
{
  unsigned short i, j;
  lettre a;

  fprintf(fichier, "$$\n\\setlength{\\extrarowheight}{2pt}\n");
  fprintf(fichier, "\\begin{tabular}{|r<{\\ptvi}|");
  switch (TypeSemigroupe)
  {
    case ParTransitions : case ParTransitionsPartielles :
      for (i = 0; i < NbEtats; i++)
        fprintf(fichier, "c|");
      break;
      
    case MatricesBooleennes:  case MatricesMaxPlus: case MatricesMinPlus: case MatricesMaxPlusTropicales: 
    case MatricesMinPlusTropicales: case MatricesMaxPlusProjectives: case MatricesEntieres:
      for (i = 0; i < NbEtats; i++)
      {
        for (j = 0; j < NbEtats; j++)
          fprintf(fichier, "c");
        fprintf(fichier, "|");
      }
      break;
      
    default:
      break;
  }
  fprintf(fichier, "}\n\\hline\n\\multicolumn{1}{|c|}{}\n");
  switch (TypeSemigroupe)
  {
    case ParTransitions : case ParTransitionsPartielles :
        SortieLaTeXElement(TableDesValeurs[IDENTITE], fichier);
    break;
      
    case MatricesBooleennes:  case MatricesMaxPlus: case MatricesMinPlus: case MatricesMaxPlusTropicales: 
    case MatricesMinPlusTropicales: case MatricesMaxPlusProjectives: case MatricesEntieres:
      for (i = 0; i < NbEtats; i++)
        fprintf(fichier, "&\\multicolumn{%d}{c|}{row %d}", NbEtats, i+1);
    break;
      
    default:
    break;
  }
  fprintf(fichier, "\\\\\n\\hline\n");
  for (a = 0; a < NbLettres; a++)
  {
    fprintf(fichier, "$%c$ ", a + 97);
    SortieLaTeXElement(Generateurs[a], fichier);
    fprintf(fichier, "\\\\\n");
  }
  fprintf(fichier, "\\hline\n\\end{tabular}\n$$\n");
}

/****************************************************
*
* Sortie d'un mot non vide. OK
*
****************************************************/

void SortieLaTeXMotNonVide(unsigned long n, FILE *fichier)
{
  if (n != IDENTITE)
  {
    SortieLaTeXMotNonVide(Table[n].Prefixe, fichier);
    fprintf(fichier, "%1c",Table[n].Finale + 97);
  }
}

/****************************************************
*
* Sortie semireduite d'un mot non vide. OK
*
****************************************************/

void SortieLaTeXSemiReduiteMotNonVide(unsigned long n, FILE *fichier)
{
  lettre LettreEnCours;
  short Exposant;
  
  while (n != IDENTITE)
  {
    LettreEnCours = Table[n].Initiale;
    Exposant = 1;
    while ((Table[n].Suffixe != IDENTITE) && (Table[Table[n].Suffixe].Initiale == LettreEnCours))
    {
      n = Table[n].Suffixe;
      Exposant++;
    }
    if (Exposant == 1)
      fprintf(fichier, "%1c", LettreEnCours + 97);
    else
      fprintf(fichier, "%1c^%hd", LettreEnCours + 97, Exposant);
    n = Table[n].Suffixe;
  }
}

/****************************************************
*
* Sortie du mot vide. OK
*
****************************************************/

void SortieLaTeXMotVide(FILE *fichier)
{
  fprintf(fichier, "1");
}

/****************************************************
*
* Sortie d'un mot. OK
*
****************************************************/

void SortieLaTeXMot(unsigned long n, FILE *fichier)
{
  if (SemiReduit)
  {
    (n == IDENTITE) ? SortieLaTeXMotVide(fichier) : SortieLaTeXSemiReduiteMotNonVide(n, fichier);
  }
  else
  {
    (n == IDENTITE) ? SortieLaTeXMotVide(fichier) : SortieLaTeXMotNonVide(n, fichier);
  }
}

/****************************************************
*
* Sortie d'un Emot. OK
*
****************************************************/

void SortieLaTeXEMot(element x, FILE *fichier)
{
  ;
}

/****************************************************
*
* Sortie LaTeX formatee d'un mot. OK
*
****************************************************/

void SortieLaTeXMotFormate(unsigned long n, unsigned short Longueur, FILE *fichier)
{
  if (n == IDENTITE) 
    fprintf(fichier, "%*c1", LongueurMax,' ');
  else
  {
    fprintf(fichier, "%*c", 1 + LongueurMax - Longueur,' ');
    SortieLaTeXMotNonVide(n, fichier);
  }
}

/****************************************************
*
* SortieLaTeXEnTeteElements. OK
*
****************************************************/

void SortieLaTeXEnTeteElements(FILE *fichier)
{
  unsigned short i, j;

  fprintf(fichier, "$$\n\\setlength{\\extrarowheight}{2pt}\n");
  fprintf(fichier, "\\begin{tabular}{%s|r<{\\ptvi}|", AvecNumero ? "|r" : "");
  switch (TypeSemigroupe)
  {
    case ParTransitions : case ParTransitionsPartielles :
      for (i = 0; i < NbEtats; i++)
        fprintf(fichier, "c|");
      break;
      
    case MatricesBooleennes:  case MatricesMaxPlus: case MatricesMinPlus: case MatricesMaxPlusTropicales: 
    case MatricesMinPlusTropicales: case MatricesMaxPlusProjectives: case MatricesEntieres:
      for (i = 0; i < NbEtats; i++)
      {
        for (j = 0; j < NbEtats; j++)
          fprintf(fichier, "c");
        fprintf(fichier, "|");
      }
      break;
      
    default:
      break;
  }
  fprintf(fichier, "}\n\\hline\n\\multicolumn{%s}{|c|}{}\n", AvecNumero ? "2" : "1");
  switch (TypeSemigroupe)
  {
    case ParTransitions : case ParTransitionsPartielles :
        SortieLaTeXElement(TableDesValeurs[IDENTITE], fichier);
    break;
      
    case MatricesBooleennes:  case MatricesMaxPlus: case MatricesMinPlus: case MatricesMaxPlusTropicales: 
    case MatricesMinPlusTropicales: case MatricesMaxPlusProjectives: case MatricesEntieres:
      for (i = 0; i < NbEtats; i++)
        fprintf(fichier, "&\\multicolumn{%d}{c|}{row %d}", NbEtats, i+1);
    break;
      
    default:
    break;
  }
  fprintf(fichier, "\\\\\n\\hline\n");
}

/****************************************************
*
* Sortie LaTeX de la liste des elements. OK
*
****************************************************/

void SortieLaTeXListeElements(FILE *fichier)
{
  unsigned long n = IDENTITE;
  unsigned short Longueur = 0;

  fprintf(fichier, "\\noindent Elements:\n"); 
  NbLignes = 2;
  SortieLaTeXEnTeteElements(fichier);
  if (PossedeUnNeutre)
  {
    fprintf(fichier, "%s$*\\ 1$", AvecNumero ? "1&" : "");
    SortieLaTeXElement(TableDesValeurs[IDENTITE], fichier);
      fprintf(fichier, "\\\\\n");
  }
  for (n = IDENTITE; n != DernierMot; ) 
  {
    n = Table[n].Suivant;
    Longueur = Table[n].Longueur;
    if (AvecNumero)
      fprintf(fichier, "& %ld ", n);
    fprintf(fichier, "$");
    if (Table[n].Statut & IDEMPOTENT)
      fprintf(fichier, "*\\ ");
    SortieLaTeXMot(n, fichier);
    fprintf(fichier, "$");
    SortieLaTeXElement(TableDesValeurs[n], fichier);
    fprintf(fichier, "\\\\\n");
    NbLignes++;
    if ((NbLignes >= NB_MAX_LIGNES) && (n != DernierMot))
    {
       fprintf(fichier, "\\hline\n\\end{tabular}\n$$\n");
      SortieLaTeXEnTeteElements(fichier);
      NbLignes = 0;
    }
  }
  fprintf(fichier, "\\hline\n\\end{tabular}\n$$\n");
}

/****************************************************
*
* Sortie LaTeX de la liste des idempotents. OK
*
****************************************************/

void SortieLaTeXIdempotents(FILE *fichier) 
{ 
  unsigned long i; 
  long LongueurLigne = LATEX_ES;  
   
  fprintf(fichier, "\\noindent Idempotents:\n"); 
  fprintf(fichier, "\\begin{align*}\nE(S) = \\{&");
  for (i = 0; i < NbIdempotents; i++)
  {
    LongueurLigne = LongueurLigne + LATEX_VIRGULE + TableauLongueurMots[TableIdempotents[i]];
    if (LongueurLigne >= LIGNE_MAX)
    {
      fprintf(fichier, " \\\\\n &");
      LongueurLigne = LATEX_ES + TableauLongueurMots[TableIdempotents[i]]; 
    }
    SortieLaTeXMot(TableIdempotents[i], fichier);
    fprintf(fichier, ", ");
  } 
  fseek(fichier, -2, SEEK_CUR);
  fprintf(fichier, "\\}\n\\end{align*}\n");
}

/****************************************************
*
* Sortie de K(S). OK
*
****************************************************/

void SortieLaTeXKS(FILE *fichier)
{
  unsigned long i;
  long LongueurLigne = LATEX_KS;  /* Il faut ajouter le mot vide au depart car 
                                                      il s'affiche par un mot de longueur 1 */ 
  fprintf(fichier, "\\begin{align*}\nK(S) = \\{&");
  for (i = IDENTITE; i <= NbElements; i++)
    if (Table[i].Statut & EST_DANS_KS)
    {
      LongueurLigne = LongueurLigne + LATEX_VIRGULE + TableauLongueurMots[i];
/*       printf("LongueurLigne = %d\n", LongueurLigne); */
      if (LongueurLigne >= LIGNE_MAX)
      {
        fprintf(fichier, " \\\\\n &");
        LongueurLigne = LATEX_KS + TableauLongueurMots[i]; 
      }
      SortieLaTeXMot(i, fichier);
      fprintf(fichier, ", ");
    }  
  fseek(fichier, -2, SEEK_CUR);
  fprintf(fichier, "\\}\n\\end{align*}\n");
}

/****************************************************
*
* Sortie de l'ideal minimal. OK
*
****************************************************/

void SortieLaTeXIdealMinimal(FILE *fichier)
{
  unsigned long i;
  long LongueurLigne = LATEX_IDEAL_MINIMAL;
  
  CalculDclasses();
  fprintf(fichier, "\\noindent Minimal ideal:\n"); 
  fprintf(fichier, "\\begin{align*}\nI = \\{&");
  for (i = IDENTITE; i <= NbElements; i++)
    if (Table2[i].Statut & EST_D_MINIMAL)
    {
      LongueurLigne = LongueurLigne + LATEX_VIRGULE + TableauLongueurMots[i];
      if (LongueurLigne >= LIGNE_MAX)
      {
        fprintf(fichier, " \\\\\n &");
        LongueurLigne = LATEX_IDEAL_MINIMAL + TableauLongueurMots[i]; 
      }
      SortieLaTeXMot(i, fichier);
      fprintf(fichier, ", ");
    }  
  fseek(fichier, -2, SEEK_CUR);
  fprintf(fichier, "\\}\n\\end{align*}\n");
}

/****************************************************
*
* SortieLaTeXEndalign. OK
*
****************************************************/

void SortieLaTeXEndalign(unsigned long n, FILE *fichier)
{
  if (CompteurColonnes < NombreColonnes)
  {
    fprintf(fichier, " & ");
  }
  else  /* Derniere colonne */
  {
    CompteurColonnes = 0;
    NbLignes++;
    if (NbLignes >= NB_MAX_LIGNES_ALIGN)
    {
      fprintf(fichier, "\\end{align*}\n\n\\begin{align*}\n");
      EndAlign = 1;
      NbLignes = 0;
    }
    else
      fprintf(fichier, " \\\\\n");
  }
}

/****************************************************
*
* Sortie des relations. OK
*
****************************************************/

void SortieLaTeXRelations(FILE *fichier)
{
  lettre a;
  unsigned long n, u;

  NbLignes = 2;
  NombreColonnes = (69 / (2 * LongueurMax + 5));
  EndAlign = 0;
  CompteurColonnes = 0;
  fprintf(fichier, "\\noindent Relations:\n"); 
  fprintf(fichier, "\\begin{align*}\n");
  for (n = IDENTITE; n != 0; n = Table[n].Suivant)
  {
    if (n == nZero)
    {
      EndAlign = 0;
      SortieLaTeXMot(n, fichier);
      fprintf(fichier, " &= 0");
      CompteurColonnes++;
      SortieLaTeXEndalign(n, fichier);
    } 
    else 
      for (a = 0; a < NbLettres; a++)
      {
        u = Table[n].Produits[a].D;
        if ((Table[Table[n].Suffixe].Produits[a].D & EST_REDUIT) && (!(u & EST_REDUIT)))
        {
           EndAlign = 0;
          SortieLaTeXMot(n, fichier);
          fprintf(fichier, "%c &= ", a + 97);
          if (u == nZero)
            fprintf(fichier, "0");
          else
            SortieLaTeXMot(u, fichier);
           CompteurColonnes++;
          SortieLaTeXEndalign(n, fichier);
        }
      }
  }
  if (!EndAlign)
  {
    if (CompteurColonnes != 0)
      fseek(fichier, -2, SEEK_CUR);
      fprintf(fichier, "\\end{align*}\n");
  }
  else
  {
    fseek(fichier, -16, SEEK_CUR);
  }
}

/****************************************************
*
* Sortie des puissances omega. OK
*
****************************************************/

void SortieLaTeXOmega(FILE *fichier)
{
  unsigned long n;
  
  for (n = IDENTITE; n <= NbElements; n++)
  {
    fprintf(fichier, "(");
    SortieLaTeXMot(n, fichier);
    fprintf(fichier, ")^\\omega = ");
    SortieLaTeXMot(Table2[n].xOmega, fichier);
    fprintf(fichier, "\n");
  }  
}

/****************************************************
*
* Sortie du semigroupe local. OK
*
****************************************************/

void SortieLaTeXMonoideLocal(unsigned long u, FILE *fichier)
{
  unsigned long n;
  long LongueurLigne = LATEX_LOCAL;
  
  fprintf(fichier, "\\noindent Local submonoid generated by $u = ");
  SortieLaTeXMot(u, fichier);
  fprintf(fichier, "$\n\\begin{align*}\neSe = \\{&");
  for (n = IDENTITE; n <= NbElements; n++)
  {
    if ((~(Table[n].Statut) & (EST_DANS_IDEAL_DROIT | EST_DANS_IDEAL_GAUCHE)) == 0)  /* Les 2 bits a 1 */
    {
      LongueurLigne = LongueurLigne + LATEX_VIRGULE + TableauLongueurMots[n];
      if (LongueurLigne >= LIGNE_MAX)
      {
        fprintf(fichier, " \\\\\n &");
        LongueurLigne = LATEX_LOCAL + TableauLongueurMots[n]; 
      }
      SortieLaTeXMot(n, fichier);
      fprintf(fichier, ", ");
    }
  }  
  fseek(fichier, -2, SEEK_CUR);
  fprintf(fichier, "\\}\n\\end{align*}\n");
}

/****************************************************
*
* Sortie Ideal droit. OK
*
****************************************************/

void SortieLaTeXIdealDroit(unsigned long u, FILE *fichier)
{
  unsigned long n;
  long LongueurLigne = LATEX_IDEAL;
  
  fprintf(fichier, "\\noindent Right ideal generated by $u = ");
  SortieLaTeXMot(u, fichier);
  fprintf(fichier, "$\n\\begin{align*}\nuS^1 = \\{&");
  for (n = IDENTITE; n <= NbElements; n++)
  {
    if ((~Table[n].Statut & EST_DANS_IDEAL_DROIT) == 0)    /* bit a 1 */
    {
      LongueurLigne = LongueurLigne + LATEX_VIRGULE + TableauLongueurMots[n];
      if (LongueurLigne >= LIGNE_MAX)
      {
        fprintf(fichier, " \\\\\n &");
        LongueurLigne = LATEX_IDEAL + TableauLongueurMots[n]; 
      }
      SortieLaTeXMot(n, fichier);
      fprintf(fichier, ", ");
    }
  }  
  fseek(fichier, -2, SEEK_CUR);
  fprintf(fichier, "\\}\n\\end{align*}\n");
}

/****************************************************
*
* Sortie Ideal gauche. OK
*
****************************************************/

void SortieLaTeXIdealGauche(unsigned long u, FILE *fichier)
{
  unsigned long n;
  long LongueurLigne = LATEX_IDEAL;
  
  fprintf(fichier, "\\noindent Left ideal generated by $u = "); 
  SortieLaTeXMot(u, fichier);
  fprintf(fichier, "$\n\\begin{align*}\nS^1u = \\{&");
  for (n = IDENTITE; n <= NbElements; n++)
  {
    if ((~Table[n].Statut & EST_DANS_IDEAL_GAUCHE) == 0)    /* bit a 1 */
    {
      LongueurLigne = LongueurLigne + LATEX_VIRGULE + TableauLongueurMots[n];
      if (LongueurLigne >= LIGNE_MAX)
      {
        fprintf(fichier, " \\\\\n &");
        LongueurLigne = LATEX_IDEAL + TableauLongueurMots[n]; 
      }
      SortieLaTeXMot(n, fichier);
      fprintf(fichier, ", ");
    }
  }  
  fseek(fichier, -2, SEEK_CUR);
  fprintf(fichier, "\\}\n\\end{align*}\n");
}

/****************************************************
*
* Sortie du zero. OK
*
****************************************************/

void SortieLaTeXZero(FILE *fichier)
{
  fprintf(fichier, "\n");
  if (PossedeUnZero)
  {
     fprintf(fichier, "\\noindent This %s has a zero: $", TypeCalcul == Semigroupe ? "semigroup" : "monoid");
    SortieLaTeXMot(nZero, fichier);
    fprintf(fichier, " = 0$\n");
  }
  else
    fprintf(fichier, "\\noindent This %s has no zero.\n", TypeCalcul == Semigroupe ? "semigroup" : "monoid");  /* Pas de zero */
}

/***************************************************************************
*
* SortieSyntactique. Sortie du preordre syntactique.
*
***************************************************************************/

void SortieLaTeXSyntactique(FILE *fichier)
{
  char compteur, c;
  unsigned long u, v;
  
  NbLignes = 2;
  NombreColonnes = 69 / (2 * LongueurMax + 4);
  CompteurColonnes = 0;
  CalculSqueletteSyntactique();
  fprintf(fichier, "\\noindent Syntactic preorder:\n");    /* Preordre syntactique de P:  */
  fprintf(fichier, "\\begin{align*}\n");
  for (u = IDENTITE + !PossedeUnNeutre; u <= NbElements; u++)
  {
    for (v = u + 1; v <= NbElements; v++)
    {
      c = Graphe[u][v].Label;
      compteur = 0;
      if ((c & TRANSITIF) == 0)
      {
        c &= CHAR_TROIS;
        switch (c)
        {
          case CHAR_UN:
            SortieLaTeXMot(v, fichier);
            fprintf(fichier, " &< ");
            CompteurColonnes++;
            compteur++;
            SortieLaTeXMot(u, fichier);
          break;
            
          case CHAR_DEUX:
            SortieLaTeXMot(u, fichier);
            fprintf(fichier, " &< ");
            CompteurColonnes++;
            compteur++;
            SortieLaTeXMot(v, fichier);
            break;

          case CHAR_TROIS:
            SortieLaTeXMot(u, fichier);
            fprintf(fichier, " &= ");
            compteur++;
            CompteurColonnes++;
            SortieLaTeXMot(v, fichier);
            break;
        }
        if (compteur != 0)
        {    
          if (CompteurColonnes < NombreColonnes)
          {
            fprintf(fichier, " & ");
          }
          else /* Derniere colonne */
          {
            CompteurColonnes = 0;
            NbLignes++;
            if ((NbLignes >= NB_MAX_LIGNES_ALIGN) && (u != DernierMot))
            {
              fprintf(fichier, "\\end{align*}\n\n\\begin{align*}\n");
              NbLignes = 0;
            }
            else if (u != DernierMot)
              fprintf(fichier, " \\\\\n");
          }
        }
      }
    }
  }    
  if (CompteurColonnes < NombreColonnes)
    fprintf(fichier, "\n");
  fprintf(fichier, "\\end{align*}\n");
}

/***************************************************************************
*
* SortieLaTeXListeInverses. 
*
***************************************************************************/

void SortieLaTeXListeInverses(unsigned long s, ListeNumero Liste, FILE *fichier)
{
  unsigned long compteur = 0;
  long LongueurLigne;
  
  SortieLaTeXMot(s, fichier);
  LongueurLigne = LongueurLaTeXMax + LATEX_TO;
  fprintf(fichier, " \\to{} \\{&");
  while (Liste != NULL)
  {
    compteur++;
    LongueurLigne = LongueurLigne + LATEX_VIRGULE + TableauLongueurMots[Liste->t];
    if (LongueurLigne >= LIGNE_MAX)
    {
      NbLignes++;
      fprintf(fichier, " \\\\\n &");
      LongueurLigne = LongueurLaTeXMax + LATEX_TO + TableauLongueurMots[Liste->t]; 
    }
    SortieLaTeXMot(Liste->t, fichier);
    fprintf(fichier, ", ");
    Liste = Liste->suivant; 
  }
  if (compteur != 0)
    fseek(fichier, -2, SEEK_CUR);
}

/***************************************************************************
*
* SortieLaTeXTable. 
*
***************************************************************************/

void SortieLaTeXTable(ListeNumero *Tableau, FILE *fichier)
{
  unsigned long s;
  
  NbLignes = 1; 
  fprintf(fichier, "\\begin{align*}\n");
  for (s = IDENTITE + !PossedeUnNeutre; s <= NbElements; s++) 
  {    
    NbLignes++;
    SortieLaTeXListeInverses(s, Tableau[s], fichier);
    if ((NbLignes >= NB_MAX_LIGNES_ALIGN) && (s != NbElements))
    {
      fprintf(fichier, "\\}\n\\end{align*}\n\n\\begin{align*}\n");
      NbLignes = 0;
    }
    else 
      fprintf(fichier, "\\} \\\\\n");
  }
  fprintf(fichier, "\\end{align*}\n\n");
}

/***************************************************************************
*
* SortieLaTeXInverses. Affiche la liste des inverses faibles de u.
*
***************************************************************************/

void SortieLaTeXInverses(FILE *fichier)
{
  fprintf(fichier, "\\newpage\n\\noindent Inverses:\n");    /* Inverses */
  SortieLaTeXTable(Inverses, fichier);
  fprintf(fichier, "\\newpage\n\\noindent Weak inverses:\n");    /* Inverses faibles */
  SortieLaTeXTable(InversesFaibles, fichier);
}

/***************************************************************************
*
* SortieLaTeXRightCayleyGraph
*
***************************************************************************/

void SortieLaTeXRightCayleyGraph(FILE *fichier)
{
  unsigned long n, na;
  lettre a;
  short T = (short)(1 + ceil(sqrt(NbElements)));
  
  fprintf(fichier, "\\begin{center}\n\\unitlength=4pt\n  \\begin{picture}(80,70)(0,0)\\nullfont\n");
  fprintf(fichier, "  \\gasset{Nadjust=w,Nh=5,Nmr=2.5,curvedepth=0}\n");
  for (n = IDENTITE; n <= NbElements; n++)
  {
    fprintf(fichier, "    \\node(S%ld)(%ld,%ld){$", n, 12 * (n / T), 10 * (n % T));
    SortieLaTeXMot(n, fichier);
    fprintf(fichier, "$}\n");
  }
  for (n = IDENTITE; n <= NbElements; n++)
    for (a = 0; a < NbLettres; a++)
    {
      na = Table[n].Produits[a].D & ~EST_REDUIT;
      if (na != n)
        fprintf(fichier, "    \\drawedge(S%ld,S%ld){$%c$}\n", n, na, a + 97);
      else
        fprintf(fichier, "    \\drawloop(S%ld){$%c$}\n", n, a + 97);
    }
  fprintf(fichier, "\\end{picture}\n\\end{center}\n");
}

/***************************************************************************
*
* SortieLaTeXLeftCayleyGraph
*
***************************************************************************/

void SortieLaTeXLeftCayleyGraph(FILE *fichier)
{
  unsigned long n, na;
  lettre a;
  short T = (short)(1 + ceil(sqrt(NbElements)));
  
  fprintf(fichier, "\\begin{center}\n\\unitlength=4pt\n  \\begin{picture}(80,70)(0,0)\\nullfont\n");
  fprintf(fichier, "  \\gasset{Nadjust=w,Nh=5,Nmr=2.5,curvedepth=0}\n");
  for (n = IDENTITE; n <= NbElements; n++)
  {
    fprintf(fichier, "    \\node(S%ld)(%ld,%ld){$", n, 12 * (n / T), 10 * (n % T));
    SortieLaTeXMot(n, fichier);
    fprintf(fichier, "$}\n");
  }
  for (n = IDENTITE; n <= NbElements; n++)
    for (a = 0; a < NbLettres; a++)
    {
      na = Table[n].Produits[a].G & ~EST_REDUIT;
      if (na != n)
        fprintf(fichier, "    \\drawedge(S%ld,S%ld){$%c$}\n", n, na, a + 97);
      else
        fprintf(fichier, "    \\drawloop(S%ld){$%c$}\n", n, a + 97);
    }
  fprintf(fichier, "\\end{picture}\n\\end{center}\n");
}