/*************************************************************************************************************************************/ /* */ /* C O M P R E S S I O N / D E C O M P R E S S I O N ' CDCM1 ' D ' U N E C H A I N E : */ /* */ /* */ /* Nota : */ /* */ /* Ce module est inspire de 'v $xtc/Compression.11$I' */ /* qui a servi a sa mise au point... */ /* */ /* */ /* Author of '$xrC/CompressionDeCompression_Compression.01$vv$I' : */ /* */ /* Jean-Francois Colonna (LACTAMME, 20151227143723). */ /* */ /*************************************************************************************************************************************/ /*************************************************************************************************************************************/ /* */ /* D E F I N I T I O N G E N E R A L E S : */ /* */ /*************************************************************************************************************************************/ #include "images.01.vv.I" #include <sys/stat.h> #include <string.h> #include <fcntl.h> #include <math.h> #include <time.h> #include <sys/time.h> #define Argument \ int #define Logical \ int #define F_INFINI \ 1.0e+300 Logical CDC_MettreEnConcurrenceLesDifferentesOptions=FAUX; double Complexite_K__Cumulee__Minimale=F_INFINI; double Complexite_LD_Cumulee__Associee_A_Complexite_K__Cumulee__Minimale; Logical BWT_Utiliser__Associee_A_Complexite_K__Cumulee__Minimale; Logical HUF_Utiliser__Associee_A_Complexite_K__Cumulee__Minimale; #define D_METTRE_EN_CONCURRENCE(Controle_BWT,Controle_HUF) \ { \ BWT_Utiliser = Controle_BWT; \ HUF_Utiliser = Controle_HUF; \ \ F_MesureDe_K_EtDe_LD_Globale(BufferDuFichier,TailleDuFichier); \ /* Mesure de K et de LD du fichier argument avec les options courantes... */ \ \ if (Complexite_K__Cumulee__ <= Complexite_K__Cumulee__Minimale) \ { \ if (Complexite_K__Cumulee__ == Complexite_K__Cumulee__Minimale) \ { \ Complexite_LD_Cumulee__Associee_A_Complexite_K__Cumulee__Minimale \ = MIN2(Complexite_LD_Cumulee__ \ ,Complexite_LD_Cumulee__Associee_A_Complexite_K__Cumulee__Minimale \ ); \ /* La fonction 'MIN2(...)' pourrait etre remplacee par 'MAX2(...)'... */ \ } \ else \ { \ Complexite_LD_Cumulee__Associee_A_Complexite_K__Cumulee__Minimale = Complexite_LD_Cumulee__; \ } \ \ Complexite_K__Cumulee__Minimale = Complexite_K__Cumulee__; \ \ BWT_Utiliser__Associee_A_Complexite_K__Cumulee__Minimale = BWT_Utiliser; \ HUF_Utiliser__Associee_A_Complexite_K__Cumulee__Minimale = HUF_Utiliser; \ } \ else \ { \ } \ } /* ATTENTION : la valeur effective des indicateurs n'est pas celle qui apparait ici, mais */ /* ce qui est force dans 'v $xrC/CompressionDeCompression_Compression.01$vv$c _Editer'. */ Logical CDC_EditerLesLongueurs=FAUX; Logical CDC_EditerArguments=VRAI; Logical CDC_EditerCDCBits=FAUX; Logical CDC_EditerChronometrage=FAUX; Logical CDC_EditerUniquement_K_et_LD_Cumulees=VRAI; Logical CDC_EditerLesComposantesDes_K_Partielles=FAUX; Logical CDC_Editer_K_bits=FAUX; Logical CDC_EditionsHexaDecimalesDesChaines=VRAI; /* Indicateurs de controle des editions... */ /* */ /* ATTENTION : la valeur effective de ces indicateurs n'est pas celle qui apparait ici, mais */ /* ce qui est force dans 'v $xrC/CompressionDeCompression_Compression.01$vv$c _Editer'. */ Argument CDC_TailleDesPaquets=0; /* La valeur nulle, par defaut, specifie en fait la taille du fichier... */ #define MALLOC(NomdreDOctets) \ malloc((size_t)NomdreDOctets) #define CHAR \ unsigned char \ /* Afin que tous les tests effectues fonctionnent correctement et que les relations */ \ /* d'odre soient bien celles que l'on attend, il est a priori necessaire que les */ \ /* caracteres soient non signes... */ #define SIZEOF(argument) \ (sizeof(argument)*NBITOC) \ /* Taille d'un argument en bits. */ #define EntierCourt \ 1 #define EntierMoyen \ 2 #define EntierLong \ 3 #define Precision \ EntierMoyen /* La Precision est soit 'EntierCourt' soit 'EntierLong'. En fait, a cause de */ /* 'v $xrC/OperateursComptage$vv$I LongInt', il convient d'utiliser 'EntierLong'... */ /* */ /* ATTENTION : on notera que 'EntierCourt' et 'EntierLong' doivent etre defines a l'aide */ /* de valeurs entieres si l'on veut que le '#if' qui suit fonctionne correctement... */ #define SEntier \ short int #define MEntier \ int #define LEntier \ long int #if (Precision == EntierCourt) # define Entier \ SEntier # define For10 \ "d" # define For16 \ "x" #else # if (Precision == EntierMoyen) # define Entier \ MEntier # define For10 \ "d" # define For16 \ "x" # else # define Entier \ LEntier # define For10 \ "ld" # define For16 \ "lx" # endif #endif /* Types de donnees et Formats utiles... */ #define DIVISION_PAR_EXCES(a,b) \ (((a)+(b)-1)/(b)) #include "CompressionDeCompression_OperateursComptage.01.vv.I" #define FORMAT_CARACTERE \ COND((CDC_EditionsHexaDecimalesDesChaines == VRAI),"%02x ","%c") \ /* Format d'edition des caracteres des chaines et de la matrice... */ #define FORMAT_VRAI_FAUX(condition) \ COND((condition == VRAI),"VRAI","FAUX") \ /* Afin de pouvoir editer la valeur d'une variable "Logical"... */ #define ACCES_CHAINE(Chaine,IndexCaractere) \ *mINDX(Chaine,IndexCaractere) /* Acces a une chaine quelconque... */ #include "CompressionDeCompression_BurrowsWheeler.01.vv.I" #define HUF_FIN_DE_CHAINE \ 0 \ /* Afin de ne pas prevoir de caractere de fin de chaine... */ #include "CompressionDeCompression_RunLengthEncoding.01.vv.I" #include "CompressionDeCompression_HuffmanCoding.01.vv.I" #define CDC_INDEXN \ NombreVersIndex(CDC_LongueurDeToutesLesChaines) Entier CDC_LongueurDeToutesLesChaines; CHAR *CDC_ChaineA; CHAR *CDC_ChaineR; CHAR CDC_ChaineBits[]="bits"; CHAR CDC_ChaineOctets[]="octets"; #define BITS_OU_OCTETS \ COND((CDC_Editer_K_bits == VRAI),CDC_ChaineBits,CDC_ChaineOctets) #define CONVERSION_BITS_OCTET(NombreDeBits) \ COND((CDC_Editer_K_bits == VRAI),NombreDeBits,DIVISION_PAR_EXCES(NombreDeBits,NBITOC)) /* Afin d'editer K en bits ou en octets... */ /*************************************************************************************************************************************/ /* */ /* V E R I F I C A T I O N D E S L O N G U E U R S : */ /* */ /*************************************************************************************************************************************/ #define D_CDC_VerificationsDesLongueurs(verifier,commentaire,longueur1,longueur2) \ { \ if (verifier == VRAI) \ { \ if (longueur1 != longueur2) \ { \ fprintf(stderr \ ,"ERREUR(CDC) : les longueurs '%s' different (%d # %d).\n" \ ,commentaire \ ,longueur1 \ ,longueur2 \ ); \ } \ else \ { \ } \ } \ else \ { \ } \ } /*************************************************************************************************************************************/ /* */ /* E D I T I O N D E S L O N G U E U R S : */ /* */ /*************************************************************************************************************************************/ #define D_CDC_EditionLongueur(commentaire,longueur) \ { \ if (CDC_EditerLesLongueurs == VRAI) \ { \ printf("LONGUEUR (%s) = %d\n" \ ,commentaire \ ,longueur \ ); \ } \ else \ { \ } \ } /*************************************************************************************************************************************/ /* */ /* C H R O N O M E T R A G E : */ /* */ /*************************************************************************************************************************************/ #define D_Bclock(commentaire) \ { \ clock_t valeur_initiale_du_chronometre=clock(); \ /* On notera que pour eviter des problemes de format dans les 'Prin?(...)' qui suivent sur */ \ /* 'SYSTEME_SGO200A2_IRIX_CC', la variable 'valeur_initiale_du_chronometre' est passe du */ \ /* type 'LongInt' au type 'Int' le 19980925104908. */ \ if (CDC_EditerChronometrage == VRAI) \ { \ printf("DEBUT DE CHRONOMETRAGE : %s\n" \ ,commentaire \ ); \ } \ else \ { \ } \ /* Mise en route du chronometre. */ #define D_Eclock(commentaire) \ if (CDC_EditerChronometrage == VRAI) \ { \ int nombre_de_secondes_pour_Eclock=((clock()-valeur_initiale_du_chronometre)/CLOCKS_PER_SEC); \ int nombre_de_micro_secondes_pour_Eclock=((clock()-valeur_initiale_du_chronometre)%CLOCKS_PER_SEC); \ \ printf("FIN DE CHRONOMETRAGE : %s - temps ecoule : %d s + %d ms\n" \ ,commentaire \ ,nombre_de_secondes_pour_Eclock \ ,nombre_de_micro_secondes_pour_Eclock \ ); \ } \ else \ { \ } \ } \ /* Et enfin, edition du temps ecoule depuis la mise en route du chronometre. */ /*************************************************************************************************************************************/ /* */ /* 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_CDC________Debut(ChaineR,ChaineA,LongueurChaineA) \ { \ Entier IndexCaractere; \ \ CDC_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(CDC_LongueurDeToutesLesChaines*sizeof(CHAR)); \ \ for (IndexCaractere=INDEX0 ; IndexCaractere <= CDC_INDEXN ; IndexCaractere++) \ { \ ACCES_CHAINE(ChaineR,IndexCaractere) = ACCES_CHAINE(ChaineA,IndexCaractere); \ } \ } #define D_CDC________Fin__(ChaineA) \ { \ CALLs(free(ChaineA)); \ } /*************************************************************************************************************************************/ /* */ /* 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_CDC_Verifications(CHAR *ChaineA1,CHAR *ChaineA2) { Entier IndexCaractere; for (IndexCaractere=INDEX0 ; IndexCaractere <= CDC_INDEXN ; IndexCaractere++) { if (ACCES_CHAINE(ChaineA1,IndexCaractere) != ACCES_CHAINE(ChaineA2,IndexCaractere)) { fprintf(stderr ,"ERREUR(CDC) : chaine retablie ('0x%02x') # chaine a traiter ('0x%02x').\n" ,ACCES_CHAINE(ChaineA1,IndexCaractere) ,ACCES_CHAINE(ChaineA2,IndexCaractere) ); } else { } } } /*************************************************************************************************************************************/ /* */ /* F O N C T I O N D E C O M P R E S S I O N E T I N V E R S E P A R T I E L L E : */ /* */ /*************************************************************************************************************************************/ Entier CDC_NombreDePaquets; Entier CDC_NumeroDuPaquetCourant; #define D_CDC_CUMUL_Complexite_K__Partielle(cumuler,composante,valeur,ponderation) \ { \ if (cumuler == VRAI) \ { \ composante = valeur; \ Complexite_K__Partielle = Complexite_K__Partielle+(ponderation*composante); \ } \ else \ { \ } \ } double Complexite_K__Partielle; double Ponderation_Complexite_K__Partielle_BWT_IndexDeLaChaineAPermuterDansLaMatrice=1; double Complexite_K__Partielle_BWT_IndexDeLaChaineAPermuterDansLaMatrice; double Ponderation_Complexite_K__Partielle_HUF_IdentiteDuNoeudCourantDeLArbre=1; double Complexite_K__Partielle_HUF_IdentiteDuNoeudCourantDeLArbre; double Ponderation_Complexite_K__Partielle_HUF_Arbre=1; /* Une ponderation egale a : */ /* */ /* (NBITOC+1)/SIZEOF(Entier) */ /* */ /* semblerait raisonnable car, en effet, pour memoriser la definition de l'arbre, soit */ /* {ArbreCaracteresEnChaqueNoeud,ArbreChainageAGauche,ArbreChainageADroite}, il semble */ /* que 8+1=9 bits suffisent... */ double Complexite_K__Partielle_HUF_Arbre; double Ponderation_Complexite_K__Partielle_HUF_CodeBinaire=1; double Complexite_K__Partielle_HUF_CodeBinaire; double Ponderation_Complexite_K__Partielle_HUF_NombreDeBitsApresCodage=1; double Complexite_K__Partielle_HUF_NombreDeBitsApresCodage; double Complexite_K__Cumulee__=0; double Complexite_LD_Partielle; double Complexite_LD_Cumulee__=0; /* Mesures de 'K' et de 'LD'... */ char *BWT_Fichier_RLE_1; char *BWT_Fichier_BWT__; char *BWT_Fichier_RLE_2; char *BWT_Fichier_HUF__; /* Afin de pouvoir eventuellement conserver les resultats de {RLE_1,BWT,RLE_2,HUF}. */ #define GENERE_FICHIER(nom,chaine,longueur,mode) \ { \ if (nom != 0) \ /* Cas ou le nom est present dans 'argv[]', mais eventuellement vide : */ \ { \ if (strlen(nom) > 0) \ /* Cas ou le nom est present dans 'argv[]' et non vide : */ \ { \ FILE *Fdescripteur; \ \ Fdescripteur = fopen(nom,mode); \ /* Le 'mode' est soit "w" la premere fois afin d'initialiser a vide le fichier, puis */ \ /* "a" ensuite afin de cumuler le resultat des traitements des differents paquets... */ \ \ if (Fdescripteur >= 0) \ { \ fwrite(chaine,longueur,1,Fdescripteur); \ fclose(Fdescripteur); \ /* On notera le 20160520134742 que si : */ \ /* */ \ /* PaquetsBWT == TailleFichier (par exemple '$taille_Sud'=65536) */ \ /* */ \ /* alors, par exemple, la sequence : */ \ /* */ \ /* $xci/display$X A="BWT_FICHIER_BWT__" \ */ \ /* (...) \ */ \ /* SeuilLectureFichier="BWT_LongueurDeToutesLesChaines" */ \ /* */ \ /* permettra de visualiser la chaine 'BWT_ChaineP' courante dans le '$formatI' courant... */ \ } \ else \ { \ fprintf(stderr,"ERREUR(CDC) : Le fichier '%s' ne peut etre cree.\n",nom); \ } \ } \ else \ { \ /* Cas ou le nom est present dans 'argv[]', mais vide... */ \ } \ } \ else \ { \ /* Cas ou le nom est absent dans 'argv[]'... */ \ } \ } void F_MesureLocaleDe_K_EtDe_LD(CHAR *ChaineAMesurer,int LongueurDeChaineAMesurer) { /*************************************************************************************************************************************/ /* */ /* D E B U T D U P R O C E S S U S : */ /* */ /*************************************************************************************************************************************/ Complexite_K__Partielle=0; Complexite_LD_Partielle=0; D_CDC________Debut(CDC_ChaineA ,ChaineAMesurer,LongueurDeChaineAMesurer ); /*************************************************************************************************************************************/ /* */ /* C O M P R E S S I O N " R U N - L E N G T H E N C O D I N G " D I R E C T E ( 1 ) : */ /* */ /*************************************************************************************************************************************/ D_RLE________Debut(RLE_1_ChaineA ,CDC_ChaineA,LongueurDeChaineAMesurer ); RLE_1_LongueurChainesNonCompressees = RLE_LongueurChainesNonCompressees; D_Bclock("RLE_1_Directe"); D_CDC_EditionLongueur("RLE_1_Directe",RLE_1_LongueurChainesNonCompressees); D_RLE_DirecteDebut(RLE_1_ChaineC); D_RLE_Directe(RLE_1_ChaineC,RLE_1_LongueurChaineC ,RLE_1_ChaineA ); GENERE_FICHIER(BWT_Fichier_RLE_1,RLE_1_ChaineC,RLE_1_LongueurChaineC,"a"); D_RLE_DirecteFin__(); RLE_Directe_1_LongueurAvant = RLE_Directe_LongueurAvant; RLE_Directe_1_LongueurApres = RLE_Directe_LongueurApres; D_CDC_EditionLongueur("RLE_1_Directe",RLE_1_LongueurChaineC); D_Eclock("RLE_1_Directe"); /*************************************************************************************************************************************/ /* */ /* 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 : */ /* */ /*************************************************************************************************************************************/ D_BWT________Debut(BWT_ChaineA ,RLE_1_ChaineC,RLE_1_LongueurChaineC ); D_Bclock("BWT_Directe"); D_CDC_EditionLongueur("BWT_Directe",RLE_1_LongueurChaineC); D_BWT_DirecteDebut(BWT_ChaineP); D_BWT_Directe(BWT_ChaineP ,BWT_ChaineA ); GENERE_FICHIER(BWT_Fichier_BWT__,BWT_ChaineP,BWT_LongueurDeToutesLesChaines,"a"); D_BWT_DirecteFin__(); D_CDC_EditionLongueur("BWT_Directe",BWT_LongueurDeToutesLesChaines); D_Eclock("BWT_Directe"); D_CDC_CUMUL_Complexite_K__Partielle(BWT_Utiliser ,Complexite_K__Partielle_BWT_IndexDeLaChaineAPermuterDansLaMatrice ,BWT_SIZE_IndexDeLaChaineAPermuterDansLaMatrice ,Ponderation_Complexite_K__Partielle_BWT_IndexDeLaChaineAPermuterDansLaMatrice ); /*************************************************************************************************************************************/ /* */ /* C O M P R E S S I O N " R U N - L E N G T H E N C O D I N G " D I R E C T E ( 2 ) : */ /* */ /*************************************************************************************************************************************/ D_RLE________Debut(RLE_2_ChaineA ,BWT_ChaineP,BWT_LongueurDeToutesLesChaines ); RLE_2_LongueurChainesNonCompressees = RLE_LongueurChainesNonCompressees; D_Bclock("RLE_2_Directe"); D_CDC_EditionLongueur("RLE_2_Directe",RLE_2_LongueurChainesNonCompressees); D_RLE_DirecteDebut(RLE_2_ChaineC); D_RLE_Directe(RLE_2_ChaineC,RLE_2_LongueurChaineC ,RLE_2_ChaineA ); GENERE_FICHIER(BWT_Fichier_RLE_2,RLE_2_ChaineC,RLE_2_LongueurChaineC,"a"); D_RLE_DirecteFin__(); RLE_Directe_2_LongueurAvant = RLE_Directe_LongueurAvant; RLE_Directe_2_LongueurApres = RLE_Directe_LongueurApres; D_CDC_EditionLongueur("RLE_2_Directe",RLE_2_LongueurChaineC); D_Eclock("RLE_2_Directe"); /*************************************************************************************************************************************/ /* */ /* C O D A G E D E H U F F M A N D I R E C T : */ /* */ /*************************************************************************************************************************************/ { CHAR *HUF_ChaineB; CHAR *HUF_ChaineR; D_HUF________Debut(HUF_ChaineB ,HUF_ChaineR ,RLE_2_ChaineC,RLE_2_LongueurChaineC ); if (HUF_Utiliser == VRAI) { D_Bclock("HUF_Directe"); D_CDC_EditionLongueur("HUF_Directe",RLE_2_LongueurChaineC); F_HUF_Initialisations(); F_HUF_GenerationFrequences(RLE_2_ChaineC,RLE_2_LongueurChaineC); F_HUF_GenerationDeLArbre(); F_HUF_EditionDeLArbre(); F_HUF_ParcoursRecursifDeLArbre(HUF_RacineDeLArbre,0,0); F_HUF_CompactageDesCodesDeHuffman(); F_HUF_EditionDesCodesDeHuffman(); F_HUF_Directe(HUF_ChaineB ,RLE_2_ChaineC,RLE_2_LongueurChaineC ); #define HUF_NOMBRE_D_OCTETS_APRES_CODAGE \ DIVISION_PAR_EXCES(HUF_NombreDeBitsApresCodage,NBITOC) GENERE_FICHIER(BWT_Fichier_HUF__,HUF_ChaineB,HUF_NOMBRE_D_OCTETS_APRES_CODAGE,"a"); D_CDC_EditionLongueur("HUF_Directe",HUF_NOMBRE_D_OCTETS_APRES_CODAGE); D_Eclock("HUF_Directe"); D_CDC_CUMUL_Complexite_K__Partielle(HUF_Utiliser ,Complexite_K__Partielle_HUF_IdentiteDuNoeudCourantDeLArbre ,HUF_SIZE_IdentiteDuNoeudCourantDeLArbre ,Ponderation_Complexite_K__Partielle_HUF_IdentiteDuNoeudCourantDeLArbre ); D_CDC_CUMUL_Complexite_K__Partielle(HUF_Utiliser ,Complexite_K__Partielle_HUF_Arbre ,HUF_SIZE_Arbre ,Ponderation_Complexite_K__Partielle_HUF_Arbre ); D_CDC_CUMUL_Complexite_K__Partielle(HUF_Utiliser ,Complexite_K__Partielle_HUF_CodeBinaire ,HUF_SIZE_CodeBinaire ,Ponderation_Complexite_K__Partielle_HUF_CodeBinaire ); } else { mEGAL(HUF_NombreDeBitsApresCodage,MUL2(RLE_2_LongueurChaineC,NBITOC)); } D_CDC_CUMUL_Complexite_K__Partielle(VRAI ,Complexite_K__Partielle_HUF_NombreDeBitsApresCodage ,HUF_NombreDeBitsApresCodage ,Ponderation_Complexite_K__Partielle_HUF_NombreDeBitsApresCodage ); INITIALISATION_DES_COMPTEURS; /* Cette (re-)initialisation des compteurs doit etre faite ici car, en effet, certains */ /* d'entre-eux ont ete incrementes dans la phase directe qui precede, en particulier dans */ /* 'v $xrC/CompressionDeCompression_BurrowsWheeler.01$vv$I TriRapideDeLEnsembleDesChaines'. */ if (HUF_Utiliser == VRAI) { /*************************************************************************************************************************************/ /* */ /* C O D A G E D E H U F F M A N I N V E R S E : */ /* */ /*************************************************************************************************************************************/ D_Bclock("HUF_Inverse"); D_CDC_EditionLongueur("HUF_Inverse",DIVISION_PAR_EXCES(HUF_NombreDeBitsApresCodage,NBITOC)); CALL(F_HUF_DeCompactageDesCodesDeHuffman()); CALL(F_HUF_Inverse(HUF_ChaineR ,HUF_ChaineB ,HUF_NombreDeBitsApresCodage ) ); D_CDC_EditionLongueur("HUF_Inverse",HUF_NombreDOctetsApresDecodage); D_Eclock("HUF_Inverse"); F_HUF_Verifications(RLE_2_ChaineC,RLE_2_LongueurChaineC ,HUF_ChaineR,HUF_NombreDOctetsApresDecodage ); if (CDC_EditerCDCBits == VRAI) { printf("\nLes %"For10" octets (=%"For10" bits) ont ete compactes " ,(Entier)LongueurDeChaineAMesurer ,((Entier)LongueurDeChaineAMesurer)*NBITOC ); printf("en %"For10" octets (=%"For10" bits).\n" ,DIVISION_PAR_EXCES(HUF_NombreDeBitsApresCodage,NBITOC) ,HUF_NombreDeBitsApresCodage ); } else { } } else { Entier IndexCaractere; DoIn(IndexCaractere,INDEX0,NombreVersIndex(RLE_2_LongueurChaineC)) { mEGAL(ACCES_CHAINE(HUF_ChaineR,IndexCaractere),ACCES_CHAINE(RLE_2_ChaineC,IndexCaractere)); /* AETTENTION : ceci est obligatoire car, en effet, le 'D_HUF________Debut(...)' a remis */ /* 'HUF_ChaineR' a zero... */ } EDoI } /*************************************************************************************************************************************/ /* */ /* C O M P R E S S I O N " R U N - L E N G T H E N C O D I N G " I N V E R S E ( 2 ) : */ /* */ /*************************************************************************************************************************************/ D_Bclock("RLE_2_Inverse"); D_CDC_EditionLongueur("RLE_2_Inverse",HUF_NombreDOctetsApresDecodage); if (HUF_Utiliser == VRAI) { if (HUF_NombreDOctetsApresDecodage != RLE_2_LongueurChaineC) { fprintf(stderr ,"ERREUR(CDC) : la longueur avant 'RLE_2_Inverse' (%d) est mauvaise (#%d).\n" ,HUF_NombreDOctetsApresDecodage ,RLE_2_LongueurChaineC ); } else { } } else { } RLE_LongueurChainesNonCompressees = RLE_2_LongueurChainesNonCompressees; D_RLE_InverseDebut(RLE_2_ChaineR); D_RLE_Inverse(RLE_2_ChaineR ,HUF_ChaineR,RLE_2_LongueurChaineC ); RLE_LongueurChainesNonCompressees = RLE_2_LongueurChainesNonCompressees; RLE_Inverse_2_LongueurAvant = RLE_Inverse_LongueurAvant; RLE_Inverse_2_LongueurApres = RLE_Inverse_LongueurApres; D_CDC_EditionLongueur("RLE_2_Inverse",RLE_2_LongueurChainesNonCompressees); D_Eclock("RLE_2_Inverse"); F_RLE_Verifications(RLE_2_ChaineR,RLE_2_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 I N V E R S E : */ /* */ /*************************************************************************************************************************************/ D_Bclock("BWT_Inverse"); D_CDC_EditionLongueur("BWT_Inverse",BWT_LongueurDeToutesLesChaines); D_BWT_InverseDebut_02(BWT_ChaineR); D_BWT_Inverse_02(BWT_ChaineR ,RLE_2_ChaineR ); D_CDC_EditionLongueur("BWT_Inverse",BWT_LongueurDeToutesLesChaines); D_Eclock("BWT_Inverse"); F_BWT_Verifications(BWT_ChaineR ,BWT_ChaineA ); /*************************************************************************************************************************************/ /* */ /* C O M P R E S S I O N " R U N - L E N G T H E N C O D I N G " I N V E R S E ( 1 ) : */ /* */ /*************************************************************************************************************************************/ D_Bclock("RLE_1_Inverse"); D_CDC_EditionLongueur("RLE_1_Inverse",RLE_1_LongueurChaineC); RLE_LongueurChainesNonCompressees = RLE_1_LongueurChainesNonCompressees; D_RLE_InverseDebut(RLE_1_ChaineR); D_RLE_Inverse(RLE_1_ChaineR ,BWT_ChaineR,RLE_1_LongueurChaineC ); RLE_Inverse_1_LongueurAvant = RLE_Inverse_LongueurAvant; RLE_Inverse_1_LongueurApres = RLE_Inverse_LongueurApres; D_CDC_EditionLongueur("RLE_1_Inverse",RLE_LongueurChainesNonCompressees); D_Eclock("RLE_1_Inverse"); D_HUF________Fin__(HUF_ChaineB,HUF_ChaineR); } F_RLE_Verifications(RLE_1_ChaineR,RLE_1_ChaineA); /*************************************************************************************************************************************/ /* */ /* F I N D U P R O C E S S U S : */ /* */ /*************************************************************************************************************************************/ F_CDC_Verifications(ChaineAMesurer,RLE_1_ChaineR); D_CDC_VerificationsDesLongueurs(VRAI ,"DEBUT --> RLE1" ,LongueurDeChaineAMesurer ,RLE_Directe_1_LongueurAvant); D_CDC_VerificationsDesLongueurs(BWT_Utiliser,"RLE1 --> BWT " ,RLE_Directe_1_LongueurApres ,BWT_Directe_LongueurAvant); D_CDC_VerificationsDesLongueurs(BWT_Utiliser,"BWT --> RLE2" ,BWT_Directe_LongueurApres ,RLE_Directe_2_LongueurAvant); D_CDC_VerificationsDesLongueurs(HUF_Utiliser,"RLE2 --> HUF " ,RLE_Directe_2_LongueurApres ,HUF_Codage_LongueurAvant); D_CDC_VerificationsDesLongueurs(HUF_Utiliser,"HUF --> HUF " ,HUF_Codage_LongueurApres ,HUF_Decodage_LongueurAvant); D_CDC_VerificationsDesLongueurs(HUF_Utiliser,"HUF --> RLE2" ,HUF_Decodage_LongueurApres ,RLE_Inverse_2_LongueurAvant); D_CDC_VerificationsDesLongueurs(BWT_Utiliser,"RLE2 --> BWT " ,RLE_Inverse_2_LongueurApres ,BWT_Inverse_LongueurAvant); D_CDC_VerificationsDesLongueurs(BWT_Utiliser,"BWT --> RLE1" ,BWT_Inverse_LongueurApres ,RLE_Inverse_1_LongueurAvant); D_CDC_VerificationsDesLongueurs(VRAI ,"RLE1 --> FIN " ,RLE_Inverse_1_LongueurApres ,LongueurDeChaineAMesurer); D_CDC_VerificationsDesLongueurs(VRAI ,"RLE1 --> RLE1" ,RLE_Directe_1_LongueurAvant ,RLE_Inverse_1_LongueurApres); D_CDC_VerificationsDesLongueurs(BWT_Utiliser,"BWT --> BWT " ,BWT_Directe_LongueurAvant ,BWT_Inverse_LongueurApres); D_CDC_VerificationsDesLongueurs(HUF_Utiliser,"HUF --> HUF " ,HUF_Codage_LongueurAvant ,HUF_Decodage_LongueurApres); D_CDC_VerificationsDesLongueurs(VRAI ,"RLE2 --> RLE2" ,RLE_Directe_2_LongueurAvant ,RLE_Inverse_2_LongueurApres); D_RLE_InverseFin__(RLE_2_ChaineR ,RLE_2_ChaineC ); D_RLE_InverseFin__(RLE_1_ChaineR ,RLE_1_ChaineC ); D_BWT_InverseFin___02(BWT_ChaineR ,BWT_ChaineP ); D_RLE________Fin__(RLE_2_ChaineA); D_BWT________Fin__(BWT_ChaineA); D_RLE________Fin__(RLE_1_ChaineA); D_CDC________Fin__(CDC_ChaineA); Complexite_K__Cumulee__ = Complexite_K__Cumulee__+Complexite_K__Partielle; CUMUL_DES_COMPTEURS(Complexite_LD_Partielle); Complexite_LD_Cumulee__ = Complexite_LD_Cumulee__+Complexite_LD_Partielle; if (CDC_EditerUniquement_K_et_LD_Cumulees == VRAI) { } else { if (CDC_NombreDePaquets > 1) { printf("paquet courant : %d/%d\n",CDC_NumeroDuPaquetCourant,CDC_NombreDePaquets); } else { } if (CDC_EditerLesComposantesDes_K_Partielles == VRAI) { printf("K(Partielle/BWT_IndexDeLaChaineAPermuterDansLaMatrice)..=%12.0f (%s)\n" ,floor(CONVERSION_BITS_OCTET(Complexite_K__Partielle_BWT_IndexDeLaChaineAPermuterDansLaMatrice)) ,BITS_OU_OCTETS ); printf("K(Partielle/HUF_IdentiteDuNoeudCourantDeLArbre).........=%12.0f (%s)\n" ,floor(CONVERSION_BITS_OCTET(Complexite_K__Partielle_HUF_IdentiteDuNoeudCourantDeLArbre)) ,BITS_OU_OCTETS ); printf("K(Partielle/HUF_Arbre)..................................=%12.0f (%s)\n" ,floor(CONVERSION_BITS_OCTET(Complexite_K__Partielle_HUF_Arbre)) ,BITS_OU_OCTETS ); printf("K(Partielle/HUF_CodeBinaire)............................=%12.0f (%s)\n" ,floor(CONVERSION_BITS_OCTET(Complexite_K__Partielle_HUF_CodeBinaire)) ,BITS_OU_OCTETS ); printf("K(Partielle/HUF_NombreDeBitsApresCodage)................=%12.0f (%s)\n" ,floor(CONVERSION_BITS_OCTET(Complexite_K__Partielle_HUF_NombreDeBitsApresCodage)) ,BITS_OU_OCTETS ); } else { } printf("K(Partielle)=%12.0f (%s) K(Cumulee)=%12.0f (%s)" ,floor(CONVERSION_BITS_OCTET(Complexite_K__Partielle)) ,BITS_OU_OCTETS ,floor(CONVERSION_BITS_OCTET(Complexite_K__Cumulee__)) ,BITS_OU_OCTETS ); printf(" "); printf("LD(Partielle)=%12.0f (instructions) LD(Cumulee)=%12.0f (instructions)\n" ,Complexite_LD_Partielle,Complexite_LD_Cumulee__ ); } } /*************************************************************************************************************************************/ /* */ /* F O N C T I O N D E C O M P R E S S I O N E T I N V E R S E G L O B A L E : */ /* */ /*************************************************************************************************************************************/ void F_MesureDe_K_EtDe_LD_Globale(CHAR *ChaineAMesurer,int LongueurDeChaineAMesurer) { CHAR *SousChaineAMesurer=ChaineAMesurer; Entier NombreDOctetsEncoreATraiter=LongueurDeChaineAMesurer; CDC_NombreDePaquets=DIVISION_PAR_EXCES(LongueurDeChaineAMesurer,CDC_TailleDesPaquets); CDC_NumeroDuPaquetCourant=1; Complexite_K__Cumulee__=0; Complexite_LD_Cumulee__=0; Complexite_K__Cumulee__ = Complexite_K__Cumulee__+SIZEOF(CDC_TailleDesPaquets); Complexite_K__Cumulee__ = Complexite_K__Cumulee__+SIZEOF(BWT_TailleDesPaquets); while (NombreDOctetsEncoreATraiter > 0) { Entier LongueurDeSousChaineAMesurer=MIN2(CDC_TailleDesPaquets,NombreDOctetsEncoreATraiter); F_MesureLocaleDe_K_EtDe_LD(SousChaineAMesurer,LongueurDeSousChaineAMesurer); SousChaineAMesurer = SousChaineAMesurer+LongueurDeSousChaineAMesurer; NombreDOctetsEncoreATraiter = NombreDOctetsEncoreATraiter-LongueurDeSousChaineAMesurer; CDC_NumeroDuPaquetCourant++; } if (CDC_MettreEnConcurrenceLesDifferentesOptions == FAUX) { printf("K.................................... = %.0f (%s)\n" ,floor(CONVERSION_BITS_OCTET(Complexite_K__Cumulee__)) ,BITS_OU_OCTETS ); printf("LD................................... = %.0f (instructions)\n" ,Complexite_LD_Cumulee__ ); } else { } }