/*************************************************************************************************************************************/
/*                                                                                                                                   */
/*        T R A N S F O R M A T I O N   D E   B U R R O W S - W H E E L E R   ' BWT '   E T   I N V E R S E  :                       */
/*                                                                                                                                   */
/*                                                                                                                                   */
/*        Nota :                                                                                                                     */
/*                                                                                                                                   */
/*                    Ce module est inspire de 'v $xtc/BurrowsWheeler.11$I'                                                          */
/*                  qui a servi a sa mise au point...                                                                                */
/*                                                                                                                                   */
/*                                                                                                                                   */
/*        Author of '$xrC/CompressionDeCompression_BurrowsWheeler.01$vv$I' :                                                         */
/*                                                                                                                                   */
/*                    Jean-Francois Colonna (LACTAMME, 20151227143647).                                                              */
/*                                                                                                                                   */
/*************************************************************************************************************************************/

/*************************************************************************************************************************************/
/*                                                                                                                                   */
/*        D E F I N I T I O N   G E N E R A L E S  :                                                                                 */
/*                                                                                                                                   */
/*************************************************************************************************************************************/
Logical   BWT_Utiliser=VRAI;

Logical   BWT_EditerLaMatrice=FAUX;
Logical   BWT_EditerLesChaines=FAUX;
                                        /* Indicateurs de controle des editions...                                                   */

Argument  BWT_TailleDesPaquets=8192;
                                        /* On notera que 512 est egal a la moitie de '$dimXSdu'...                                   */
                                        /*                                                                                           */
                                        /* Le 20160129123333, avec le passage a la version '02' cette taille est passee de 512       */
                                        /* a 8192 soit huit fois '$dimXSdu'...                                                       */

#define   BWT_INDEXN                                                                                                                    \
                    NombreVersIndex(BWT_LongueurDeToutesLesChaines)
Entier    BWT_LongueurDeToutesLesChaines;
                                        /* On notera qu'a priori, aucune des chaines utilisees n'a de caractere de fin. Cela         */
                                        /* vient du fait que ces chaines peuvent contenir 256 codes differents et qu'alors le        */
                                        /* code '0x00' habituel ne peut etre utilise. La fin d'une chaine est donc reperee via       */
                                        /* son dernier caractere d'index 'INDEXN'...                                                 */

Entier    BWT_Directe_LongueurAvant;
Entier    BWT_Directe_LongueurApres;
Entier    BWT_Inverse_LongueurAvant;
Entier    BWT_Inverse_LongueurApres;
                                        /* Afin de faciliter des verifications de coherence...                                       */

CHAR      *BWT_ChaineA;
#define   BWT_TYPE_IndexDeLaChaineAPermuterDansLaMatrice                                                                                \
                    Entier
#define   BWT_SIZE_IndexDeLaChaineAPermuterDansLaMatrice                                                                                \
                    COND((BWT_Utiliser == VRAI)                                                                                         \
                        ,(SIZEOF(BWT_NombreDePaquets)+(BWT_NombreDePaquets*SIZEOF(BWT_TYPE_IndexDeLaChaineAPermuterDansLaMatrice)))     \
                        ,0                                                                                                              \
                         )
BWT_TYPE_IndexDeLaChaineAPermuterDansLaMatrice    BWT_IndexDeLaChaineAPermuterDansLaMatrice;
Entier                                            BWT_NombreDePaquets;
BWT_TYPE_IndexDeLaChaineAPermuterDansLaMatrice    *BWT_ListeIndexDeLaChaineA;
                                        /* Definition de la chaine Argument a permuter...                                            */
CHAR      *BWT_ChaineP;
                                        /* Definition de la version permutee de 'ChaineAPermuter'...                                 */
CHAR      *BWT_ChainePT;
int       *BWT_ChainePT_NumeroDOccurence;
                                        /* Definition de la version permutee et triee de 'ChaineAPermuter'...                        */
CHAR      *BWT_ChaineR;
                                        /* Definition de la chaine "depermutee" qui doit donc etre identique a 'ChaineAPermuter'...  */

#define   MATRICEd(IndexLigne,IndexColonne)                                                                                             \
                    mINDX(BWT_Matrice,((((LEntier)IndexLigne)*((LEntier)BWT_LongueurDeToutesLesChaines))+((LEntier)IndexColonne)))
#define   MATRICE(IndexLigne,IndexColonne)                                                                                              \
                    *MATRICEd(IndexLigne,IndexColonne)
CHAR      *BWT_Matrice;
                                        /* Definition de la matrice contenant 'ChaineAPermuter' et toutes ses permutations           */
                                        /* circulaires possibles.                                                                    */

#define   PERMUTATION_DES_LIGNES_DE_LA_MATRICE(IndexLigne)                                                                              \
                    *mINDX(BWT_PermutationDesLignesDeLaMatrice,IndexLigne)
Entier    *BWT_PermutationDesLignesDeLaMatrice;
                                        /* Definition du tri par ordre croissant des differentes lignes de 'Matrice' via cette       */
                                        /* liste de permutation...                                                                   */

/*************************************************************************************************************************************/
/*                                                                                                                                   */
/*        T R I S   E N   ' N . L O G ( N ) '   D E   C H A I N E S   Q U E L C O N Q U E S  :                                       */
/*                                                                                                                                   */
/*************************************************************************************************************************************/
enum      RelationsDOrdre
          {
           INFERIEUR=-1
          ,EGAL
          ,SUPERIEUR
          };
                                        /* Liste des trois relations d'ordre possibles.                                              */

Entier    F_BWT_ComparaisonDeDeuxChaines(Entier IndexLigne_1
                                        ,Entier IndexLigne_2
                                        ,Entier IndexColonneMinimal
                                        ,Entier IndexColonneMaximal
                                         )
          {
          Entier    IndexColonne;
          Entier    PoursuivreLaComparaison;
          Entier    ResultatDeLaComparaisonDeDeuxChaines;

          mEGAL(IndexColonne,IndexColonneMinimal);
          mEGAL(PoursuivreLaComparaison,VRAI);

          mEGAL(ResultatDeLaComparaisonDeDeuxChaines,INFERIEUR);

          Tant(mIFEQ(PoursuivreLaComparaison,VRAI))
                    {
                    CHAR      caractere_1;
                    CHAR      caractere_2;

                    mEGAL(caractere_1,MATRICE(PERMUTATION_DES_LIGNES_DE_LA_MATRICE(IndexLigne_1),IndexColonne));
                    mEGAL(caractere_2,MATRICE(PERMUTATION_DES_LIGNES_DE_LA_MATRICE(IndexLigne_2),IndexColonne));
                                        /* Afin d'optimiser ce qui suit...                                                           */

                    Test(mIFLT(caractere_1,caractere_2))
                              {
                              mEGAL(ResultatDeLaComparaisonDeDeuxChaines,INFERIEUR);
                              mEGAL(PoursuivreLaComparaison,FAUX);
                              }
                    ATes
                              {
                              Test(mIFGT(caractere_1,caractere_2))
                                        {
                                        mEGAL(ResultatDeLaComparaisonDeDeuxChaines,SUPERIEUR);
                                        mEGAL(PoursuivreLaComparaison,FAUX);
                                        }
                              ATes
                                        {
                                        mEGAL(ResultatDeLaComparaisonDeDeuxChaines,EGAL);
                                        }
                              ETes
                              }
                    ETes

                    Test(mIFEQ(PoursuivreLaComparaison,VRAI))
                              {
                              Test(mIFLT(IndexColonne,IndexColonneMaximal))
                                        {
                                        mINCR(IndexColonne);
                                        }
                              ATes
                                        {
                                        mEGAL(PoursuivreLaComparaison,FAUX);
                                        }
                              ETes
                              }
                    ATes
                              {
                              }
                    ETes
                    }
          ETan

          return(ResultatDeLaComparaisonDeDeuxChaines);
          }

#define   D_BWT_EchangeDeDeuxChaines(IndexLigne_1,IndexLigne_2)                                                                         \
                    {                                                                                                                   \
                    Entier    VariableDeManoeuvre;                                                                                      \
                                                                                                                                        \
                    mEGAL(VariableDeManoeuvre,PERMUTATION_DES_LIGNES_DE_LA_MATRICE(IndexLigne_1));                                      \
                    mEGAL(PERMUTATION_DES_LIGNES_DE_LA_MATRICE(IndexLigne_1),PERMUTATION_DES_LIGNES_DE_LA_MATRICE(IndexLigne_2));       \
                    mEGAL(PERMUTATION_DES_LIGNES_DE_LA_MATRICE(IndexLigne_2),VariableDeManoeuvre);                                      \
                                        /* Permutation "virtuelle" des lignes de la matrice...                                       */ \
                    }

Entier    F_BWT_Reorganisation_01(Entier IndexLigneDebut
                                 ,Entier IndexLigneFin
                                 ,Entier IndexColonneMinimal
                                 ,Entier IndexColonneMaximal
                                  )
          {
          Entier    IndexLigne;
          Entier    ItererLaReorganisation;

          mEGAL(IndexLigne,IndexLigneDebut);
          mEGAL(ItererLaReorganisation,VRAI);

          Tant(mIFEQ(ItererLaReorganisation,VRAI))
                    {
                    Entier    IndexLigneGauche;

                    mEGAL(IndexLigneGauche,mMUL2(2,IndexLigne));

                    Test(mIFGT(IndexLigneGauche,IndexLigneFin))
                              {
                              mEGAL(ItererLaReorganisation,FAUX);
                              }
                    ATes
                              {
                              Entier    IndexMaximal;
                              Entier    IndexLigneDroite;

                              mEGAL(IndexMaximal,IndexLigneGauche);
                              mEGAL(IndexLigneDroite,mADD2(IndexLigneGauche,1));

                              Test(mIFGT(IndexLigneDroite,IndexLigneFin))
                                        {
                                        }
                              ATes
                                        {
                                        Test(mIFLT(F_BWT_ComparaisonDeDeuxChaines(IndexLigneGauche
                                                                                 ,IndexLigneDroite
                                                                                 ,IndexColonneMinimal
                                                                                 ,IndexColonneMaximal
                                                                                  )
                                                  ,EGAL
                                                   )
                                             )
                                                  {
                                                  mEGAL(IndexMaximal,IndexLigneDroite);
                                                  }
                                        ATes
                                                  {
                                                  }
                                        ETes
                                        }
                              ETes

                              Test(mIFLE(F_BWT_ComparaisonDeDeuxChaines(IndexMaximal
                                                                       ,IndexLigne
                                                                       ,IndexColonneMinimal
                                                                       ,IndexColonneMaximal
                                                                        )
                                        ,EGAL
                                         )
                                   )
                                        {
                                        mEGAL(ItererLaReorganisation,FAUX);
                                        }
                              ATes
                                        {
                                        D_BWT_EchangeDeDeuxChaines(IndexLigne,IndexMaximal);

                                        mEGAL(IndexLigne,IndexMaximal);
                                        }
                              ETes
                              }
                    ETes
                    }
          ETan

          return(VRAI);
          }

void      F_BWT_TriRapideDeLEnsembleDesChaines(Entier IndexLigneDebut
                                              ,Entier IndexLigneFin
                                              ,Entier IndexColonneMinimal
                                              ,Entier IndexColonneMaximal
                                               )
          {
          Entier    IndexLigne;

          mEGAL(IndexLigne,mDIVI(IndexLigneFin,2));

          Tant(mIFGE(IndexLigne,IndexLigneDebut))
                    {
                    CALL(F_BWT_Reorganisation_01(IndexLigne
                                                ,IndexLigneFin
                                                ,IndexColonneMinimal
                                                ,IndexColonneMaximal
                                                 )
                         );
                    mDECR(IndexLigne);
                    }
          ETan

          mEGAL(IndexLigne,IndexLigneFin);

          Tant(mIFGT(IndexLigne,IndexLigneDebut))
                    {
                    D_BWT_EchangeDeDeuxChaines(IndexLigneDebut,IndexLigne);

                    mDECR(IndexLigne);
                    CALL(F_BWT_Reorganisation_01(IndexLigneDebut
                                                ,IndexLigne
                                                ,IndexColonneMinimal
                                                ,IndexColonneMaximal
                                                 )
                         );
                    }
          ETan
          }

/*************************************************************************************************************************************/
/*                                                                                                                                   */
/*        E D I T I O N S   D I V E R S E S  :                                                                                       */
/*                                                                                                                                   */
/*************************************************************************************************************************************/
#define   D_BWT_EDITION_D_UNE_CHAINE(Message,EditionPreliminaire,ChaineA)                                                               \
                    {                                                                                                                   \
                    if        (BWT_EditerLesChaines == VRAI)                                                                            \
                              {                                                                                                         \
                              Entier    IndexCaractere;                                                                                 \
                                                                                                                                        \
                              printf("BWT/%s : ",Message);                                                                              \
                                                                                                                                        \
                              EditionPreliminaire;                                                                                      \
                                                                                                                                        \
                              for       (IndexCaractere=INDEX0 ; IndexCaractere <= BWT_INDEXN ; IndexCaractere++)                       \
                                        {                                                                                               \
                                        printf(FORMAT_CARACTERE,ACCES_CHAINE(ChaineA,IndexCaractere));                                  \
                                        }                                                                                               \
                                                                                                                                        \
                              printf("\n");                                                                                             \
                              }                                                                                                         \
                    else                                                                                                                \
                              {                                                                                                         \
                              }                                                                                                         \
                    }

#define   D_BWT_EDITION_DE_LA_MATRICE(operateur)                                                                                        \
                    {                                                                                                                   \
                    if        (BWT_EditerLaMatrice == VRAI)                                                                             \
                              {                                                                                                         \
                              Entier    IndexLigne;                                                                                     \
                                                                                                                                        \
                              printf("\n");                                                                                             \
                                                                                                                                        \
                              for       (IndexLigne=INDEX0 ; IndexLigne <= BWT_INDEXN ; IndexLigne++)                                   \
                                        {                                                                                               \
                                        Entier    IndexColonne;                                                                         \
                                                                                                                                        \
                                        for       (IndexColonne=0 ; IndexColonne <= BWT_INDEXN ; IndexColonne++)                        \
                                                  {                                                                                     \
                                                  printf(FORMAT_CARACTERE,MATRICE(operateur(IndexLigne),IndexColonne));                 \
                                                  }                                                                                     \
                                                                                                                                        \
                                        printf("\n");                                                                                   \
                                        }                                                                                               \
                                                                                                                                        \
                              printf("\n");                                                                                             \
                              }                                                                                                         \
                    else                                                                                                                \
                              {                                                                                                         \
                              }                                                                                                         \
                    }

/*************************************************************************************************************************************/
/*                                                                                                                                   */
/*        I N I T I A L I S A T I O N   D E   L A   C H A I N E   A   T R A I T E R  :                                               */
/*                                                                                                                                   */
/*************************************************************************************************************************************/
#define   D_BWT________Debut(ChaineR,ChaineA,LongueurChaineA)                                                                           \
                    {                                                                                                                   \
                    Entier    IndexCaractere;                                                                                           \
                                                                                                                                        \
                    BWT_LongueurDeToutesLesChaines = LongueurChaineA;                                                                   \
                                        /* ATTENTION : en toute generalite dans 'ChaineA' les 256 codes possibles peuvent            */ \
                                        /* etre presents et donc 'strlen(...)' ne peut pas fonctionner systematiquement. C'est       */ \
                                        /* pourquoi un parametre de longueur 'LongueurChaineA' doit apparaitre explicitement...      */ \
                                                                                                                                        \
                    ChaineR = MALLOC(BWT_LongueurDeToutesLesChaines*sizeof(CHAR));                                                      \
                                                                                                                                        \
                    DoIn(IndexCaractere,INDEX0,BWT_INDEXN)                                                                              \
                              {                                                                                                         \
                              ACCES_CHAINE(ChaineR,IndexCaractere) = ACCES_CHAINE(ChaineA,IndexCaractere);                              \
                              }                                                                                                         \
                    EDoI                                                                                                                \
                    }

#define   D_BWT________Fin__(ChaineA)                                                                                                   \
                    {                                                                                                                   \
                    free(ChaineA);                                                                                                      \
                    }

/*************************************************************************************************************************************/
/*                                                                                                                                   */
/*        T R A N S F O R M A T I O N   D E   B U R R O W S - W H E E L E R   D I R E C T E  :                                       */
/*                                                                                                                                   */
/*************************************************************************************************************************************/
#define   D_BWT_GenerationDeLaChainePermutee(ChaineR)                                                                                   \
                    {                                                                                                                   \
                    Entier    IndexLigne;                                                                                               \
                                                                                                                                        \
                    for       (IndexLigne=INDEX0 ; IndexLigne <= BWT_INDEXN ; IndexLigne++)                                             \
                              {                                                                                                         \
                              ACCES_CHAINE(ChaineR,IndexLigne)                                                                          \
                              = MATRICE(PERMUTATION_DES_LIGNES_DE_LA_MATRICE(IndexLigne),BWT_INDEXN);                                   \
                                        /* Version permutee de la chaine initiale 'ChaineAPermuter'. Elle est en fait constituee     */ \
                                        /* de la derniere colonne ('INDEXN') de la matrice 'Matrice'...                              */ \
                                                                                                                                        \
                              if        (PERMUTATION_DES_LIGNES_DE_LA_MATRICE(IndexLigne) == INDEX0)                                    \
                                        {                                                                                               \
                                        BWT_IndexDeLaChaineAPermuterDansLaMatrice = IndexLigne;                                         \
                                        /* Memorisation de l'index de la ligne de la matrice 'Matrice' contenant dans le bon         */ \
                                        /* ordre la chaine Argument...                                                               */ \
                                        }                                                                                               \
                              else                                                                                                      \
                                        {                                                                                               \
                                        }                                                                                               \
                              }                                                                                                         \
                                                                                                                                        \
                    D_BWT_EDITION_D_UNE_CHAINE("GenerationDeLaChainePermutee"                                                           \
                                              ,{                                                                                        \
                                               printf("%08"For10" "                                                                     \
                                                     ,BWT_IndexDeLaChaineAPermuterDansLaMatrice                                         \
                                                      );                                                                                \
                                               }                                                                                        \
                                              ,ChaineR                                                                                  \
                                               );                                                                                       \
                    }

#define   D_BWT_DirecteDebut(ChaineA)                                                                                                   \
                    {                                                                                                                   \
                    BWT_Directe_LongueurAvant = BWT_LongueurDeToutesLesChaines;                                                         \
                                                                                                                                        \
                    ChaineA = MALLOC(BWT_LongueurDeToutesLesChaines*sizeof(CHAR));                                                      \
                                        /* Allocations memoire diverses...                                                           */ \
                    }

#define   D_BWT_Directe(ChaineR,ChaineA)                                                                                                \
                    {                                                                                                                   \
                    if        (BWT_Utiliser == VRAI)                                                                                    \
                              {                                                                                                         \
                              Entier    SaveBWT_LongueurDeToutesLesChaines                                                              \
                                        =BWT_LongueurDeToutesLesChaines;                                                                \
                                                                                                                                        \
                              CHAR      *SousChaineR=ChaineR;                                                                           \
                              CHAR      *SousChaineA=ChaineA;                                                                           \
                                                                                                                                        \
                              Entier    NombreDOctetsEncoreATraiter=BWT_LongueurDeToutesLesChaines;                                     \
                              Entier    NumeroDuPaquetCourant=1;                                                                        \
                                                                                                                                        \
                              BWT_NombreDePaquets = DIVISION_PAR_EXCES(BWT_LongueurDeToutesLesChaines,BWT_TailleDesPaquets);            \
                                                                                                                                        \
                              BWT_ListeIndexDeLaChaineA                                                                                 \
                              = MALLOC(BWT_NombreDePaquets*sizeof(BWT_TYPE_IndexDeLaChaineAPermuterDansLaMatrice));                     \
                                                                                                                                        \
                              while     (NombreDOctetsEncoreATraiter > 0)                                                               \
                                        {                                                                                               \
                                        Entier    LongueurDeSousChaineAMesurer=MIN2(BWT_TailleDesPaquets,NombreDOctetsEncoreATraiter);  \
                                        Entier    IndexLigne;                                                                           \
                                                                                                                                        \
                                        BWT_LongueurDeToutesLesChaines = LongueurDeSousChaineAMesurer;                                  \
                                                                                                                                        \
                                        BWT_Matrice                                                                                     \
                                        = MALLOC(BWT_LongueurDeToutesLesChaines*BWT_LongueurDeToutesLesChaines*sizeof(CHAR));           \
                                        BWT_PermutationDesLignesDeLaMatrice                                                             \
                                        = MALLOC(BWT_LongueurDeToutesLesChaines*sizeof(Entier));                                        \
                                                                                                                                        \
                                        for       (IndexLigne=INDEX0 ; IndexLigne <= BWT_INDEXN ; IndexLigne++)                         \
                                                  {                                                                                     \
                                                  Entier    IndexColonne;                                                               \
                                                                                                                                        \
                                                  PERMUTATION_DES_LIGNES_DE_LA_MATRICE(IndexLigne) = IndexLigne;                        \
                                        /* Initialisation neutre a priori du tri de toutes les chaines...                            */ \
                                                                                                                                        \
                                                  for       (IndexColonne=0 ; IndexColonne <= BWT_INDEXN ; IndexColonne++)              \
                                                            {                                                                           \
                                                            Entier    IndexCaractere=IndexColonne-IndexLigne;                           \
                                                                                                                                        \
                                                            if        (IndexCaractere < 0)                                              \
                                                                      {                                                                 \
                                                                      IndexCaractere = IndexCaractere+BWT_LongueurDeToutesLesChaines;   \
                                                                      }                                                                 \
                                                            else                                                                        \
                                                                      {                                                                 \
                                                                      }                                                                 \
                                                                                                                                        \
                                                            MATRICE(IndexLigne,IndexColonne)                                            \
                                                            = ACCES_CHAINE(SousChaineA,IndexCaractere);                                 \
                                        /* Permutations circulaires de 'ChaineAPermuter'...                                          */ \
                                                            }                                                                           \
                                                  }                                                                                     \
                                                                                                                                        \
                                        D_BWT_EDITION_DE_LA_MATRICE(PERMUTATION_DES_LIGNES_DE_LA_MATRICE);                              \
                                                                                                                                        \
                                        F_BWT_TriRapideDeLEnsembleDesChaines(INDEX0,BWT_INDEXN                                          \
                                                                            ,INDEX0,BWT_INDEXN                                          \
                                                                             );                                                         \
                                                                                                                                        \
                                        D_BWT_EDITION_DE_LA_MATRICE(PERMUTATION_DES_LIGNES_DE_LA_MATRICE);                              \
                                                                                                                                        \
                                        D_BWT_GenerationDeLaChainePermutee(SousChaineR);                                                \
                                                                                                                                        \
                                        ACCES_CHAINE(BWT_ListeIndexDeLaChaineA,NombreVersIndex(NumeroDuPaquetCourant))                  \
                                        = BWT_IndexDeLaChaineAPermuterDansLaMatrice;                                                    \
                                                                                                                                        \
                                        SousChaineA = SousChaineA+LongueurDeSousChaineAMesurer;                                         \
                                        SousChaineR = SousChaineR+LongueurDeSousChaineAMesurer;                                         \
                                                                                                                                        \
                                        NombreDOctetsEncoreATraiter = NombreDOctetsEncoreATraiter-LongueurDeSousChaineAMesurer;         \
                                        NumeroDuPaquetCourant++;                                                                        \
                                                                                                                                        \
                                        free(BWT_Matrice);                                                                              \
                                        free(BWT_PermutationDesLignesDeLaMatrice);                                                      \
                                        }                                                                                               \
                                                                                                                                        \
                              BWT_LongueurDeToutesLesChaines = SaveBWT_LongueurDeToutesLesChaines;                                      \
                              }                                                                                                         \
                    else                                                                                                                \
                              {                                                                                                         \
                              Entier    IndexCaractere;                                                                                 \
                                                                                                                                        \
                              for       (IndexCaractere=INDEX0 ; IndexCaractere <= BWT_INDEXN ; IndexCaractere++)                       \
                                        {                                                                                               \
                                        ACCES_CHAINE(ChaineR,IndexCaractere) = ACCES_CHAINE(ChaineA,IndexCaractere);                    \
                                        }                                                                                               \
                              }                                                                                                         \
                                                                                                                                        \
                    BWT_Directe_LongueurApres = BWT_LongueurDeToutesLesChaines;                                                         \
                    }

#define   D_BWT_DirecteFin__()                                                                                                          \
                    {                                                                                                                   \
                    }

/*************************************************************************************************************************************/
/*                                                                                                                                   */
/*        T R A N S F O R M A T I O N   D E   B U R R O W S - W H E E L E R   I N V E R S E   ( V E R S I O N   " 01 " )  :          */
/*                                                                                                                                   */
/*************************************************************************************************************************************/
#define   D_BWT_GenerationDeLaChaineRetablie(ChaineR)                                                                                   \
                    {                                                                                                                   \
                    Entier    IndexCaractere;                                                                                           \
                                                                                                                                        \
                    DoIn(IndexCaractere,INDEX0,BWT_INDEXN)                                                                              \
                              {                                                                                                         \
                              mEGAL(ACCES_CHAINE(ChaineR,IndexCaractere)                                                                \
                                   ,MATRICE(PERMUTATION_DES_LIGNES_DE_LA_MATRICE(BWT_IndexDeLaChaineAPermuterDansLaMatrice)             \
                                           ,IndexCaractere                                                                              \
                                            )                                                                                           \
                                     );                                                                                                 \
                              }                                                                                                         \
                    EDoI                                                                                                                \
                    }

#define   D_BWT_InverseDebut_01(ChaineR)                                                                                                \
                    {                                                                                                                   \
                    BWT_Inverse_LongueurAvant = BWT_LongueurDeToutesLesChaines;                                                         \
                                                                                                                                        \
                    ChaineR = MALLOC(BWT_LongueurDeToutesLesChaines*sizeof(CHAR));                                                      \
                                        /* Allocations memoire diverses...                                                           */ \
                    }

#define   D_BWT_Inverse_Debut(ChaineR,ChaineA)                                                                                          \
                    {                                                                                                                   \
                    Test(mIFEQ(BWT_Utiliser,VRAI))                                                                                      \
                              {                                                                                                         \
                              CHAR      *SousChaineR=ChaineR;                                                                           \
                              CHAR      *SousChaineA=ChaineA;                                                                           \
                              Entier    NombreDOctetsEncoreATraiter;                                                                    \
                              Entier    NumeroDuPaquetCourant;                                                                          \
                              Entier    SaveBWT_LongueurDeToutesLesChaines=BWT_LongueurDeToutesLesChaines;                              \
                                                                                                                                        \
                              mEGAL(NombreDOctetsEncoreATraiter,BWT_LongueurDeToutesLesChaines);                                        \
                              mEGAL(BWT_NombreDePaquets,DIVISION_PAR_EXCES(LongueurDeChaineAMesurer,BWT_TailleDesPaquets));             \
                              mEGAL(NumeroDuPaquetCourant,1);                                                                           \
                                                                                                                                        \
                              Tant(mIFGT(NombreDOctetsEncoreATraiter,0))                                                                \
                                        {                                                                                               \
                                        Entier    LongueurDeSousChaineAMesurer=MIN2(BWT_TailleDesPaquets,NombreDOctetsEncoreATraiter);  \
                                        Entier    IndexColonne;                                                                         \
                                                                                                                                        \
                                        mEGAL(BWT_IndexDeLaChaineAPermuterDansLaMatrice                                                 \
                                             ,ACCES_CHAINE(BWT_ListeIndexDeLaChaineA,NombreVersIndex(NumeroDuPaquetCourant))            \
                                              );                                                                                        \
                                        BWT_LongueurDeToutesLesChaines = LongueurDeSousChaineAMesurer;

#define   D_BWT_Inverse_Milieu_01(SousChaineR,SousChaineA)                                                                              \
                                        {                                                                                               \
                                        BWT_Matrice                                                                                     \
                                        = MALLOC(BWT_LongueurDeToutesLesChaines*BWT_LongueurDeToutesLesChaines*sizeof(CHAR));           \
                                        BWT_PermutationDesLignesDeLaMatrice                                                             \
                                        = MALLOC(BWT_LongueurDeToutesLesChaines*sizeof(Entier));                                        \
                                                                                                                                        \
                                                                                                                                        \
                                        Test(FAUX)                                                                                      \
                                                  {                                                                                     \
                                                  DoIn(IndexColonne,INDEX0,BWT_INDEXN)                                                  \
                                                            {                                                                           \
                                                            Entier    IndexLigne;                                                       \
                                                                                                                                        \
                                                            DoIn(IndexLigne,INDEX0,BWT_INDEXN)                                          \
                                                                      {                                                                 \
                                                                      mEGAL(MATRICEd(IndexLigne,IndexColonne),0);                       \
                                        /* Initialisation de la matrice : ceci est en fait inutile car cette derniere est remplie    */ \
                                        /* colonne par colonne (en partant de la colonne de droite 'INDEXN') et que n'est utilise    */ \
                                        /* que le sous-ensemble de colonnes qui ont ete remplies. Cette sequence est malgre tout     */ \
                                        /* conservee (sans etre utilisee), on ne sait jamais...                                      */ \
                                                                      }                                                                 \
                                                            EDoI                                                                        \
                                                            }                                                                           \
                                                  EDoI                                                                                  \
                                                  }                                                                                     \
                                        ATes                                                                                            \
                                                  {                                                                                     \
                                                  }                                                                                     \
                                        ETes                                                                                            \
                                                                                                                                        \
                                        DoDe(IndexColonne,INDEX0,BWT_INDEXN)                                                            \
                                                  {                                                                                     \
                                                  Entier    IndexLigne;                                                                 \
                                                                                                                                        \
                                                  DoIn(IndexLigne,INDEX0,BWT_INDEXN)                                                    \
                                                            {                                                                           \
                                                            Test(mIFEQ(IndexColonne,BWT_INDEXN))                                        \
                                                                      {                                                                 \
                                                                      mEGAL(PERMUTATION_DES_LIGNES_DE_LA_MATRICE(IndexLigne)            \
                                                                           ,IndexLigne                                                  \
                                                                            );                                                          \
                                        /* Initialisation neutre a priori du tri de toutes les chaines...                            */ \
                                                                      }                                                                 \
                                                            ATes                                                                        \
                                                                      {                                                                 \
                                                                      }                                                                 \
                                                            ETes                                                                        \
                                                                                                                                        \
                                                            mEGAL(MATRICEd(PERMUTATION_DES_LIGNES_DE_LA_MATRICE(IndexLigne)             \
                                                                          ,IndexColonne                                                 \
                                                                           )                                                            \
                                                                 ,ACCES_CHAINE(SousChaineA,IndexLigne)                                  \
                                                                  );                                                                    \
                                        /* La chaine permutee est introduite dans l'ordre du classement courant en tant que          */ \
                                        /* colonne courante de gauche ('IndexColonne').                                              */ \
                                                            }                                                                           \
                                                  EDoI                                                                                  \
                                                                                                                                        \
                                                  D_BWT_EDITION_DE_LA_MATRICE(PERMUTATION_DES_LIGNES_DE_LA_MATRICE);                    \
                                                                                                                                        \
                                                  F_BWT_TriRapideDeLEnsembleDesChaines(INDEX0                                           \
                                                                                      ,BWT_INDEXN                                       \
                                                                                      ,IndexColonne                                     \
                                                                                      ,BWT_INDEXN                                       \
                                                                                       );                                               \
                                                                                                                                        \
                                                  D_BWT_EDITION_DE_LA_MATRICE(PERMUTATION_DES_LIGNES_DE_LA_MATRICE);                    \
                                                  }                                                                                     \
                                        EDoD                                                                                            \
                                                                                                                                        \
                                        D_BWT_GenerationDeLaChaineRetablie(SousChaineR);                                                \
                                        /* La chaine Argment est retrouvee sur la ligne 'IndexDeLaChaineAPermuterDansLaMatrice'      */ \
                                        /* de la matrice 'Matrice'.                                                                  */ \
                                                                                                                                        \
                                        CALLs(free(BWT_PermutationDesLignesDeLaMatrice));                                               \
                                        CALLs(free(BWT_Matrice));                                                                       \
                                        }

#define   D_BWT_Inverse_Fin(ChaineR,SousChaineR,ChaineA,SousChaineA)                                                                    \
                                        D_BWT_EDITION_D_UNE_CHAINE("TransformationInverse",{},SousChaineR);                             \
                                                                                                                                        \
                                        mEGAL(SousChaineA,mADD2(SousChaineA,LongueurDeSousChaineAMesurer));                             \
                                        mEGAL(SousChaineR,mADD2(SousChaineR,LongueurDeSousChaineAMesurer));                             \
                                        mEGAL(NombreDOctetsEncoreATraiter                                                               \
                                             ,mSOUS(NombreDOctetsEncoreATraiter,LongueurDeSousChaineAMesurer)                           \
                                              );                                                                                        \
                                        mINCR(NumeroDuPaquetCourant);                                                                   \
                                        }                                                                                               \
                              ETan                                                                                                      \
                                                                                                                                        \
                              mEGAL(BWT_LongueurDeToutesLesChaines                                                                      \
                                   ,SaveBWT_LongueurDeToutesLesChaines                                                                  \
                                    );                                                                                                  \
                              CALLs(free(BWT_ListeIndexDeLaChaineA));                                                                   \
                              }                                                                                                         \
                    ATes                                                                                                                \
                              {                                                                                                         \
                              Entier    IndexCaractere;                                                                                 \
                                                                                                                                        \
                              DoIn(IndexCaractere,INDEX0,BWT_INDEXN)                                                                    \
                                        {                                                                                               \
                                        mEGAL(ACCES_CHAINE(ChaineR,IndexCaractere),ACCES_CHAINE(ChaineA,IndexCaractere));               \
                                        }                                                                                               \
                              EDoI                                                                                                      \
                              }                                                                                                         \
                    ETes                                                                                                                \
                    }

#define   D_BWT_Inverse_01(ChaineR,ChaineA)                                                                                             \
                    {                                                                                                                   \
                    D_BWT_Inverse_Debut(ChaineR,ChaineA);                                                                               \
                    D_BWT_Inverse_Milieu_01(SousChaineR,SousChaineA);                                                                   \
                    D_BWT_Inverse_Fin(ChaineR,SousChaineR,ChaineA,SousChaineA);                                                         \
                                                                                                                                        \
                    BWT_Inverse_LongueurApres = BWT_LongueurDeToutesLesChaines;                                                         \
                    }

#define   D_BWT_InverseFin___01(ChaineA1,ChaineA2)                                                                                      \
                    {                                                                                                                   \
                    CALLs(free(ChaineA1));                                                                                              \
                    CALLs(free(ChaineA2));                                                                                              \
                    }

/*************************************************************************************************************************************/
/*                                                                                                                                   */
/*        T R A N S F O R M A T I O N   D E   B U R R O W S - W H E E L E R   I N V E R S E   ( V E R S I O N   02 )  :              */
/*                                                                                                                                   */
/*************************************************************************************************************************************/
#define   D_BWT_InverseDebut_02(ChaineR)                                                                                                \
                    {                                                                                                                   \
                    BWT_Inverse_LongueurAvant = BWT_LongueurDeToutesLesChaines;                                                         \
                                                                                                                                        \
                    ChaineR = MALLOC(BWT_LongueurDeToutesLesChaines*sizeof(CHAR));                                                      \
                                        /* Allocations memoire diverses...                                                           */ \
                    }

#define   D_BWT_EchangeDeDeuxCaracteres(Index_1,Index_2)                                                                                \
                    {                                                                                                                   \
                    CHAR      CaractereIntermediaire;                                                                                   \
                                                                                                                                        \
                    mEGAL(CaractereIntermediaire,ACCES_CHAINE(BWT_ChainePT,Index_1));                                                   \
                    mEGAL(ACCES_CHAINE(BWT_ChainePT,Index_1),ACCES_CHAINE(BWT_ChainePT,Index_2));                                       \
                    mEGAL(ACCES_CHAINE(BWT_ChainePT,Index_2),CaractereIntermediaire);                                                   \
                    }

Entier    F_BWT_Reorganisation_02(Entier IndexDebut,Entier IndexFin)
          {
          Entier    Index;
          Logical   ItererLaReorganisation;

          mEGAL(Index,IndexDebut);
          mEGAL(ItererLaReorganisation,VRAI);

          Tant(IFEQ(ItererLaReorganisation,VRAI))
                    {
                    Entier    IndexGauche;

                    mEGAL(IndexGauche,mMUL2(2,Index));

                    Test(mIFGT(IndexGauche,IndexFin))
                              {
                              mEGAL(ItererLaReorganisation,FAUX);
                              }
                    ATes
                              {
                              Entier    IndexMaximal;
                              Entier    IndexDroite;

                              mEGAL(IndexMaximal,IndexGauche);
                              mEGAL(IndexDroite,mADD2(IndexGauche,1));

                              Test(mIFGT(IndexDroite,IndexFin))
                                        {
                                        }
                              ATes
                                        {
                                        Test(mIFLT(ACCES_CHAINE(BWT_ChainePT,IndexGauche),ACCES_CHAINE(BWT_ChainePT,IndexDroite)))
                                                  {
                                                  mEGAL(IndexMaximal,IndexDroite);
                                                  }
                                        ATes
                                                  {
                                                  }
                                        ETes
                                        }
                              ETes

                              Test(mIFLE(ACCES_CHAINE(BWT_ChainePT,IndexMaximal),ACCES_CHAINE(BWT_ChainePT,Index)))
                                        {
                                        mEGAL(ItererLaReorganisation,FAUX);
                                        }
                              ATes
                                        {
                                        D_BWT_EchangeDeDeuxCaracteres(Index,IndexMaximal);
                                        mEGAL(Index,IndexMaximal);
                                        }
                              ETes
                              }
                    ETes
                    }
          ETan

          return(VRAI);
          }

Entier    F_BWT_TriRapideDUneChaine(Entier IndexDebut,Entier IndexFin)
          {
          Entier    Index;

          mEGAL(Index,mDIVI(IndexFin,2));

          Tant(mIFGE(Index,IndexDebut))
                    {
                    CALL(F_BWT_Reorganisation_02(Index,IndexFin));
                    mDECR(Index);
                    }
          ETan

          mEGAL(Index,IndexFin);

          Tant(Index > IndexDebut)
                    {
                    D_BWT_EchangeDeDeuxCaracteres(IndexDebut,Index);
                    mDECR(Index);
                    CALL(F_BWT_Reorganisation_02(IndexDebut,Index));
                    }
          ETan

          return(VRAI);
          }

#define   D_BWT_Inverse_Milieu_02(SousChaineR,SousChaineA)                                                                              \
                                        {                                                                                               \
                                        Entier    Index;                                                                                \
                                                                                                                                        \
                                        BWT_ChainePT = MALLOC(BWT_LongueurDeToutesLesChaines*sizeof(CHAR));                             \
                                        BWT_ChainePT_NumeroDOccurence = MALLOC(BWT_LongueurDeToutesLesChaines*sizeof(Entier));          \
                                                                                                                                        \
                                        DoIn(Index,INDEX0,BWT_INDEXN)                                                                   \
                                                  {                                                                                     \
                                                  mEGAL(ACCES_CHAINE(BWT_ChainePT,Index),ACCES_CHAINE(SousChaineA,Index));              \
                                                  }                                                                                     \
                                        EDoI                                                                                            \
                                                                                                                                        \
                                        Test(FAUX)                                                                                      \
                                        /* Cas du tri en N^2 :                                                                       */ \
                                                  {                                                                                     \
                                                  Entier    IndexDeFinDeChaine;                                                         \
                                                                                                                                        \
                                                  DoDe(IndexDeFinDeChaine,INDEX0,mSOUS(BWT_INDEXN,1))                                   \
                                                            {                                                                           \
                                                            Entier    IndexDeDebutDeChaine;                                             \
                                                                                                                                        \
                                                            DoIn(IndexDeDebutDeChaine,INDEX0,IndexDeFinDeChaine)                        \
                                                                      {                                                                 \
                                                                      Test(mIFGT(ACCES_CHAINE(BWT_ChainePT,IndexDeDebutDeChaine)        \
                                                                                ,ACCES_CHAINE(BWT_ChainePT                              \
                                                                                             ,mADD2(IndexDeDebutDeChaine,1)             \
                                                                                              )                                         \
                                                                                 )                                                      \
                                                                           )                                                            \
                                                                                {                                                       \
                                                                                CHAR      CaractereDeManoeuvre;                         \
                                                                                                                                        \
                                                                                mEGAL(CaractereDeManoeuvre                              \
                                                                                     ,ACCES_CHAINE(BWT_ChainePT,IndexDeDebutDeChaine)   \
                                                                                      );                                                \
                                                                                mEGAL(ACCES_CHAINE(BWT_ChainePT,IndexDeDebutDeChaine)   \
                                                                                     ,ACCES_CHAINE(BWT_ChainePT                         \
                                                                                                  ,mADD2(IndexDeDebutDeChaine,1)        \
                                                                                                   )                                    \
                                                                                      );                                                \
                                                                                mEGAL(ACCES_CHAINE(BWT_ChainePT                         \
                                                                                                  ,mADD2(IndexDeDebutDeChaine,1)        \
                                                                                                   )                                    \
                                                                                     ,CaractereDeManoeuvre                              \
                                                                                      );                                                \
                                        /* Tri en N^2 de la chaine permutee...                                                       */ \
                                                                                }                                                       \
                                                                      ATes                                                              \
                                                                                {                                                       \
                                                                                }                                                       \
                                                                      ETes                                                              \
                                                                      }                                                                 \
                                                            EDoI                                                                        \
                                                            }                                                                           \
                                                  EDoD                                                                                  \
                                                  }                                                                                     \
                                        ATes                                                                                            \
                                                  {                                                                                     \
                                        /* Cas du tri en N.log(N) :                                                                  */ \
                                                  CALL(F_BWT_TriRapideDUneChaine(INDEX0,BWT_INDEXN));                                   \
                                                  }                                                                                     \
                                        ETes                                                                                            \
                                                                                                                                        \
                                                  {                                                                                     \
                                                  Entier    NombreDOccurences;                                                          \
                                                                                                                                        \
                                                  mEGAL(NombreDOccurences,1);                                                           \
                                                                                                                                        \
                                                  mEGAL(ACCES_CHAINE(BWT_ChainePT_NumeroDOccurence,INDEX0),NombreDOccurences);          \
                                                                                                                                        \
                                                  DoIn(Index,mADD2(INDEX0,1),BWT_INDEXN)                                                \
                                                            {                                                                           \
                                                            Test(mIFEQ(ACCES_CHAINE(BWT_ChainePT,mSOUS(Index,1))                        \
                                                                      ,ACCES_CHAINE(BWT_ChainePT,Index)                                 \
                                                                       )                                                                \
                                                                 )                                                                      \
                                                                      {                                                                 \
                                                                      mINCR(NombreDOccurences);                                         \
                                                                      }                                                                 \
                                                            ATes                                                                        \
                                                                      {                                                                 \
                                                                      mEGAL(NombreDOccurences,1);                                       \
                                                                      }                                                                 \
                                                            ETes                                                                        \
                                                                                                                                        \
                                                            mEGAL(ACCES_CHAINE(BWT_ChainePT_NumeroDOccurence,Index),NombreDOccurences); \
                                                            }                                                                           \
                                                  EDoI                                                                                  \
                                                                                                                                        \
                                                            {                                                                           \
                                                            Entier    IndexCaractere;                                                   \
                                                                                                                                        \
                                                            mEGAL(IndexCaractere,BWT_IndexDeLaChaineAPermuterDansLaMatrice);            \
                                                                                                                                        \
                                                            DoIn(Index,INDEX0,BWT_INDEXN)                                               \
                                                                      {                                                                 \
                                                                      CHAR      CaractereCourant;                                       \
                                                                      Entier    NombreDOccurencesCourant;                               \
                                                                                                                                        \
                                                                      Entier    IndexDeRecherche;                                       \
                                                                      Logical   ItererLaRecherche;                                      \
                                                                                                                                        \
                                                                      mEGAL(CaractereCourant                                            \
                                                                           ,ACCES_CHAINE(BWT_ChainePT,IndexCaractere)                   \
                                                                            );                                                          \
                                                                      mEGAL(NombreDOccurencesCourant                                    \
                                                                           ,ACCES_CHAINE(BWT_ChainePT_NumeroDOccurence,IndexCaractere)  \
                                                                            );                                                          \
                                                                                                                                        \
                                                                      mEGAL(ACCES_CHAINE(SousChaineR,Index),CaractereCourant);          \
                                                                                                                                        \
                                                                      mEGAL(IndexDeRecherche,INDEX0);                                   \
                                                                      mEGAL(ItererLaRecherche,VRAI);                                    \
                                                                                                                                        \
                                                                      mEGAL(NombreDOccurences,1);                                       \
                                                                                                                                        \
                                                                      Tant(mIFEQ(ItererLaRecherche,VRAI))                               \
                                                                                {                                                       \
                                                                                Test(mIFEQ(ACCES_CHAINE(SousChaineA,IndexDeRecherche)   \
                                                                                          ,CaractereCourant                             \
                                                                                           )                                            \
                                                                                     )                                                  \
                                                                                          {                                             \
                                                                                          Test(mIFEQ(NombreDOccurencesCourant           \
                                                                                                    ,NombreDOccurences                  \
                                                                                                     )                                  \
                                                                                               )                                        \
                                                                                                    {                                   \
                                                                                                    mEGAL(IndexCaractere                \
                                                                                                         ,IndexDeRecherche              \
                                                                                                          );                            \
                                                                                                    mEGAL(ItererLaRecherche,FAUX);      \
                                                                                                    }                                   \
                                                                                          ATes                                          \
                                                                                                    {                                   \
                                                                                                    mINCR(NombreDOccurences);           \
                                                                                                    }                                   \
                                                                                          ETes                                          \
                                                                                          }                                             \
                                                                                ATes                                                    \
                                                                                          {                                             \
                                                                                          }                                             \
                                                                                ETes                                                    \
                                                                                                                                        \
                                                                                Test(mIFLT(IndexDeRecherche,BWT_INDEXN))                \
                                                                                          {                                             \
                                                                                          mINCR(IndexDeRecherche);                      \
                                                                                          }                                             \
                                                                                ATes                                                    \
                                                                                          {                                             \
                                                                                          mEGAL(ItererLaRecherche,FAUX);                \
                                                                                          }                                             \
                                                                                ETes                                                    \
                                                                                }                                                       \
                                                                      ETan                                                              \
                                                                      }                                                                 \
                                                            }                                                                           \
                                                  EDoI                                                                                  \
                                                  }                                                                                     \
                                                                                                                                        \
                                        CALLs(free(BWT_ChainePT_NumeroDOccurence));                                                     \
                                        CALLs(free(BWT_ChainePT));                                                                      \
                                        }

#define   D_BWT_Inverse_02(ChaineR,ChaineA)                                                                                             \
                    {                                                                                                                   \
                    D_BWT_Inverse_Debut(ChaineR,ChaineA);                                                                               \
                    D_BWT_Inverse_Milieu_02(SousChaineR,SousChaineA);                                                                   \
                    D_BWT_Inverse_Fin(ChaineR,SousChaineR,ChaineA,SousChaineA);                                                         \
                                                                                                                                        \
                    BWT_Inverse_LongueurApres = BWT_LongueurDeToutesLesChaines;                                                         \
                    }

#define   D_BWT_InverseFin___02(ChaineA1,ChaineA2)                                                                                      \
                    {                                                                                                                   \
                    }

/*************************************************************************************************************************************/
/*                                                                                                                                   */
/*        V E R I F I C A T I O N   D U   P R O C E S S U S   C O M P L E T  :                                                       */
/*                                                                                                                                   */
/*************************************************************************************************************************************/
void      F_BWT_Verifications(CHAR *ChaineA1,CHAR *ChaineA2)
          {
          Entier    IndexCaractere;

          for       (IndexCaractere=INDEX0 ; IndexCaractere <= BWT_INDEXN ; IndexCaractere++)
                    {
                    if        (ACCES_CHAINE(ChaineA1,IndexCaractere) != ACCES_CHAINE(ChaineA2,IndexCaractere))
                              {
                              fprintf(stderr
                                     ,"ERREUR(BWT) : chaine R ('0x%02x') # chaine A ('0x%02x').\n"
                                     ,ACCES_CHAINE(ChaineA1,IndexCaractere)
                                     ,ACCES_CHAINE(ChaineA2,IndexCaractere)
                                      );
                              }
                    else
                              {
                              }
                    }
          }



Copyright © Jean-François Colonna, 2016-2021.
Copyright © CMAP (Centre de Mathématiques APpliquées) UMR CNRS 7641 / Ecole Polytechnique, 2016-2021.