/*************************************************************************************************************************************/
/*                                                                                                                                   */
/*        O P E R A T I O N S   A R I T H M E T I Q U E S   S U R   D E S   F I C H I E R S  :                                       */
/*                                                                                                                                   */
/*                                                                                                                                   */
/*        Author of '$xrv/ARITHMET.1g$I' :                                                                                           */
/*                                                                                                                                   */
/*                    Jean-Francois COLONNA (LACTAMME, 20060215103111).                                                              */
/*                                                                                                                                   */
/*************************************************************************************************************************************/

/*===================================================================================================================================*/
/*************************************************************************************************************************************/
/*                                                                                                                                   */
/*        R E C U P E R A T I O N   D ' U N   F I C H I E R   " L I S T E "  :                                                       */
/*                                                                                                                                   */
/*************************************************************************************************************************************/
#define   PREMIER_ELEMENT_D_UNE_LISTE_VERSION_PREMIER_ELEMENT_D_UN_FICHIER_0                                                            \
                                        /* Afin de faire la difference entre les programmes dont les premiers elements sont          */ \
                                        /* numerotes 'PREMIER_POINT_DES_LISTES' ('v $xrv/particule.10$K') et ceux dont les premiers  */ \
                                        /* elements sont numerotes 'PREMIER_ELEMENT_D_UN_FICHIER' ('v $xrv/distance.02$K').          */

/*===================================================================================================================================*/
/*************************************************************************************************************************************/
/*                                                                                                                                   */
/*        V A L E U R S   I M P L I C I T E S   D E S   P A R A M E T R E S  :                                                       */
/*                                                                                                                                   */
/*************************************************************************************************************************************/
#nodefine NOMBRE_D_ELEMENTS                                                                                                             \
                    TRI_DIMENSIONNEL
#define   NOMBRE_D_ELEMENTS                                                                                                             \
                    ZERO
                                        /* Nombre d'elements attendus a priori dans les fichiers. Le passage de 'TRI_DIMENSIONNEL'   */
                                        /* a 'ZERO' a eu lieu le 19991217121738 afin de permettre la determination automatique de    */
                                        /* 'nombre_d_elements'...                                                                    */

#define   UTILISER_LE_FORMAT_EXPONENTIEL                                                                                                \
                    VRAI                                                                                                                \
                                        /* Faut-il sortir en format "%g" ('VRAI') ou en format "%f" ('FAUX'). Ceci a ete introduit   */ \
                                        /* afin de permettre d'extraire la partie entiere d'un nombre en supprimant simplement tout  */ \
                                        /* ce qui suit le point decimal avec '$SE'...                                                */

/*===================================================================================================================================*/
/*************************************************************************************************************************************/
/*                                                                                                                                   */
/*        D E F I N I T I O N   D E S   F I C H I E R S  :                                                                           */
/*                                                                                                                                   */
/*************************************************************************************************************************************/
#define   EN_TETE_DANS_LE_FICHIER                                                                                                       \
                    ZERO
#define   SAUT_DANS_LE_FICHIER                                                                                                          \
                    ZERO
DEFV(Local,DEFV(Positive,INIT(en_tete_dans_le_fichier_des_valeurs,EN_TETE_DANS_LE_FICHIER)));
DEFV(Local,DEFV(Positive,INIT(saut_dans_le_fichier_des_valeurs,SAUT_DANS_LE_FICHIER)));
                                        /* Definition du nombre de valeurs a sauter entre deux valeurs recuperees du fichier de      */
                                        /* coordonnees et de valeurs. L'amplitude du saut sur le debut du fichier ("en_tete") a      */
                                        /* ete introduite le 20021104171432 par symetrie avec '$xrv/particule.11$I 20021104161517'.  */

#define   PROCESS_ARGUMENTS_DE_DEFINITION_DES_FICHIERS_01                                                                               \
                                        /* La partie "_01" du nom 'PROCESS_ARGUMENTS_DE_DEFINITION_DES_FICHIERS_01' est choisie      */ \
                                        /* en harmonie avec le nom de la procedure 'lTRANSFORMAT_01(...)' qui lui est associee...    */ \
                    Bblock                                                                                                              \
                                                                                                                                        \
                    DEBUT_D_IMBRICATION_DES_____gPROCESS_PARAMETRE_____SECONDAIRES;                                                     \
                                        /* Introduit le 20060208111712 ('v $xig/fonct$vv$DEF _IMBRICATION_DES__gPROCESS_PARAMETRE'). */ \
                                                                                                                                        \
                    PROCESS_ARGUMENT_I("en_tete=",en_tete_dans_le_fichier_des_valeurs                                                   \
                                      ,BLOC(VIDE;)                                                                                      \
                                      ,BLOC(PRINT_AVERTISSEMENT("'saut=' doit etre defini avant toute entree de fichiers");)            \
                                       );                                                                                               \
                                        /* ATTENTION : la recuperation de 'en_tete_dans_le_fichier_des_valeurs' doit                 */ \
                                        /* preceder les 'PROCESS_ARGUMENT_C(...)' qui suivent car ils l'utilisent.                   */ \
                    PROCESS_ARGUMENT_I("saut=",saut_dans_le_fichier_des_valeurs                                                         \
                                      ,BLOC(VIDE;)                                                                                      \
                                      ,BLOC(PRINT_AVERTISSEMENT("'saut=' doit etre defini avant toute entree de fichiers");)            \
                                       );                                                                                               \
                                        /* ATTENTION : la recuperation de 'saut_dans_le_fichier_des_valeurs' doit preceder           */ \
                                        /* les 'PROCESS_ARGUMENT_C(...)' qui suivent car ils l'utilisent.                            */ \
                                                                                                                                        \
                    FIN___D_IMBRICATION_DES_____gPROCESS_PARAMETRE_____SECONDAIRES;                                                     \
                                        /* Introduit le 20060208111712 ('v $xig/fonct$vv$DEF _IMBRICATION_DES__gPROCESS_PARAMETRE'). */ \
                                                                                                                                        \
                    Eblock                                                                                                              \
                                        /* Introduit le 20021104173637 pour faciliter la mise a jour de differents '$K' suite        */ \
                                        /* a l'introduction du nouveau parametre 'en_tete_dans_le_fichier_des_valeurs'...            */

#TestADef NOMBRE_MAXIMAL_D_ELEMENTS_DANS_LE_FICHIER                                                                                     \
                    GRO2(MILLION)                                                                                                       \
                                        /* Nombre maximal d'elements dans les fichiers (valeur tres arbitraire...).                  */ \
                                        /*                                                                                           */ \
                                        /* Le 20060210172552, ce nombre est passe de 'MILLION' a 'GRO2(MILLION)' a cause de          */ \
                                        /* 'v $xiird/.PEA3.3.11.$U'...                                                               */

DEFV(Local,DEFV(Positive,INIT(nombre_maximal_d_elements_dans_le_fichier,NOMBRE_MAXIMAL_D_ELEMENTS_DANS_LE_FICHIER)));

#define   gGENERATION_D_UN_FICHIER_nom(fichier_des_valeurs)                                                                             \
                    DEFV(Local,DEFV(CHAR,INIT(POINTERc(fichier_des_valeurs),NOM_PIPE_Local)));
#define   gGENERATION_D_UN_FICHIER_liste(liste_des_valeurs)                                                                             \
                    DEFV(Local,DEFV(Positive,INIT(liste_des_valeurs`____nombre_d_elements,NOMBRE_D_ELEMENTS)));                         \
                                        /* Il est plus logique de definir 'nombre_d_elements' a partir de 'liste_des_valeurs' qu'a   */ \
                                        /* l'aide de 'fichier_des_valeurs' car, en effet, ainsi cette variable specifique a chaque   */ \
                                        /* fichier pourra etre utilisee dans 'gELEMENT_DU_FICHIER(...)' si besoin est...             */ \
                    DEFV(Local,DEFV(Float,DdTb1(POINTERf                                                                                \
                                               ,liste_des_valeurs                                                                       \
                                               ,nombre_maximal_d_elements_dans_le_fichier                                               \
                                               ,ADRESSE_NON_ENCORE_DEFINIE                                                              \
                                                )                                                                                       \
                                    )                                                                                                   \
                         );

#define   gGENERATION_D_UN_FICHIER(fichier_des_valeurs,liste_des_valeurs)                                                               \
                    gGENERATION_D_UN_FICHIER_nom(fichier_des_valeurs);                                                                  \
                    gGENERATION_D_UN_FICHIER_liste(liste_des_valeurs);
                                        /* Generation en memoire d'un fichier sous la forme {nom,liste}.                             */
                                        /*                                                                                           */
                                        /* L'allocation dynamique de 'liste_des_valeurs' a ete introduite le 20060213182327...       */
                                        /*                                                                                           */
                                        /* Le nombre specifique d'elements de chauqe fichier a ete introduit le 20240930155301...    */

#define   gELEMENT_DU_FICHIER(liste_des_valeurs,index)                                                                                  \
                    IdTb1(liste_des_valeurs                                                                                             \
                         ,INDX(index,PREMIER_ELEMENT_D_UN_FICHIER)                                                                      \
                         ,nombre_maximal_d_elements_dans_le_fichier                                                                     \
                          )                                                                                                             \
                                        /* Acces a un element courant des fichiers.                                                  */ \
                                        /*                                                                                           */ \
                                        /* ATTENTION a ne pas confondre :                                                            */ \
                                        /*                                                                                           */ \
                                        /* 1-'ACCES_LISTE(...)', pour lequel le premier element vaut :                               */ \
                                        /*                                                                                           */ \
                                        /*                  PREMIER_POINT_DES_LISTES=PREMIER_POINT=PREMIERE_ITERATION_D_UN_Komp=UN   */ \
                                        /*                                                                                           */ \
                                        /* qui est donc adapte a une gestion de type 'Komp(...)' ou le premier element est defini    */ \
                                        /* implicitement (et vaut donc 'UN'), et                                                     */ \
                                        /*                                                                                           */ \
                                        /* 2-'gELEMENT_DU_FICHIER(...)', pour lequel le premier element vaut :                       */ \
                                        /*                                                                                           */ \
                                        /*                  PREMIER_ELEMENT_D_UN_FICHIER=INDEX0=ZERO                                 */ \
                                        /*                                                                                           */ \
                                        /* qui ne peut utiliser 'Komp(...)' et demande donc une gestion de type 'DoIn(...)' en       */ \
                                        /* precisant le premier element en tant qu'argument du 'DoIn(...)' (et valant donc 'ZERO').  */

#define   glTRANSFORMAT_01__nombre_d_elements(nombre_effectif_d_elements,editer_les_messages_d_erreur_des_fichiers)                     \
                    Bblock                                                                                                              \
                    DEFV(Int,INIT(taille_du_fichier_des_valeurs_effectif,UNDEF));                                                       \
                    EGAL(Fsize_fichier_____compter_les_lignes,COMPTER_LES_LIGNES_DANS_Fsize_fichier);                                   \
                    CALS(Fsize_fichier(fichier_des_valeurs_effectif                                                                     \
                                      ,ADRESSE(taille_du_fichier_des_valeurs_effectif)                                                  \
                                      ,editer_les_messages_d_erreur_des_fichiers                                                        \
                                       )                                                                                                \
                         );                                                                                                             \
                    EGAL(nombre_effectif_d_elements                                                                                     \
                        ,DIVI(SOUS(Fsize_fichier_____nombre_de_lignes,en_tete_dans_le_fichier_des_valeurs)                              \
                             ,TRPU(saut_dans_le_fichier_des_valeurs)                                                                    \
                              )                                                                                                         \
                         );                                                                                                             \
                    Eblock                                                                                                              \
                                        /* Introduit le 20240930155301...                                                            */

#define   glTRANSFORMAT_01(fichier_des_valeurs,liste_des_valeurs,valeur_par_defaut,sequence_allocation_eventuelle)                      \
                    Bblock                                                                                                              \
                    DEFV(CHAR,INIC(POINTERc(fichier_des_valeurs_effectif),NOM_UNDEF));                                                  \
                                        /* Nom du fichier a lire (soit un "vrai" fichier, soit un "pipe").                           */ \
                                                                                                                                        \
                    Test(I3OU(IFEQ_chaine(fichier_des_valeurs,C_VIDE)                                                                   \
                             ,IFEQ_chaine(fichier_des_valeurs,NOM_PIPE)                                                                 \
                             ,IFEQ_chaine(fichier_des_valeurs,NOM_PIPE_Local)                                                           \
                              )                                                                                                         \
                         )                                                                                                              \
                                        /* ATTENTION, j'ai decouvert le 20000207110651 qu'il n'etait pas equivalent de laisser       */ \
                                        /* a un argument 'fichier_des_valeurs' sa valeur implicite ('NOM_PIPE_Local'), et de lui     */ \
                                        /* donner cette valeur, par exemple a l'aide de :                                            */ \
                                        /*                                                                                           */ \
                                        /*                  fichier="="                                                              */ \
                                        /*                                                                                           */ \
                                        /* (en supposant que l'argument s'appelle "fichier="). En effet, dans le premier cas         */ \
                                        /* (valeur implicite conservee), la procedure 'lTRANSFORMAT_01(...)' n'est pas appelee       */ \
                                        /* par 'PROCESF_ARGUMENT_C(...)' puisque l'argument courant n'est pas rencontre. Alors,      */ \
                                        /* dans ce cas, la gestion du "pipe" qui suit n'est pas effectuee. Donc, moralite, pour      */ \
                                        /* acceder proprement au "pipe", il faut que cela soit demande explicitement...              */ \
                                        /*                                                                                           */ \
                                        /* Cela est vrai aussi, malheureusement, de l'evaluation automatique de 'nombre_d_elements'. */ \
                                        /*                                                                                           */ \
                                        /* Cela a donc conduit a l'introduction de 'v $xig/fonct$vv$DEF gPROCESS_PARAMETRE' et de    */ \
                                        /* 'v $xig/fonct$vv$DEF PROCESF_ARGUMENT_C'. Malheureusement, le 20000207173145 j'ai         */ \
                                        /* decouvert que cela etait insuffisant ('v $xig/fonct$vv$DEF 20000207173145'). Donc, pour   */ \
                                        /* "connecter" un fichier au "pipe", il faudra malheureusement ecrire quelque chose du       */ \
                                        /* type :                                                                                    */ \
                                        /*                                                                                           */ \
                                        /*                  fichier="="                                                              */ \
                                        /*                                                                                           */ \
                                        /* si l'on veut que les arguments du meme type et qui sont absents, correspondent a leur     */ \
                                        /* valeur par defaut. On etait donc en presence de deux desirs contradictoires :             */ \
                                        /*                                                                                           */ \
                                        /*                  1-initialiser un fichier avec la valeur par defaut lorsqu'il est         */ \
                                        /*                  absent en tant qu'argument,                                              */ \
                                        /*                                                                                           */ \
                                        /*                  1-"connecter" un fichier au "pipe" (valeur par defaut de son nom)        */ \
                                        /*                  lorsqu'il est absent en tant qu'argument.                                */ \
                                        /*                                                                                           */ \
                                        /* Ainsi, malgre les initialisations (dans 'gGENERATION_D_UN_FICHIER(...)'), l'absence d'un  */ \
                                        /* fichier (en tant qu'argument) impliquera l'initialisation de tous ses elements avec sa    */ \
                                        /* valeur par defaut, meme si donc son nom vaut 'NOM_PIPE_Local'...                          */ \
                         Bblock                                                                                                         \
                         EGAL(fichier_des_valeurs_effectif,generation_d_un_nom_absolu_dans_xT_temporaire(C_VIDE));                      \
                                        /* Generation du nom du fichier temporaire correspondant au "pipe".                          */ \
                                                                                                                                        \
                         EXECUTION_D_UNE_SUITE_DE_COMMANDES_SOUS_SH(chain_Aconcaten3(Gvar("CA")                                         \
                                                                                    ,C_SH__REDIRECTION_FICHIER                          \
                                                                                    ,fichier_des_valeurs_effectif                       \
                                                                                     )                                                  \
                                                                    );                                                                  \
                                        /* Transfert du "pipe" dans le fichier temporaire...                                         */ \
                                        /*                                                                                           */ \
                                        /* Passage de 'C_REDIRECTION_FICHIER' a 'C_SH__REDIRECTION_FICHIER' le 20111117082138...     */ \
                         Eblock                                                                                                         \
                    ATes                                                                                                                \
                         Bblock                                                                                                         \
                         EGAL(fichier_des_valeurs_effectif,chain_Acopie(fichier_des_valeurs));                                          \
                                        /* Le fichier utilise est le fichier argument...                                             */ \
                         Eblock                                                                                                         \
                    ETes                                                                                                                \
                                                                                                                                        \
                    Test(IZEQ(nombre_d_elements))                                                                                       \
                                        /* Dispositif introduit le 19991217121738 pour permettre la determination automatique        */ \
                                        /* de 'nombre_d_elements' lorsque la valeur qui lui est donnee est nulle...                  */ \
                         Bblock                                                                                                         \
                         glTRANSFORMAT_01__nombre_d_elements(nombre_d_elements                                                          \
                                                            ,EDITER_LES_MESSAGES_D_ERREUR_DES_FICHIERS                                  \
                                                             );                                                                         \
                                        /* Determination automatique de 'nombre_d_elements' que le fichier soit un "vrai" fichier    */ \
                                        /* ou bien un "pipe"...                                                                      */ \
                                        /*                                                                                           */ \
                                        /* ATTENTION, cela ne fonctionne pas evidemment dans le cas ou le nom du fichier est en fait */ \
                                        /* une valeur numerique ('LE_NOM_DU_FICHIER_EST_CONVERTISSABLE_EN_UNE_VALEUR_NUMERIQUE').    */ \
                                        /* Dans ce cas et lorsque le programme correspondant recoit comme Arguments plusieurs noms   */ \
                                        /* de fichier, la solution consiste a mettre en premier les "vrais" fichiers, puis derriere  */ \
                                        /* les "faux" fichiers (dont les noms sont des valeurs numeriques). Ainsi :                  */ \
                                        /*                                                                                           */ \
                                        /*                  COMMANDE  ne=0 fichier1=1234 fichier2=NOM                                */ \
                                        /*                                                                                           */ \
                                        /* ne fonctionnera pas car 'Fsize_fichier(...)' va vouloir ouvrir le fichier dont le nom     */ \
                                        /* est '1234', alors que :                                                                   */ \
                                        /*                                                                                           */ \
                                        /*                  COMMANDE  ne=0 fichier1=NOM fichier2=1234                                */ \
                                        /*                                                                                           */ \
                                        /* ou encore :                                                                               */ \
                                        /*                                                                                           */ \
                                        /*                  COMMANDE  ne=0 fichier1="=" fichier2=1234                                */ \
                                        /*                                                                                           */ \
                                        /* fonctionneront car la determination de 'nombre_d_elements' aura lieu sur 'fichier1' et    */ \
                                        /* donc sur un vrai fichier (de nom 'NOM' ou le "pipe").                                     */ \
                                        /*                                                                                           */ \
                                        /* Le 20110324100311 (c'est-a-dire un peu tardivement !) ont ete pris en compte dans le      */ \
                                        /* calcul de 'nombre_d_elements' des variables 'en_tete_dans_le_fichier_des_valeurs' et      */ \
                                        /* 'saut_dans_le_fichier_des_valeurs'...                                                     */ \
                         Eblock                                                                                                         \
                    ATes                                                                                                                \
                         Bblock                                                                                                         \
                         Eblock                                                                                                         \
                    ETes                                                                                                                \
                                                                                                                                        \
                    glTRANSFORMAT_01__nombre_d_elements(liste_des_valeurs`____nombre_d_elements                                         \
                                                       ,NE_PAS_EDITER_LES_MESSAGES_D_ERREUR_DES_FICHIERS                                \
                                                        );                                                                              \
                                        /* Mise a jour specifique et systematique introduite le 20240930155301...                    */ \
                                        /*                                                                                           */ \
                                        /* Je note le 20241005203934 que cette instruction rend impossible la conversion d'un        */ \
                                        /* nom de fichier en valeur numerique. On a alors :                                          */ \
                                        /*                                                                                           */ \
                                        /*                  liste_des_valeurs`____nombre_d_elements == 0                             */ \
                                        /*                                                                                           */ \
                                        /* En fait, il apparait que tout se passe bien, sauf le message d'erreur, d'ou sa            */ \
                                        /* suppression...                                                                            */ \
                                                                                                                                        \
                    BLOC(sequence_allocation_eventuelle);                                                                               \
                                        /* Allocation memoire ou validation de la taille...                                          */ \
                                                                                                                                        \
                    CALS(Fload_fichier_formatte_Float(fichier_des_valeurs_effectif                                                      \
                                                     ,liste_des_valeurs                                                                 \
                                                     ,nombre_d_elements                                                                 \
                                                     ,en_tete_dans_le_fichier_des_valeurs                                               \
                                                     ,saut_dans_le_fichier_des_valeurs                                                  \
                                                     ,VRAI                                                                              \
                                                     ,valeur_par_defaut                                                                 \
                                                     ,LE_NOM_DU_FICHIER_EST_CONVERTISSABLE_EN_UNE_VALEUR_NUMERIQUE                      \
                                                      )                                                                                 \
                         );                                                                                                             \
                                        /* Et enfin, lecture du fichier...                                                           */ \
                                                                                                                                        \
&define   __ParaVal liste_des_valeurs&&&                                                                                                \
&define   __ParaInd PREMIER_ELEMENT_D_UN_FICHIER&&&                                                                                     \
&define   __ParaLon nombre_d_elements&&&                                                                                                \
&define   __ParaTyp TYPE_FORMAT_FLOT&&&                                                                                                 \
&define   __ParaFor FORMAT_FLOT_EDITION&&&                                                                                              \
                                                                                                                                        \
                    Test(IFEQ_chaine(fichier_des_valeurs_effectif,fichier_des_valeurs))                                                 \
                         Bblock                                                                                                         \
                                        /* Cas ou il s'agissait d'un "vrai" fichier...                                               */ \
                         Eblock                                                                                                         \
                    ATes                                                                                                                \
                         Bblock                                                                                                         \
                                        /* Cas ou il s'agissait d'un "pipe"...                                                       */ \
                         CALS(Idelete_fichier(fichier_des_valeurs_effectif));                                                           \
                                        /* Destruction du fichier temporaire.                                                        */ \
                         Eblock                                                                                                         \
                    ETes                                                                                                                \
                                                                                                                                        \
                    CALZ_FreCC(fichier_des_valeurs_effectif);                                                                           \
                                        /* Liberation de l'espace contenant le nom du fichier effectif.                              */ \
                    Eblock                                                                                                              \
                                        /* Recuperation d'un fichier contenant une liste. ATTENTION, le 19980317091800, le           */ \
                                        /* parametre :                                                                               */ \
                                        /*                                                                                           */ \
                                        /*                  LE_NOM_DU_FICHIER_N_EST_PAS_CONVERTISSABLE_EN_UNE_VALEUR_NUMERIQUE       */ \
                                        /*                                                                                           */ \
                                        /* est devenu :                                                                              */ \
                                        /*                                                                                           */ \
                                        /*                  LE_NOM_DU_FICHIER_EST_CONVERTISSABLE_EN_UNE_VALEUR_NUMERIQUE             */ \
                                        /*                                                                                           */ \
                                        /* car cela permet, par exemple, d'incrementer tous les elements d'un fichier d'une valeur   */ \
                                        /* constante...                                                                              */ \
                                        /*                                                                                           */ \
                                        /* Je rappelle le 20170111102646 que si le nom du fichier est une "bonne" valeur numerique,  */ \
                                        /* c'est elle qui l'emporte, meme si il existe un fichier portant ce nom. Cela ne peut       */ \
                                        /* evidemment se produire que si ce dernier fichier est designe de facon relative (et donc   */ \
                                        /* dans '$CWD'). Pour forcer l'acces a ce fichier (et donc ne pas utiliser la valeur         */ \
                                        /* numerique correspondant a son nom), il suffit d'absolutiser ce nom, qui alors ne          */ \
                                        /* ressemblera plus a une "bonne" valeur numerique...                                        */



Copyright © Jean-François COLONNA, 2019-2024.
Copyright © CMAP (Centre de Mathématiques APpliquées) UMR CNRS 7641 / École polytechnique, Institut Polytechnique de Paris, 2019-2024.