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

/*-------------------------------------------------------------------
 * Sortie.c    Jean-Eric Pin 07/12/96
 *-------------------------------------------------------------------
 */     

#include <stdlib.h>
#include <stdio.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"

extern unsigned long Periode, Seuil, CalculsEffectues;
extern unsigned short NbEtats, NbLettres, NbChiffresNbElements, LongueurMax, 
                      TypeCalcul, TypeSemigroupe, PossedeUnZero, PossedeUnNeutre;
extern unsigned long NbElements, NbIdempotents, nZero, DernierMot;
extern element *Generateurs, *TableDesValeurs;
extern info *Table;
extern info2 *Table2;
extern unsigned long *TableIdempotents;  /* La table des idempotents */
extern Sortie_ SortieElement;
extern char **Messages;
extern infoSommet **Graphe;  /* Le graphe syntactique */
extern ListeNumero *Inverses, *InversesFaibles;

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

void SortieSemiAnneauZst(void)
{
  printf("%s%ld, %ld}\n", Messages[M_Semiring], Seuil, Periode);
  /* Le semianneau est Z_{s, t} */
}

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

void SortieGenerateurs(void)
{
  lettre a;

  printf("%s\n", Messages[M_Generators]);  /* Generateurs : \n */
  for (a = 0; a < NbLettres; a++)
  {
    printf("%c |", a + 97);
    SortieElement(Generateurs[a]);
  }
  printf("\n");
}

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

void SortieMotNonVide(unsigned long n)
{
  if (n != IDENTITE)
  {
    SortieMotNonVide(Table[n].Prefixe);
    printf("%1c",Table[n].Finale + 97);
  }
}

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

void SortieMotVide(void)
{
  printf("1");
}

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

void SortieMot(unsigned long n)
{
  (n == IDENTITE) ? SortieMotVide() : SortieMotNonVide(n);
}

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

void SortieMotFormate(unsigned long n, unsigned short Longueur)
{
  if (n == IDENTITE) 
    printf("%*c1", LongueurMax,' ');
  else
  {
    printf("%*c", 1 + LongueurMax - Longueur,' ');
    SortieMotNonVide(n);
  }
}

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

void SortieListeElements(void)
{
  unsigned long n = IDENTITE;
  unsigned short Longueur = 0;

  printf("  %*c | ", LongueurMax + NbChiffresNbElements + 3, ' ');
  SortieElement(TableDesValeurs[IDENTITE]);
  switch (TypeSemigroupe)
  {
    case ParTransitions : case ParTransitionsPartielles :
      printf("%.*s\n", LongueurMax + NbChiffresNbElements + 8 + 3 * NbEtats, 
"----------------------------------------------------------------------------------------------------------------------------------");
      break;
      
    case MatricesBooleennes:
      printf("%.*s\n", LongueurMax + NbChiffresNbElements + 8 + (3 * NbEtats + 1) * NbEtats, 
"-----------------------------------------------------------------------------------------------------------------------------");
      break;
      
    case MatricesMaxPlus: case MatricesMinPlus: case MatricesMaxPlusTropicales : 
    case MatricesMinPlusTropicales : case MatricesMaxPlusProjectives :case MatricesEntieres:
      printf("%.*s\n", LongueurMax + NbChiffresNbElements + 8 + (4 * NbEtats + 1) * NbEtats, 
"-----------------------------------------------------------------------------------------------------------------------------");
      break;
      
    default:
      break;
  }
  if (PossedeUnNeutre)
  {
    if (CalculsEffectues & CALCUL_D_CLASSES)
      printf("*%c%*c1 %*c1 | ", (Table2[IDENTITE].Statut & EST_D_MINIMAL) ? 
              'M' : ' ', NbChiffresNbElements, ' ', LongueurMax, ' ');
    else
      printf("*%*c1 %*c1 | ", NbChiffresNbElements, ' ', LongueurMax, ' ');
    SortieElement(TableDesValeurs[IDENTITE]);
    for (n = IDENTITE; n != DernierMot; )
    {
      n = Table[n].Suivant;
      Longueur = Table[n].Longueur;
      if (Table[n].Statut & IDEMPOTENT)
        printf("*");
      else if  (Table[n].Statut & DANS_UN_GROUPE)
        printf("G");
      else if  (Table[n].Statut & REGULIER)
        printf("R");
      else
        printf(" ");
      if (CalculsEffectues & CALCUL_D_CLASSES)
        printf("%c", (Table2[n].Statut & EST_D_MINIMAL) ? 'M' : ' ');
      printf(" %*ld ", NbChiffresNbElements, n);
      SortieMotFormate(n, Longueur);
      printf(" | ");
      SortieElement(TableDesValeurs[n]);
    }
  }
  else
    for (n = IDENTITE; n != DernierMot; )
    {
      n = Table[n].Suivant;
      Longueur = Table[n].Longueur;
      if (Table[n].Statut & IDEMPOTENT)
        printf("*");
      else if  (Table[n].Statut & DANS_UN_GROUPE)
        printf("G");
      else if  (Table[n].Statut & REGULIER)
        printf("R");
      else
        printf(" ");
      if (CalculsEffectues & CALCUL_D_CLASSES)
        printf("%c", (Table2[n].Statut & EST_D_MINIMAL) ? 'M' : ' ');
      printf(" %*ld ", NbChiffresNbElements, n - 1);
      SortieMotFormate(n, Longueur);
      printf(" | ");
      SortieElement(TableDesValeurs[n]);
    }
  printf("\n");
}

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

void SortieListeIdempotents(void)
{
  unsigned long i;
  
  printf("E(S) = {");
  for (i = 0; i < NbIdempotents; i++)
  {
    SortieMot(TableIdempotents[i]);
    printf(", ");
  }  
  printf("\b\b}\n");
}

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

void SortieKS(void)
{
  unsigned long u;
  
  printf("K(S) = {");
  for (u = IDENTITE; u <= NbElements; u++)
    if (Table[u].Statut & EST_DANS_KS)
    {
      SortieMot(u);
      printf(", ");
    }  
  printf("\b\b}\n");
}

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

void SortieIdealMinimal(void)
{
  unsigned long u;
  
  CalculDclasses();
  printf("I = {");
  for (u = IDENTITE; u <= NbElements; u++)
    if (Table2[u].Statut & EST_D_MINIMAL)
    {
      SortieMot(u);
      printf(", ");
    }  
  printf("\b\b}\n");
}

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

void SortieRelations(void)
{
  lettre a;
  unsigned long n, u;

  if (!(CalculsEffectues & CALCUL_ZERO))
    TesteZero();
  printf("%s\n", Messages[M_Relations]);  /* \nRelations : \n */
  for (n = IDENTITE; n != 0; n = Table[n].Suivant)
  {
    if (n == nZero)
    {
       SortieMot(n);
      printf(" = 0\n");
    }
    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)))
        {
           SortieMot(n);
          printf("%c = ", a + 97);
          if (u == nZero)
            printf("0");
          else
            SortieMot(u);
          printf("\n");
        }
      }
  }
  printf("\n");
}

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

void SortieOmega(void)
{
  unsigned long n;
  
  for (n = IDENTITE; n <= NbElements; n++)
  {
    printf("(");
    SortieMot(n);
    printf(")^ = ");
    SortieMot(Table2[n].xOmega);
    printf("\n");
  }  
}

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

void SortieMonoideLocal(unsigned long e)
{
  unsigned long n;
  
  printf("Local submonoid generated by e = \n");
  SortieMot(e);
  printf("eSe = {");
  for (n = IDENTITE; n <= NbElements; n++)
  {
    if ((~(Table[n].Statut) & (EST_DANS_IDEAL_DROIT | EST_DANS_IDEAL_GAUCHE)) == 0)  /* Les 2 bits a 1 */
    {
      SortieMot(n);
      printf(", ");
    }
  }  
  printf("\b\b}\n");
}

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

void SortieIdealDroit(unsigned long u)
{
  unsigned long n;
  
  printf("Right ideal generated by u = \n");
  SortieMot(u);
  printf("uS^1 = {");
  for (n = IDENTITE; n <= NbElements; n++)
  {
    if ((~Table[n].Statut & EST_DANS_IDEAL_DROIT) == 0)    /* bit a 1 */
    {
      SortieMot(n);
      printf(", ");
    }
  }  
  printf("\b\b}\n");
}

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

void SortieIdealGauche(unsigned long u)
{
  unsigned long n;
  
  printf("Left ideal generated by u = \n");
  SortieMot(u);
  printf("S^1u = {");
  for (n = IDENTITE; n <= NbElements; n++)
  {
    if ((~Table[n].Statut & EST_DANS_IDEAL_GAUCHE) == 0)    /* bit a 1 */
    {
      SortieMot(n);
      printf(", ");
    }
  }  
  printf("\b\b}\n");
}

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

void SortieZero(void)
{
  printf("\n");
  if (PossedeUnZero)
  {
    SortieMot(nZero);
    printf(" = 0\n");
  }
  else
    printf("%s\n", Messages[M_No_zero]);  /* Pas de zero */
}

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

void SortieSyntactique(void)
{
  char compteur, c;
  unsigned long u, v;
  
  CalculSyntactique();
   CalculSqueletteSyntactique(); 
  printf("%s\n", Messages[M_SyntacticOrder]);    /* Preordre syntactique de P:  */
  for (u = IDENTITE + !PossedeUnNeutre; u <= NbElements; u++)
  {
    compteur = 0;
    for (v = u + 1; v <= NbElements; v++)
    {
      c = Graphe[u][v].Label;
      if ((c & TRANSITIF) == 0)
      {
        c &= CHAR_TROIS;
        switch (c)
        {
          case CHAR_UN:
            SortieMot(v);
            printf(" < ");
            compteur++;
            SortieMot(u);
            printf(", ");
            break;
            
          case CHAR_DEUX:
            SortieMot(u);
            printf(" < ");
            compteur++;
            SortieMot(v);
            printf(", ");
            break;

          case CHAR_TROIS:
            SortieMot(u);
            printf(" = ");
            compteur++;
            SortieMot(v);
            printf(", ");
            break;
        }
      }
    }
    if (compteur != 0)
      printf("\n");
  }    
}

/***************************************************************************

*
* SortieTableInverses. 
*
***************************************************************************/


void SortieTable(ListeNumero *Tableau, short Message)
{
  unsigned long s;
  
  printf("%s\n", Messages[Message]);    /* Inverses faibles */
  for (s = IDENTITE + !PossedeUnNeutre; s <= NbElements; s++)
    SortieListe(s, Tableau[s]);
}

/***************************************************************************

*
* SortieInverses. 
*
***************************************************************************/


void SortieInverses(void)
{
  SortieTable(Inverses, M_Computation_Inverses);
  SortieTable(InversesFaibles, M_Computation_WeakInverses);
}


/***************************************************************************

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


void SortieListe(unsigned long s, ListeNumero Liste)
{
  unsigned long compteur = 0;
  
  SortieMot(s);
  printf(" --> {");
  while (Liste != NULL)
  {
    compteur++;
    SortieMot(Liste->t);
    printf(", ");
    Liste = Liste->suivant;
  }
  if (compteur != 0)
    printf("\b\b");
  printf("}\n");
}