/*************************************************************************************************************************************/
/* */
/* G E N E R A T I O N D E V A L E U R S C O R R E S P O N D A N T A U X */
/* N O M B R E S D E D I V I S E U R S D E S N O M B R E S E N T I E R S : */
/* */
/* */
/* Definition : */
/* */
/* Cette commande (inspiree de la fonction */
/* 'v $ximf/nombres$FON Inombres_premiers') */
/* donne le nombre de diviseurs d'une liste */
/* de nombres entiers. Les nombres premiers */
/* sont obtenus en regardant ceux qui ont 2 */
/* Diviseurs... */
/* */
/* */
/* Nota : */
/* */
/* Je rappelle le 20161019093452 que pour */
/* simplement lister les nombres premiers, */
/* il suffira d'utiliser : */
/* */
/* $xci/valeurs_Goldbach$X premiere=1 derniere=N \ */
/* editer_nombres_premiers=VRAI \ */
/* calculer_decompositions=FAUX */
/* */
/* ou 'N' designe le nombre de nombres */
/* premiers que l'on souhaite calculer... */
/* */
/* */
/* Author of '$xci/valeurs_prem$K' : */
/* */
/* Jean-Francois COLONNA (LACTAMME, 19990202091459). */
/* */
/*************************************************************************************************************************************/
/*===================================================================================================================================*/
/*************************************************************************************************************************************/
/* */
/* I N T E R F A C E ' listG ' : */
/* */
/* */
/* :Debut_listG: */
/* :Fin_listG: */
/* */
/*************************************************************************************************************************************/
/*===================================================================================================================================*/
/*************************************************************************************************************************************/
/* */
/* D I R E C T I V E S S P E C I F I Q U E S D E C O M P I L A T I O N : */
/* */
/*************************************************************************************************************************************/
/*===================================================================================================================================*/
/*************************************************************************************************************************************/
/* */
/* F I C H I E R S D ' I N C L U D E S : */
/* */
/*************************************************************************************************************************************/
#include INCLUDES_MINI
/*===================================================================================================================================*/
/*************************************************************************************************************************************/
/* */
/* P A R A M E T R E S : */
/* */
/*************************************************************************************************************************************/
#include xci/sequence.01.I"
#define EDITER_DES_EN_TETES \
FAUX \
/* Faut-il editer des en-tetes (introduit le 20121109171704) ? */
#define EDITER_LES_NOMBRES \
FAUX \
/* Faut-il editer les nombres eux-memes (introduit le 20100102101009) ? */
#define EDITER_LES_DIVISEURS \
FAUX \
/* Faut-il editer la liste des diviseurs de chaque nombre. */
#define EDITER_LA_SOMME_DES_DIVISEURS \
FAUX \
/* Faut-il editer la somme des diviseurs de chaque nombre (introduit le 20121109170802) ? */
#define CALCULER_LA_FONCTION_DE_LIOUVILLE \
FAUX \
/* Faut-il calculer la fonction de Liouville et donc editer sa valeur (introduit le */ \
/* 20100102101009) ? */
#define EDITER_LA_FONCTION_DU_NOMBRE_DE_DIVISEURS \
VRAI \
/* Faut-il editer la fonction calculee du nombre de diviseurs, c'est-a-dire le nombre de */ \
/* diviseurs ou fonction de Liouville (introduit le 20121110071338) ? */
#define RECHERCHER_LES_DIVISEURS_PREMIERS \
FAUX \
/* Faut-il ne rechercher que les diviseurs premiers (introduit le 20100102103922) ou */ \
/* tous, quel qu'ils soient... */
#define PRENDRE_EN_COMPTE_LA_MULTIPLICITE_DES_DIVISEURS_PREMIERS \
VRAI \
/* Faut-il preendre en compte la multiplicite de chaque diviseur premier ou bien ne les */ \
/* compter qu'une seule fois chacun meme s'ils apparaissent plusieurs fois (introduit le */ \
/* 20100110134420) ? */
#include xci/valeurs.01.I"
/*===================================================================================================================================*/
/*************************************************************************************************************************************/
/* */
/* M A C R O S U T I L E S : */
/* */
/*************************************************************************************************************************************/
#include xci/valeurs.02.I"
#define NOMBRE_DE_NOMBRES \
NBRE(premiere_image,derniere_image) \
/* Nombre de nombres... */
#define INDEX_DU_PREMIER_NOMBRE_PREMIER \
INDEX0 \
/* Index du premier nombre premier... */
#define PREMIER_NOMBRE_PREMIER \
SUCC(UN) \
/* Definition a priori du premier nombre premier... */
/*===================================================================================================================================*/
/*************************************************************************************************************************************/
/* */
/* G E N E R A T I O N D E V A L E U R S C O R R E S P O N D A N T A U X */
/* N O M B R E S D E D I V I S E U R S D E S N O M B R E S E N T I E R S : */
/* */
/*************************************************************************************************************************************/
BCommande(nombre_d_arguments,arguments)
/*-----------------------------------------------------------------------------------------------------------------------------------*/
Bblock
DEFV(Int,INIT(premiere_image,PREMIERE_IMAGE));
/* Numero de la premiere image, */
DEFV(Int,INIT(derniere_image,DERNIERE_IMAGE));
/* Numero de la derniere image. */
DEFV(Int,INIT(numero_d_image,UNDEF));
/* Numero de l'image courante. */
DEFV(Int,INIT(pas_des_images,PAS_DES_IMAGES));
/* Pas de passage d'un numero d'image a une autre. */
DEFV(Logical,INIT(editer_des_en_tetes,EDITER_DES_EN_TETES));
/* Faut-il editer des en-tetes (introduit le 20121109171704) ? */
DEFV(Logical,INIT(editer_les_nombres,EDITER_LES_NOMBRES));
/* Faut-il editer les nombres eux-memes (introduit le 20100102101009) ? */
DEFV(Logical,INIT(editer_les_diviseurs,EDITER_LES_DIVISEURS));
/* Faut-il editer la liste des diviseurs de chaque nombre. */
DEFV(Logical,INIT(editer_la_somme_des_diviseurs,EDITER_LA_SOMME_DES_DIVISEURS));
/* Faut-il editer la somme des diviseurs de chaque nombre (introduit le 20121109170802) ? */
DEFV(Logical,INIT(calculer_la_fonction_de_Liouville,CALCULER_LA_FONCTION_DE_LIOUVILLE));
/* Faut-il calculer la fonction de Liouville et donc editer sa valeur (introduit le */
/* 20100102101009) ? */
DEFV(Logical,INIT(editer_la_fonction_du_nombre_de_diviseurs,EDITER_LA_FONCTION_DU_NOMBRE_DE_DIVISEURS));
/* Faut-il editer la fonction calculee du nombre de diviseurs, c'est-a-dire le nombre de */
/* diviseurs ou fonction de Liouville (introduit le 20121110071338) ? */
DEFV(Logical,INIT(rechercher_les_diviseurs_premiers,RECHERCHER_LES_DIVISEURS_PREMIERS));
/* Faut-il ne rechercher que les diviseurs premiers (introduit le 20100102103922) ou */
/* tous, quel qu'ils soient... */
DEFV(Logical,INIT(prendre_en_compte_la_multiplicite_des_diviseurs_premiers
,PRENDRE_EN_COMPTE_LA_MULTIPLICITE_DES_DIVISEURS_PREMIERS
)
);
/* Faut-il preendre en compte la multiplicite de chaque diviseur premier ou bien ne les */
/* compter qu'une seule fois chacun meme s'ils apparaissent plusieurs fois (introduit le */
/* 20100110134420) ? */
#include xci/valeurs.03.I"
/*..............................................................................................................................*/
GET_ARGUMENTS_(nombre_d_arguments
,BLOC(GET_ARGUMENT_I("premiere=""p=""D=",premiere_image);
GET_ARGUMENT_I("derniere=""d=""A=",derniere_image);
GET_ARGUMENT_I("pas=",pas_des_images);
GET_ARGUMENT_L("editer_en_tetes=""en_tetes=""et=",editer_des_en_tetes);
/* Arguments introduits le 20121109171704... */
GET_ARGUMENT_L("editer_nombres=""nombres=""en=",editer_les_nombres);
/* Arguments introduits le 20100102101009... */
GET_ARGUMENT_L("editer_diviseurs=""diviseurs=""ed=",editer_les_diviseurs);
/* L'argument "editer=" a ete supprime le 20100102101009... */
GET_ARGUMENT_L("editer_somme_diviseurs=""somme=""sd=",editer_la_somme_des_diviseurs);
/* Arguments introduits le 20121109170802... */
GET_ARGUMENT_L("fonction_Liouville=""Liouville=""fl=",calculer_la_fonction_de_Liouville);
/* Arguments introduits le 20100102101009... */
GET_ARGUMENT_L("editer_fonction=""fonction=""ef=",editer_la_fonction_du_nombre_de_diviseurs);
/* Arguments introduits le 20121110071338... */
GET_ARGUMENT_L("diviseurs_premiers=""dp=",rechercher_les_diviseurs_premiers);
/* Arguments introduits le 20100102103922... */
GET_ARGUMENT_L("multiplicite_diviseurs_premiers=""multiplicite=""mdp="
,prendre_en_compte_la_multiplicite_des_diviseurs_premiers
);
GET_ARGUMENT_N("unicite_diviseurs_premiers=""unicite=""udp="
,prendre_en_compte_la_multiplicite_des_diviseurs_premiers
);
/* Arguments introduits le 20100110134420... */
GET_ARGUMENT_C("signe=",valeurs_signees);
)
);
Test(IFLE(premiere_image,derniere_image))
Bblock
DEFV(Int,INIT(index_courant_des_nombres_premiers,INDEX_DU_PREMIER_NOMBRE_PREMIER));
DEFV(Local,DEFV(Int,DdTb1(POINTERi,liste_des_nombres_premiers,NOMBRE_DE_NOMBRES,ADRESSE_NON_ENCORE_DEFINIE)));
MdTb1(liste_des_nombres_premiers,NOMBRE_DE_NOMBRES,Int,ADRESSE_NON_ENCORE_DEFINIE);
/* Definition de la liste des nombres premiers si besoin est (introduit le 20100129094657). */
/* */
/* On notera que le nombre possible d'elements de 'liste_des_nombres_premiers' (soit */
/* 'NOMBRE_DE_NOMBRES') pourrait etre optimise grace au logarithme integral, mais avec */
/* cette valeur, au moins, je ne prends pas de risque... */
EGAL(IdTb1(liste_des_nombres_premiers,index_courant_des_nombres_premiers,NOMBRE_DE_NOMBRES),PREMIER_NOMBRE_PREMIER);
/* Definition a priori du premier nombre premier... */
Test(IFET(IL_FAUT(calculer_la_fonction_de_Liouville)
,IL_NE_FAUT_PAS(rechercher_les_diviseurs_premiers)
)
)
Bblock
PRINT_ERREUR("le calcul de la fonction de Liouville implique et force la recherche des seuls diviseurs premiers");
EGAL(rechercher_les_diviseurs_premiers,VRAI);
/* Et on force la recherche des diviseurs premiers... */
Eblock
ATes
Bblock
Eblock
ETes
DoIn(numero_d_image,premiere_image,derniere_image,pas_des_images)
Bblock
DEFV(Int,INIT(nombre_courant,numero_d_image));
/* Nombre entier courant a tester (introduit le 20100102103741). */
DEFV(Int,INIT(diviseur_courant_ou_index_du_diviseur_courant,UNDEF));
/* Diviseur courant du nombre courant 'nombre_courant' ou son index dans le cas ou ne */
/* sont recherches que les diviseurs premiers... */
DEFV(Int,INIT(nombre_de_diviseurs_du_nombre_courant,ZERO));
/* Nombre de diviseurs du nombre courant 'nombre_courant'. */
DEFV(Int,INIT(somme_des_diviseurs_du_nombre_courant,ZERO));
/* Somme des diviseurs du nombre courant 'nombre_courant'. */
Test(IL_FAUT(editer_les_nombres))
Bblock
CAL2(Prin1(Cara(chain_Aconcaten5(COND(IL_FAUT(editer_des_en_tetes),"Nombre=",C_VIDE)
,INTRODUCTION_FORMAT
,valeurs_signees
,"d"
,":"
)
)
,nombre_courant
)
);
/* Edition des nombres eux-memes (introduite le 20100102101009). */
Eblock
ATes
Bblock
Eblock
ETes
DoIn(diviseur_courant_ou_index_du_diviseur_courant
,COND(IL_FAUT(rechercher_les_diviseurs_premiers)
,INDEX_DU_PREMIER_NOMBRE_PREMIER
,UN
)
,COND(IL_FAUT(rechercher_les_diviseurs_premiers)
,index_courant_des_nombres_premiers
,nombre_courant
)
,I
)
/* ATTENTION, on n'optimise pas avec 'INTE(RACX(nombre_courant))' afin d'etre sur d'avoir */
/* 'nombre_courant' comme diviseur de lui-meme et aussi, eviter des problemes au cas ou */
/* l'on utiliserait des nombres negatifs... */
Bblock
DEFV(Int,INIT(diviseur_courant_effectif
,COND(IL_FAUT(rechercher_les_diviseurs_premiers)
,IdTb1(liste_des_nombres_premiers
,diviseur_courant_ou_index_du_diviseur_courant
,NOMBRE_DE_NOMBRES
)
,diviseur_courant_ou_index_du_diviseur_courant
)
)
);
/* Introduit le 20100129094657... */
Test(IFET(IFGE(nombre_courant,diviseur_courant_effectif)
,IZGT(diviseur_courant_effectif)
)
)
Bblock
DEFV(Logical,INIT(tester_le_diviseur_courant,VRAI));
/* Afin de faire au moins une fois la boucle 'Tant(...)' qui suit... */
Tant(IL_FAUT(tester_le_diviseur_courant))
Bblock
Test(IZEQ(REST(nombre_courant,diviseur_courant_effectif)))
Bblock
INCR(nombre_de_diviseurs_du_nombre_courant,I);
/* Comptage des diviseurs... */
INCR(somme_des_diviseurs_du_nombre_courant,diviseur_courant_effectif);
/* Calcul de la somme des diviseurs... */
Test(IL_FAUT(editer_les_diviseurs))
Bblock
CAL2(Prin1(Cara(chain_Aconcaten5(COND(IL_FAUT(editer_des_en_tetes),"Diviseur=",C_VIDE)
,"=%"
,valeurs_signees
,"d"
," "
)
)
,diviseur_courant_effectif
)
);
/* Edition de chacun des diviseurs lorsque cela est demande. Cela est fait sur la meme ligne */
/* que 'nombre_de_diviseurs_du_nombre_courant' afin de simplifier le "tri" de toutes ces */
/* valeurs... */
Eblock
ATes
Bblock
Eblock
ETes
Test(IL_FAUT(rechercher_les_diviseurs_premiers))
Bblock
DEFV(Logical,INIT(tester_le_diviseur_premier_courant,VRAI));
/* Afin de faire au moins une fois la boucle 'Tant(...)' qui suit... */
Tant(IL_FAUT(tester_le_diviseur_premier_courant))
Bblock
EGAL(nombre_courant,DIVI(nombre_courant,diviseur_courant_effectif));
/* Lorsque l'on ne recherche que les diviseurs premiers, on itere sur le diviseur courant */
/* tant que cela est possible... */
Test(IFOU(IFLT(nombre_courant,diviseur_courant_effectif)
,IFEQ(nombre_courant,UN)
)
)
Bblock
EGAL(tester_le_diviseur_courant,FAUX);
EGAL(tester_le_diviseur_premier_courant,FAUX);
Eblock
ATes
Bblock
Test(IL_FAUT(prendre_en_compte_la_multiplicite_des_diviseurs_premiers))
Bblock
EGAL(tester_le_diviseur_premier_courant,FAUX);
Eblock
ATes
Bblock
Test(IZNE(REST(nombre_courant,diviseur_courant_effectif)))
Bblock
EGAL(tester_le_diviseur_premier_courant,FAUX);
Eblock
ATes
Bblock
/* Tant que le nombre courant est divisible par le nombre premier courant on continue */
/* a diviser par lui afin d'ignorer ainsi son degre de multiplicite (introduit le */
/* 20100110134420). */
Eblock
ETes
Eblock
ETes
Eblock
ETes
Eblock
ETan
Eblock
ATes
Bblock
EGAL(tester_le_diviseur_courant,FAUX);
Eblock
ETes
Eblock
ATes
Bblock
EGAL(tester_le_diviseur_courant,FAUX);
Eblock
ETes
Eblock
ETan
Eblock
ATes
Bblock
Eblock
ETes
Eblock
EDoI
Test(IL_FAUT(rechercher_les_diviseurs_premiers))
Bblock
Test(IFGT(nombre_courant,PREMIER_NOMBRE_PREMIER))
Bblock
Test(IZEQ(nombre_de_diviseurs_du_nombre_courant))
Bblock
INCR(index_courant_des_nombres_premiers,I);
EGAL(IdTb1(liste_des_nombres_premiers,index_courant_des_nombres_premiers,NOMBRE_DE_NOMBRES)
,nombre_courant
);
/* Un nouveau nombre premier a ete trouve, on le memorise... */
EGAL(nombre_de_diviseurs_du_nombre_courant,UN);
/* Et un nombre premier a au moins un diviseur : lui-meme... */
Test(IL_FAUT(editer_les_diviseurs))
Bblock
CAL2(Prin1(Cara(chain_Aconcaten5(COND(IL_FAUT(editer_des_en_tetes),"Diviseur=",C_VIDE)
,"=%"
,valeurs_signees
,"d"
," "
)
)
,nombre_courant
)
);
/* Edition de l'unique diviseur (lui-meme) lorsque cela est demande... */
Eblock
ATes
Bblock
Eblock
ETes
Eblock
ATes
Bblock
Eblock
ETes
Eblock
ATes
Bblock
Eblock
ETes
Eblock
ATes
Bblock
Eblock
ETes
Test(IL_FAUT(editer_la_somme_des_diviseurs))
Bblock
CAL2(Prin1(Cara(chain_Aconcaten4("SommeDiviseurs=%",valeurs_signees,"d"," "))
,somme_des_diviseurs_du_nombre_courant
)
);
/* Edition de la somme des diviseurs lorsque cela est demande (introduit le 20121109170802). */
/* */
/* On notera que pour un nombre premier 'P', on a : */
/* */
/* SommeDiviseur(P) = 1+P */
/* */
/* puisque, par definition il n'a comme diviseurs que {1,P}... */
Eblock
ATes
Bblock
Eblock
ETes
Test(IL_FAUT(editer_la_fonction_du_nombre_de_diviseurs))
/* Test introduit le 20121110071338... */
Bblock
CAL2(Prin1(Cara(chain_Aconcaten4(COND(IL_FAUT(editer_des_en_tetes),"FonctionNombreDiviseurs=",C_VIDE)
,INTRODUCTION_FORMAT
,valeurs_signees
,"d"
)
)
,COND(IL_NE_FAUT_PAS(calculer_la_fonction_de_Liouville)
,nombre_de_diviseurs_du_nombre_courant
,INTE(PUIX(NEGA(UN),nombre_de_diviseurs_du_nombre_courant))
)
)
);
/* Et enfin, edition du nombre de diviseurs du nombre courant 'nombre_courant'. */
/* */
/* Le calcul de la fonction de Liouville a ete introduit le 20100102101009. Cette fonction */
/* vaut -1 a la puissance le nombre de diviseurs premiers (eventuellement identiques et */
/* en excluant 1 evidemment...). */
Eblock
ATes
Bblock
Eblock
ETes
CAL2(Prin0("\n"));
/* Introduit sous cette forme le 20121110071338... */
Eblock
EDoI
FdTb1(liste_des_nombres_premiers,NOMBRE_DE_NOMBRES,Int,ADRESSE_NON_ENCORE_DEFINIE);
/* Definition de la liste des nombres premiers si besoin est (introduit le 20100129094657). */
Eblock
ATes
Bblock
PRINT_ERREUR("la relation d'ordre stricte ('premier < dernier') n'est pas respectee");
Eblock
ETes
RETU_Commande;
Eblock
ECommande