/*************************************************************************************************************************************/ /* */ /* 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