_______________________________________________________________________________________________________________________________________ /*************************************************************************************************************************************/ /* */ /* F O N C T I O N S R E L A T I V E S A U X N O M B R E S E N T I E R S : */ /* */ /* */ /* Definition : */ /* */ /* Ce fichier contient toutes les fonctions */ /* de base de generation de champs utilisant les */ /* nombre entiers. */ /* */ /* */ /* Author of '$ximf/nombres$FON' : */ /* */ /* Jean-Francois COLONNA (LACTAMME, 19880000000000). */ /* */ /*************************************************************************************************************************************/ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* R E C H E R C H E D E S N O M B R E S P R E M I E R S */ /* E T P L U S G E N E R A L E M E N T D E S D I V I S E U R S D I F F E R E N T S : */ /* */ /*************************************************************************************************************************************/ #define PREMIER_NOMBRE_ENTIER \ UN \ /* Premier nombre entier non nul. */ #define NOMBRE_DE_NOMBRES_A_TESTER \ QUOE(ADD2(dimXY,DOUB(ADD2(dimX,dimY))),MUL2(pasX,pasY)) \ /* Ainsi, on ajoute une "bordure" autour de l'image compensant le fait que si */ \ /* l'on prend juste 'dimXY', etant donne la position de (Xcentre,Ycentre), on */ \ /* risque de laisser deux cotes de l'image incomplets... */ BFonctionP DEFV(Common,DEFV(Logical,SINT(Inombres_premiers_____visualiser_le_nombre_de_diviseurs_du_point_courant,VRAI))); /* Introduit le 20150331100103 pour plus de generalite... */ DEFV(Common,DEFV(genere_p,SINT(Inombres_premiers_____niveau_de_marquage_des_nombres_non_premiers__________,GRIS_0))); DEFV(Common,DEFV(genere_p,SINT(Inombres_premiers_____niveau_de_marquage_du_premier_nombre_________________,GRIS_2))); DEFV(Common,DEFV(genere_p,SINT(Inombres_premiers_____niveau_de_marquage_des_nombres_____premiers__________,GRIS_8))); DEFV(Common,DEFV(genere_p,SINT(Inombres_premiers_____niveau_de_marquage_des_nombres_____premiers_jumeaux_1,GRIS_4))); DEFV(Common,DEFV(genere_p,SINT(Inombres_premiers_____niveau_de_marquage_des_nombres_____premiers_jumeaux_2,GRIS_5))); /* Niveaux a utiliser lorsque l'on ne visualise que les nombres premiers (introduit */ /* le 20150331100103). */ DEFV(Common,DEFV(Positive,SINT(Inombres_premiers_____distance_entre_deux_nombres_premiers_jumeaux,DEUX))); /* Distance entre deux nombres premiers jumeuax (introduite le 20150331173218). */ DEFV(Common,DEFV(FonctionP,POINTERp(Inombres_premiers(imageR,dernier_nombre_a_tester,pas_entre_les_nombres)))) DEFV(Argument,DEFV(image,imageR)); /* Image Resultat, telle que : imageR[X][Y]=nombre de diviseurs du nombre valant */ /* le rang du point {X,Y} sur une spirale carree centree. */ DEFV(Argument,DEFV(Positive,dernier_nombre_a_tester)); /* Dernier nombre entier que l'on testera, */ DEFV(Argument,DEFV(Int,pas_entre_les_nombres)); /* Et pas de passage d'un nombre entier au suivant... */ /*-----------------------------------------------------------------------------------------------------------------------------------*/ Bblock DEFV(Int,INIT(numero_du_point_courant,UNDEF)); /* Numero du point courant dans [PREMIER_NOMBRE_ENTIER,dernier_nombre_a_tester]. */ DEFV(Int,INIT(diviseur_courant,UNDEF)); /* Diviseur courant du numero du point courant dans */ /* [PREMIER_NOMBRE_ENTIER,numero_du_point_courant]. */ DEFV(Int,INIT(nombre_de_diviseurs_du_point_courant,UNDEF)); /* Nombre de diviseurs du numero du point courant. */ DEFV(pointI_2D,point_courant); /* Point (entier) courant. */ SPIRALE_DEFINITION /* Donnees de generation d'une spirale de parcours d'une image. */ DEFV(Logical,INIT(le_nombre_premier_precedent_existe,FAUX)); DEFV(Int,INIT(nombre_premier_precedent,UNDEF)); DEFV(pointI_2D,point_precedent); /* Donnees utiles a la visualisation des nombres premiers jumeaux... */ /*..............................................................................................................................*/ Test(IFGE(NOIR,NIVA(PREMIER_NOMBRE_ENTIER))) Bblock PRINT_ATTENTION("on ne pourra faire la difference entre les points marques et les points non marques"); Eblock ATes Bblock Eblock ETes Test(IZLE(pas_entre_les_nombres)) Bblock PRINT_ERREUR("le pas de passage d'un nombre entier au suivant doit etre strictement positif"); Eblock ATes Bblock Eblock ETes Test(IFET(EST_IMPAIR(Inombres_premiers_____distance_entre_deux_nombres_premiers_jumeaux) ,IFGT(Inombres_premiers_____distance_entre_deux_nombres_premiers_jumeaux,UN) ) ) Bblock PRINT_ATTENTION("une distance entre nombres premiers 'jumeaux' impaire et superieure a 1 n'a pas de sens"); /* Message introduit le 20150331173218... */ /* */ /* En effet, la "distance" entre deux nombres premiers quelconques (et donc pas */ /* necessairement jumeaux) ne peut etre que paire (sauf entre 2 et 3) puisque les */ /* nombres premiers sont impairs (sauf 2...). */ Eblock ATes Bblock Eblock ETes SPIRALE_VALIDATION; /* Validation des pas de parcours (pasX,pasY) des images. */ INITIALISATION_POINT_2D(point_courant,Xcentre,Ycentre); /* Et on se place au centre de l'image. */ CALS(Inoir(imageR)); /* Au cas ou l'on ne balayerait pas toute l'image... */ DoIn(numero_du_point_courant ,PREMIER_NOMBRE_ENTIER ,TRON(dernier_nombre_a_tester,PREMIER_NOMBRE_ENTIER,MUL2(NOMBRE_DE_NOMBRES_A_TESTER,pas_entre_les_nombres)) ,pas_entre_les_nombres ) Bblock DEFV(genere_p,INIT(niveau_de_marquage,NIVEAU_UNDEF)); /* Introduit le 20150331095646 afin de permettre de visualiser autre chose que le nombre */ /* de diviseurs... */ CLIR(nombre_de_diviseurs_du_point_courant); /* Initialisation du nombre de diviseurs du numero du point courant. */ DoIn(diviseur_courant,PREMIER_NOMBRE_ENTIER,numero_du_point_courant,I) Bblock Test(IZEQ(REST(numero_du_point_courant,diviseur_courant))) Bblock INCR(nombre_de_diviseurs_du_point_courant,I); /* Et on compte les diviseurs du nombre courant (y compris l'unite et ce */ /* nombre lui-meme...). */ Eblock ATes Bblock Eblock ETes Eblock EDoI Test(IFGE(NIVA(nombre_de_diviseurs_du_point_courant),BLANC)) Bblock PRINT_ATTENTION("il y a des points qui ont au moins 'BLANC' diviseurs"); Eblock ATes Bblock Eblock ETes Test(IL_FAUT(Inombres_premiers_____visualiser_le_nombre_de_diviseurs_du_point_courant)) /* Test introduit le 20150331100103... */ Bblock EGAL(niveau_de_marquage,GENP(TRNP(NIVA(nombre_de_diviseurs_du_point_courant)))); /* Afin de visualiser le nombre de diviseurs... */ Eblock ATes Bblock Test(IFEQ(numero_du_point_courant,PREMIER_NOMBRE_ENTIER)) Bblock EGAL(niveau_de_marquage,Inombres_premiers_____niveau_de_marquage_du_premier_nombre_________________); /* Cas du premier nombre entier... */ Eblock ATes Bblock Test(IFEQ(nombre_de_diviseurs_du_point_courant,DEUX)) Bblock EGAL(niveau_de_marquage,Inombres_premiers_____niveau_de_marquage_des_nombres_____premiers__________); /* Afin de visualiser les nombres premiers a priori... */ Test(EST_VRAI(le_nombre_premier_precedent_existe)) Bblock Test(IFEQ(SOUS(numero_du_point_courant,nombre_premier_precedent) ,Inombres_premiers_____distance_entre_deux_nombres_premiers_jumeaux ) ) Bblock EGAL(niveau_de_marquage ,Inombres_premiers_____niveau_de_marquage_des_nombres_____premiers_jumeaux_1 ); /* Afin de visualiser les nombres premiers jumeaux... */ store_point_valide(niveau_de_marquage ,imageR ,ASD1(point_precedent,x),ASD1(point_precedent,y) ,FVARIABLE ); /* Et on remarque le point precedent correspondant au couple courant de nombres */ /* premiers jumeaux... */ EGAL(niveau_de_marquage ,Inombres_premiers_____niveau_de_marquage_des_nombres_____premiers_jumeaux_2 ); /* Afin de visualiser les nombres premiers jumeaux... */ Eblock ATes Bblock Eblock ETes Eblock ATes Bblock Eblock ETes TRANSFERT_POINT_2D(point_precedent,point_courant); EGAL(nombre_premier_precedent,numero_du_point_courant); EGAL(le_nombre_premier_precedent_existe,VRAI); /* Memorisation du nombre premier courant... */ Eblock ATes Bblock EGAL(niveau_de_marquage,Inombres_premiers_____niveau_de_marquage_des_nombres_non_premiers__________); /* Afin de visualiser les nombres non premiers. */ Eblock ETes Eblock ETes Eblock ETes store_point_valide(niveau_de_marquage ,imageR ,ASD1(point_courant,x),ASD1(point_courant,y) ,FVARIABLE ); /* Et on marque le point courant avec le nombre de diviseurs de son rang... */ /* */ /* ATTENTION : le point marque est correct, c'est 'point_courant', et non pas {X,Y} ce qui */ /* serait incorrect. On notera que dans le cas d'une image non carree (de type 'Pal', par */ /* exemple), il y aura donc des bandes 'NOIR' dans l'image... */ SPIRALE_INITIALISATION; /* Initialisation dynamique de 'spirale_nombre_de_points_a_traiter'. */ SPIRALE_DEPLACEMENT(ASD1(point_courant,x),ASD1(point_courant,y)); /* Deplacement du point courant de la spirale... */ /* ATTENTION : on n'utilise pas 'SPIRALE_DEPLACEMENT_ET_PARCOURS(...)' afin de garantir le */ /* traitement de tous les points de l'image... */ SPIRALE_PARCOURS; /* Parcours de la spirale avec rotation eventuelle de PI/2 du bras courant... */ Eblock EDoI RETI(imageR); Eblock EFonctionP /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* R E C H E R C H E D E S M U L T I P L E S D ' U N N O M B R E : */ /* */ /*************************************************************************************************************************************/ BFonctionP DEFV(Common,DEFV(FonctionP,POINTERp(Imultiples_d_un_nombre(imageR ,racine_des_multiples ,niveau_des_multiples ,dernier_nombre_a_tester,pas_entre_les_nombres ) ) ) ) DEFV(Argument,DEFV(image,imageR)); /* Image Resultat, telle que : imageR[X][Y]=liste des multiples de la "racine", */ /* les nombres entiers etant reperes par le rang du point {X,Y} sur une spirale */ /* carree centree. */ DEFV(Argument,DEFV(Int,racine_des_multiples)); /* Nombre entier dont on cherche les multiples. */ DEFV(Argument,DEFV(genere_p,niveau_des_multiples)); /* Niveau de marquage des multiples du nombre argument ; on notera que l'on */ /* ne marque pas les "non multiples", afin de permettre des "superpositions" */ /* de differents nombres de base. */ DEFV(Argument,DEFV(Positive,dernier_nombre_a_tester)); /* Dernier nombre entier que l'on testera, */ DEFV(Argument,DEFV(Int,pas_entre_les_nombres)); /* Et pas de passage d'un nombre entier au suivant... */ /*-----------------------------------------------------------------------------------------------------------------------------------*/ Bblock DEFV(Int,INIT(numero_du_point_courant,UNDEF)); /* Numero du point courant dans [PREMIER_NOMBRE_ENTIER,dernier_nombre_a_tester]. */ DEFV(pointI_2D,point_courant); /* Point (entier) courant. */ SPIRALE_DEFINITION /* Donnees de generation d'une spirale de parcours d'une image. */ /*..............................................................................................................................*/ Test(IFGE(NOIR,NIVA(PREMIER_NOMBRE_ENTIER))) Bblock PRINT_ATTENTION("on ne pourra faire la difference entre les points marques et les points non marques"); Eblock ATes Bblock Eblock ETes Test(IZLE(racine_des_multiples)) Bblock PRINT_ERREUR("les nombres entiers doivent etre strictement positifs"); Eblock ATes Bblock Eblock ETes Test(IZLE(pas_entre_les_nombres)) Bblock PRINT_ERREUR("le pas de passage d'un nombre entier au suivant doit etre strictement positif"); Eblock ATes Bblock Eblock ETes SPIRALE_VALIDATION; /* Validation des pas de parcours (pasX,pasY) des images. */ INITIALISATION_POINT_2D(point_courant,Xcentre,Ycentre); /* Et on se place au centre de l'image. */ DoIn(numero_du_point_courant ,PREMIER_NOMBRE_ENTIER ,TRON(dernier_nombre_a_tester,PREMIER_NOMBRE_ENTIER,MUL2(NOMBRE_DE_NOMBRES_A_TESTER,pas_entre_les_nombres)) ,pas_entre_les_nombres ) Bblock Test(IZEQ(REST(numero_du_point_courant,racine_des_multiples))) Bblock store_point_valide(niveau_des_multiples ,imageR ,ASD1(point_courant,x),ASD1(point_courant,y) ,FVARIABLE ); /* Et on marque le point courant lorsqu'il est divisible par la "racine"... */ Eblock ATes Bblock Eblock ETes SPIRALE_INITIALISATION; /* Initialisation dynamique de 'spirale_nombre_de_points_a_traiter'. */ SPIRALE_DEPLACEMENT(ASD1(point_courant,x),ASD1(point_courant,y)); /* Deplacement du point courant de la spirale... */ /* ATTENTION : on n'utilise pas 'SPIRALE_DEPLACEMENT_ET_PARCOURS(...)' afin de garantir le */ /* traitement de tous les points de l'image... */ SPIRALE_PARCOURS; /* Parcours de la spirale avec rotation eventuelle de PI/2 du bras courant... */ Eblock EDoI RETI(imageR); Eblock EFonctionP /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* E T U D E D E L A P E R S I S T A N C E M U L T I P L I C A T I V E */ /* E T A D D I T I V E D E S N O M B R E S : */ /* */ /*************************************************************************************************************************************/ BFonctionP DEFV(Common,DEFV(Logical,SINT(Ipersistance_multiplicative_des_nombres_entiers_____persistance_additive,FAUX))); /* Introduit le 20130531105329 pour plus de generalite... */ DEFV(Common,DEFV(Positive,SINT(Ipersistance_multiplicative_des_nombres_entiers_____base_de_numeration,BASE10))); /* Base de numeration a utiliser, la base decimale etant la base par defaut... */ DEFV(Common,DEFV(Logical,SINT(Ipersistance_multiplicative_des_nombres_entiers_____editer_la_persistance_des_nombres_entiers,FAUX))); /* Introduit le 20130531094217 a des fins de validation principalement... */ DEFV(Common,DEFV(Logical,SINT(Ipersistance_multiplicative_des_nombres_entiers_____renvoyer_la_Persistance,VRAI))); DEFV(Common,DEFV(Positive,SINT(Ipersistance_multiplicative_des_nombres_entiers_____maximum_de_la_Persistance,INFINI))); /* Introduits le 20150113092936 afin de permettre, par exemple, de reperer les nombres qui */ /* initialement contiennent au moins un zero. Il suffit pour ce faire de prendre un maximum */ /* de la 'Persistance' egal a 0 et de ne pas renvoyer la 'Persistance' (et donc renvoyer le */ /* 'CumulMultiplicatif_ou_Additif')... */ DEFV(Common,DEFV(FonctionP,POINTERp(Ipersistance_multiplicative_des_nombres_entiers(imageR ,dernier_nombre_a_tester,pas_entre_les_nombres ) ) ) ) /* Fonction introduite le 20130531075712... */ DEFV(Argument,DEFV(image,imageR)); /* Image Resultat, telle que : imageR[X][Y]=persistance multiplicative du point {X,Y} */ /* sur une spirale carree centree. */ /* carree centree. */ DEFV(Argument,DEFV(Positive,dernier_nombre_a_tester)); /* Dernier nombre entier que l'on testera, */ DEFV(Argument,DEFV(Int,pas_entre_les_nombres)); /* Et pas de passage d'un nombre entier au suivant... */ /*-----------------------------------------------------------------------------------------------------------------------------------*/ Bblock DEFV(Int,INIT(numero_du_point_courant,UNDEF)); /* Numero du point courant dans [PREMIER_NOMBRE_ENTIER,dernier_nombre_a_tester]. */ DEFV(pointI_2D,point_courant); /* Point (entier) courant. */ SPIRALE_DEFINITION /* Donnees de generation d'une spirale de parcours d'une image. */ DEFV(Int,INIT(PersistanceMaximale,MOINS_L_INFINI)); /* Calcul de la persistance maximale qui n'a de sens que si l'on edite les persistnces... */ /*..............................................................................................................................*/ Test(IFGE(NOIR,NIVA(PREMIER_NOMBRE_ENTIER))) Bblock PRINT_ATTENTION("on ne pourra faire la difference entre les points marques et les points non marques"); Eblock ATes Bblock Eblock ETes Test(IZLE(pas_entre_les_nombres)) Bblock PRINT_ERREUR("le pas de passage d'un nombre entier au suivant doit etre strictement positif"); Eblock ATes Bblock Eblock ETes SPIRALE_VALIDATION; /* Validation des pas de parcours (pasX,pasY) des images. */ INITIALISATION_POINT_2D(point_courant,Xcentre,Ycentre); /* Et on se place au centre de l'image. */ DoIn(numero_du_point_courant ,PREMIER_NOMBRE_ENTIER ,TRON(dernier_nombre_a_tester,PREMIER_NOMBRE_ENTIER,MUL2(NOMBRE_DE_NOMBRES_A_TESTER,pas_entre_les_nombres)) ,pas_entre_les_nombres ) Bblock DEFV(Int,INIT(CumulMultiplicatif_ou_Additif ,COND(IL_NE_FAUT_PAS(Ipersistance_multiplicative_des_nombres_entiers_____persistance_additive) ,UN ,ZERO ) ) ); DEFV(Int,INIT(Reduction,numero_du_point_courant)); DEFV(Int,INIT(Persistance,ZERO)); Test(IL_FAUT(Ipersistance_multiplicative_des_nombres_entiers_____editer_la_persistance_des_nombres_entiers)) Bblock CAL3(Prme1("%d",Reduction)); Test(IFLT(Reduction,Ipersistance_multiplicative_des_nombres_entiers_____base_de_numeration)) Bblock CAL3(Prme1(" --> %d",Reduction)); /* Introduit le 20150113104756 car, en effet, cela manquait... */ Eblock ATes Bblock Eblock ETes Eblock ATes Bblock Eblock ETes Tant(IFET(IFGE(Reduction,Ipersistance_multiplicative_des_nombres_entiers_____base_de_numeration) ,IFLE(Persistance,Ipersistance_multiplicative_des_nombres_entiers_____maximum_de_la_Persistance) ) ) Bblock DEFV(Int,INIT(Quotient,Reduction)); DEFV(Int,INIT(Reste,UNDEF)); EGAL(CumulMultiplicatif_ou_Additif ,COND(IL_NE_FAUT_PAS(Ipersistance_multiplicative_des_nombres_entiers_____persistance_additive) ,UN ,ZERO ) ); /* La reinitialisation de 'CumulMultiplicatif_ou_Additif' doit avoir lieu evidemment a */ /* chaque nouvelle iteration du 'Tant(...)'... */ Tant(IFNE(Quotient,ZERO)) Bblock EGAL(Reste,REST(Quotient,Ipersistance_multiplicative_des_nombres_entiers_____base_de_numeration)); EGAL(Quotient,DIVI(Quotient,Ipersistance_multiplicative_des_nombres_entiers_____base_de_numeration)); EGAL(CumulMultiplicatif_ou_Additif ,OPC2(IL_NE_FAUT_PAS(Ipersistance_multiplicative_des_nombres_entiers_____persistance_additive) ,MUL2 ,ADD2 ,CumulMultiplicatif_ou_Additif ,Reste ) ); Eblock ETan EGAL(Reduction,CumulMultiplicatif_ou_Additif); INCR(Persistance,I); Test(IL_FAUT(Ipersistance_multiplicative_des_nombres_entiers_____editer_la_persistance_des_nombres_entiers)) Bblock CAL3(Prme1(" --> %d",Reduction)); Eblock ATes Bblock Eblock ETes Eblock ETan EGAL(PersistanceMaximale,MAX2(PersistanceMaximale,Persistance)); Test(IL_FAUT(Ipersistance_multiplicative_des_nombres_entiers_____editer_la_persistance_des_nombres_entiers)) Bblock CAL3(Prme1(" %d\n",Persistance)); Eblock ATes Bblock Eblock ETes store_point_valide(COND(IL_FAUT(Ipersistance_multiplicative_des_nombres_entiers_____renvoyer_la_Persistance) ,NIVA(Persistance) ,NIVA(CumulMultiplicatif_ou_Additif) ) ,imageR ,ASD1(point_courant,x),ASD1(point_courant,y) ,FVARIABLE ); /* Et on marque le point courant a l'aide de sa persistance ou du cumul courant suivant */ /* les cas... */ SPIRALE_INITIALISATION; /* Initialisation dynamique de 'spirale_nombre_de_points_a_traiter'. */ SPIRALE_DEPLACEMENT(ASD1(point_courant,x),ASD1(point_courant,y)); /* Deplacement du point courant de la spirale... */ /* ATTENTION : on n'utilise pas 'SPIRALE_DEPLACEMENT_ET_PARCOURS(...)' afin de garantir le */ /* traitement de tous les points de l'image... */ SPIRALE_PARCOURS; /* Parcours de la spirale avec rotation eventuelle de PI/2 du bras courant... */ Eblock EDoI Test(IL_FAUT(Ipersistance_multiplicative_des_nombres_entiers_____editer_la_persistance_des_nombres_entiers)) Bblock CAL3(Prme4("PersistanceMaximale(%d,%d)=%d en base %d\n" ,PINTE(PREMIER_NOMBRE_ENTIER) ,bSOU(numero_du_point_courant,pas_entre_les_nombres) ,PersistanceMaximale ,Ipersistance_multiplicative_des_nombres_entiers_____base_de_numeration ) ); /* On n'oubliera pas que la definition de 'NOMBRE_DE_NOMBRES_A_TESTER' fait que l'on */ /* etudie un peu plus de nombres que 'dimXY'... */ Eblock ATes Bblock Eblock ETes RETI(imageR); Eblock EFonctionP #undef NOMBRE_DE_NOMBRES_A_TESTER /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* C R I B L E D ' E R A T O S T H E N E : */ /* */ /*************************************************************************************************************************************/ BFonctionP DEFV(Common,DEFV(Logical,SINT(Icrible_d_Eratosthene_____visualiser_la_divisibilite,VRAI))); /* Choix entre visualiser la divisibilite ou la non divisibilite... */ DEFV(Common,DEFV(Logical,SINT(Icrible_d_Eratosthene_____visualiser_les_nombres_premiers,VRAI))); /* Afin de pouvoir visualiser les nombres premiers... */ DEFV(Common,DEFV(Int,SINT(Icrible_d_Eratosthene_____premier_diviseur,PREMIER_NOMBRE_ENTIER))); DEFV(Common,DEFV(Int,SINT(Icrible_d_Eratosthene_____pas_des_diviseurs,UN))); DEFV(Common,DEFV(Int,SINT(Icrible_d_Eratosthene_____premier_nombre_a_tester,PREMIER_NOMBRE_ENTIER))); DEFV(Common,DEFV(Int,SINT(Icrible_d_Eratosthene_____pas_des_nombres,UN))); /* Definition des nombres a tester... */ DEFV(Common,DEFV(genere_p,SINT(Icrible_d_Eratosthene_____niveau_complementaire,GRIS_2))); DEFV(Common,DEFV(genere_p,SINT(Icrible_d_Eratosthene_____premier_niveau_de_marquage,GRIS_4))); DEFV(Common,DEFV(Float,SINT(Icrible_d_Eratosthene_____pas_du_niveau_de_marquage,FZERO))); DEFV(Common,DEFV(genere_p,SINT(Icrible_d_Eratosthene_____niveau_des_nombres_premiers,GRIS_8))); /* Definition du marquage. On notera le type 'Float' du pas destine a permettre de */ /* progresser "doucement" de facon a ce que les niveaux ne soient pas utilises "modulo"... */ DEFV(Common,DEFV(FonctionP,POINTERp(Icrible_d_Eratosthene(imageR)))) /* Fonction introduite le 20150402092828... */ DEFV(Argument,DEFV(image,imageR)); /* Image Resultat. */ /*-----------------------------------------------------------------------------------------------------------------------------------*/ Bblock DEFV(Int,INIT(diviseur_courant,Icrible_d_Eratosthene_____premier_diviseur)); DEFV(Float,INIT(niveau_courant,Icrible_d_Eratosthene_____premier_niveau_de_marquage)); /*..............................................................................................................................*/ begin_colonne Bblock DEFV(Int,INIT(nombre_courant,Icrible_d_Eratosthene_____premier_nombre_a_tester)); Test(IFEQ(niveau_courant,NOIR)) Bblock EGAL(niveau_courant,NOIR_PLANCHER); Eblock ATes Bblock Eblock ETes begin_ligne Bblock Test(IFLE(diviseur_courant,nombre_courant)) Bblock DEFV(Logical,INIT(est_divisible,DIVISIBLE(nombre_courant,diviseur_courant))); store_point(COND(IFOU(IFET(IL_FAUT(Icrible_d_Eratosthene_____visualiser_la_divisibilite) ,EST_VRAI(est_divisible) ) ,IFET(IL_NE_FAUT_PAS(Icrible_d_Eratosthene_____visualiser_la_divisibilite) ,EST_FAUX(est_divisible) ) ) ,GENP(niveau_courant) ,Icrible_d_Eratosthene_____niveau_complementaire ) ,imageR ,X,Y ,FVARIABLE ); /* Marquage de la divisibilite ou de la non divisibilite... */ Eblock ATes Bblock Eblock ETes Test(IL_FAUT(Icrible_d_Eratosthene_____visualiser_les_nombres_premiers)) Bblock Test(TOUJOURS_VRAI) /* Il a eu un temps ici : */ /* */ /* Test(IL_NE_FAUT_PAS(Icrible_d_Eratosthene_____visualiser_la_divisibilite)) */ /* */ Bblock Test(IFEQ(diviseur_courant,nombre_courant)) Bblock /* Cas ou on atteint la diagonale principale, on a fini de tester 'nombre_courant'... */ DEFV(Int,INIT(sous_diviseur_courant,UNDEF)); DEFV(Int,INIT(nombre_de_diviseurs,ZERO)); DoIn(sous_diviseur_courant,SUCC(PREMIER_NOMBRE_ENTIER),PRED(nombre_courant),I) Bblock INCR(nombre_de_diviseurs,COND(DIVISIBLE(nombre_courant,sous_diviseur_courant),UN,ZERO)); /* Comptage des diviseurs de 'nombre_courant' excepte 1 et lui-meme... */ Eblock EDoI Test(IZEQ(nombre_de_diviseurs)) Bblock /* Cas ou 'nombre_courant' est un nombre premier : */ begin_colonneQ(DoIn ,SUCY(Ymin) ,PREY(SavM_____Y) ,pasY ) Bblock store_point(Icrible_d_Eratosthene_____niveau_des_nombres_premiers ,imageR ,X,Y ,FVARIABLE ); /* Marquage de la colonne du nombre premier 'nombre_courant'... */ Eblock end_colonneQ(EDoI) Eblock ATes Bblock Eblock ETes Eblock ATes Bblock Eblock ETes Eblock ATes Bblock Eblock ETes Eblock ATes Bblock Eblock ETes INCR(nombre_courant,Icrible_d_Eratosthene_____pas_des_nombres); Eblock end_ligne INCR(niveau_courant,Icrible_d_Eratosthene_____pas_du_niveau_de_marquage); INCR(diviseur_courant,Icrible_d_Eratosthene_____pas_des_diviseurs); Eblock end_colonne RETI(imageR); Eblock EFonctionP /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* S U B D I V I S I O N R E C U R S I V E D ' U N E I M A G E : */ /* */ /*************************************************************************************************************************************/ BFonctionP #define NOMBRE_DE_NOMBRES_A_TESTER \ ADD2(dimXY,DOUB(ADD2(dimX,dimY))) \ /* Ainsi, on ajoute une "bordure" autour de l'image compensant le fait que si */ \ /* l'on prend juste 'dimXY', etant donne la position de (Xcentre,Ycentre), on */ \ /* risque de laisser deux cotes de l'image incomplets... */ #define AVANT_PREMIER_NIVEAU_DE_RECURSIVITE \ ZERO \ /* "Faux" premier niveau de recursivite ; mais on notera que celui-ci n'est */ \ /* jamais utilise pour le marquage, puisque l'on fait d'abord un 'SUCC'. */ #define PREMIER_NIVEAU_DE_RECURSIVITE \ SUCC(AVANT_PREMIER_NIVEAU_DE_RECURSIVITE) \ /* "Vrai" premier niveau de recursivite. */ #define NOMBRE_DE_NIVEAUX_DE_RECURSIVITE \ TRPU(MAX2(logX,logY)) \ /* Nombre de niveaux de recursivite maximum. */ #define NIVEAU_DE_PREMARQUAGE_DES_COLLISIONS \ NOIR \ /* Niveau indiquant qu'un point n'a pas ete encore atteint. */ #define NOMBRE_DE_SOMMETS_D_UN_CARRE \ INTE(PUI2(NOMBRE_DE_POINTS_DE_vectorI_2D)) \ /* Nombre de sommets d'un carre. */ \ /* */ \ /* Le 20070227143233, 'PUIX(...,BI_DIMENSIONNEL))' fut remplace par 'PUI2(...)'. */ #define DEFINITION_D_UN_CARRE(X_bas_gauche,Y_bas_gauche,X_haut_droite,Y_haut_droite) \ /* */ \ /* Y_haut_droite |---------------| */ \ /* |CHG CHD| */ \ /* | / | */ \ /* | / | */ \ /* | / | */ \ /* | / | */ \ /* | / | */ \ /* |CBG CBD| */ \ /* Y_bas_gauche |---------------| */ \ /* X_bas_gauche X_haut_droite */ \ /* */ \ /* "C" signifie "coin", */ \ /* "B" signifie "bas", "H" signifie "haut", */ \ /* "G" signifie "gauche", "D" signifie "droite". */ \ Bblock \ INITIALISATION_POINT_2D(coin_bas_gauche_reduit,X_bas_gauche,Y_bas_gauche); \ /* Definition du coin bas-gauche du carre courant, */ \ INITIALISATION_POINT_2D(coin_haut_droite_reduit,X_haut_droite,Y_haut_droite); \ /* Definition du coin haut-droite du carre courant, */ \ Eblock #define DECOUPAGE_RECURSIF_D_UN_CARRE \ Bblock \ CALS(Iquatre_subdivision_recursive(imageR \ ,coin_bas_gauche_reduit \ ,coin_haut_droite_reduit \ ,SUCC(niveau_de_la_recursivite) \ ,profondeur_maximale_de_la_recursivite \ ,population_courante_des_niveaux \ ,population_maximale_inferieure \ ,visualiser_le_nombre_de_diviseurs \ ) \ ); \ Eblock \ /* Appel de la fonction de decoupage recursif d'une image. */ DEFV(Local,DEFV(FonctionP,POINTERp(Iquatre_subdivision_recursive(imageR ,coin_bas_gauche ,coin_haut_droite ,niveau_de_la_recursivite ,profondeur_maximale_de_la_recursivite ,population_courante_des_niveaux ,population_maximale_inferieure ,visualiser_le_nombre_de_diviseurs ) ) ) ) DEFV(Argument,DEFV(image,imageR)); /* Image Resultat, telle que : imageR[X][Y]=profondeur de la recursion. */ DEFV(Argument,DEFV(pointI_2D,coin_bas_gauche)); /* Coin bas gauche du carre courant (a subdiviser), */ DEFV(Argument,DEFV(pointI_2D,coin_haut_droite)); /* Coin haut droite du carre courant (a subdiviser). */ DEFV(Argument,DEFV(Positive,niveau_de_la_recursivite)); /* Donne le niveau courant de la recursivite de decoupage. *. */ DEFV(Argument,DEFV(Positive,profondeur_maximale_de_la_recursivite)); /* Profondeur d'arret de la recursivite ; avec 'INFINI', on est sur */ /* d'aller jusqu'au bout... */ DEFV(Argument,DEFV(Positive,DTb1(population_courante_des_niveaux,NOMBRE_DE_NIVEAUX_DE_RECURSIVITE))); /* Pour chaque niveau de recursivite, on trouve dans ce vecteur sa population */ /* courante, c'est-a-dire le nombre de points qui y sont presents. */ DEFV(Argument,DEFV(Positive,DTb1(population_maximale_inferieure,NOMBRE_DE_NIVEAUX_DE_RECURSIVITE))); /* Pour chaque niveau de recursivite, on trouve dans ce vecteur la population */ /* maximale cumulee des niveaux de recursivite inferieurs. */ DEFV(Argument,DEFV(Logical,visualiser_le_nombre_de_diviseurs)); /* Cet indicateur precise si l'on visualise le niveau de recursivite ('FAUX'), */ /* ou le nombre de diviseurs du numero de chaque point ('VRAI'). */ /*-----------------------------------------------------------------------------------------------------------------------------------*/ Bblock DEFV(pointI_2D,coin_bas_gauche_reduit); /* Coin bas gauche du carre subdivise, */ DEFV(pointI_2D,coin_haut_droite_reduit); /* Coin haut droite du carre subdivise. */ DEFV(pointI_2D,centre_du_carre); /* Centre du carre courant. */ DEFV(Int,INIT(numero_du_centre_du_carre,UNDEF)); /* On definit ici un numero du centre du carre courant. Ce numero est */ /* independant du nombre de niveaux de recursivite que l'on va explorer (ce qui */ /* qu'un meme point aura toujours le meme numero, quelle que soit la profondeur */ /* de la recursivite) ; il est egal a la population totale des niveaux de */ /* recursivite inferieurs (que l'on considere alors pleins) plus le numero */ /* de ce centre a ce niveau... */ DEFV(Int,INIT(diviseur_courant,UNDEF)); /* Diviseur courant du numero du point courant dans */ /* [PREMIER_NOMBRE_ENTIER,numero_du_centre_du_carre]. */ DEFV(Int,INIT(nombre_de_diviseurs_du_point_courant,UNDEF)); /* Nombre de diviseurs du numero du point courant. */ /*..............................................................................................................................*/ Test(IFGT(niveau_de_la_recursivite,LSTX(PREMIER_NIVEAU_DE_RECURSIVITE,NOMBRE_DE_NIVEAUX_DE_RECURSIVITE))) Bblock PRINT_ERREUR("le niveau de recursivite courant est trop grand"); Eblock ATes Bblock Eblock ETes INITIALISATION_POINT_2D(centre_du_carre ,MOYE(ASD1(coin_bas_gauche,x),ASD1(coin_haut_droite,x)) ,MOYE(ASD1(coin_bas_gauche,y),ASD1(coin_haut_droite,y)) ); /* Calcul du centre du carre courant. */ INCR(ITb1(population_courante_des_niveaux,INDX(niveau_de_la_recursivite,PREMIER_NIVEAU_DE_RECURSIVITE)),I); /* Comptage de la population courante du niveau de recursivite courant. */ EGAL(numero_du_centre_du_carre ,ADD2(ITb1(population_maximale_inferieure,INDX(niveau_de_la_recursivite,PREMIER_NIVEAU_DE_RECURSIVITE)) ,ITb1(population_courante_des_niveaux,INDX(niveau_de_la_recursivite,PREMIER_NIVEAU_DE_RECURSIVITE)) ) ); /* Ce qui donne le numero du centre du carre courant. Celui-ci est donc */ /* egal a la population totale des niveaux inferieurs (supposes donc */ /* completement remplis), plus le numero de ce point au niveau courant ; */ /* le calcul est fait avant le test suivant afin d'avoir une numerotation */ /* homogene et "isotrope". */ Test(IFEQ(load_point_valide(imageR ,ASD1(centre_du_carre,x),ASD1(centre_du_carre,y) ) ,NIVEAU_DE_PREMARQUAGE_DES_COLLISIONS ) ) Bblock Test(IL_FAUT(visualiser_le_nombre_de_diviseurs)) Bblock CLIR(nombre_de_diviseurs_du_point_courant); /* Initialisation du nombre de diviseurs du numero du point courant. */ DoIn(diviseur_courant,PREMIER_NOMBRE_ENTIER,numero_du_centre_du_carre,I) Bblock Test(IZEQ(REST(numero_du_centre_du_carre,diviseur_courant))) Bblock INCR(nombre_de_diviseurs_du_point_courant,I); /* Et on compte les diviseurs du nombre courant (y compris l'unite et ce */ /* nombre lui-meme...). */ Eblock ATes Bblock Eblock ETes Eblock EDoI Test(IFGE(NIVA(nombre_de_diviseurs_du_point_courant),BLANC)) Bblock PRINT_ATTENTION("il y a des points qui ont au moins 'BLANC' diviseurs"); Eblock ATes Bblock Eblock ETes Eblock ATes Bblock Eblock ETes store_point_valide(COND(IL_FAUT(visualiser_le_nombre_de_diviseurs) ,GENP(TRNP(NIVA(nombre_de_diviseurs_du_point_courant))) ,GENP(NIVA(niveau_de_la_recursivite)) ) ,imageR ,ASD1(centre_du_carre,x),ASD1(centre_du_carre,y) ,FVARIABLE ); /* Et on le marque avec le niveau de recursivite courant */ /* a condition de ne pas ecraser un point anterieur. */ Eblock ATes Bblock Eblock ETes Test(IFET(IFLT(niveau_de_la_recursivite,profondeur_maximale_de_la_recursivite) ,IFET(IFGT(SOUA(ASD1(coin_haut_droite,x),ASD1(coin_bas_gauche,x)),pasX) ,IFGT(SOUA(ASD1(coin_haut_droite,y),ASD1(coin_bas_gauche,y)),pasY) ) ) ) Bblock /* On ne procede au decoupage recursif que si cela est possible (il ne */ /* se reduit pas a un point) et demande : */ /* */ /* Y_haut_droite |---------------| */ /* | | | */ /* | CHG | CHD | */ /* | | | */ /* |-------|-------| */ /* | | | */ /* | CBG | CBD | */ /* | | | */ /* Y_bas_gauche |---------------| */ /* X_bas_gauche X_haut_droite */ /* */ /* "C" signifie "carre", */ /* "B" signifie "bas", "H" signifie "haut", */ /* "G" signifie "gauche", "D" signifie "droite". */ DEFINITION_D_UN_CARRE(ASD1(centre_du_carre,x),ASD1(centre_du_carre,y),ASD1(coin_haut_droite,x),ASD1(coin_haut_droite,y)); /* Definition du sous-carre haut-droite, */ DECOUPAGE_RECURSIF_D_UN_CARRE; /* Et decoupage recursif... */ DEFINITION_D_UN_CARRE(ASD1(coin_bas_gauche,x),ASD1(centre_du_carre,y),ASD1(centre_du_carre,x),ASD1(coin_haut_droite,y)); /* Definition du sous-carre haut-gauche, */ DECOUPAGE_RECURSIF_D_UN_CARRE; /* Et decoupage recursif... */ DEFINITION_D_UN_CARRE(ASD1(coin_bas_gauche,x),ASD1(coin_bas_gauche,y),ASD1(centre_du_carre,x),ASD1(centre_du_carre,y)); /* Definition du sous-carre bas-gauche, */ DECOUPAGE_RECURSIF_D_UN_CARRE; /* Et decoupage recursif... */ DEFINITION_D_UN_CARRE(ASD1(centre_du_carre,x),ASD1(coin_bas_gauche,y),ASD1(coin_haut_droite,x),ASD1(centre_du_carre,y)); /* Definition du sous-carre haut-droite, */ DECOUPAGE_RECURSIF_D_UN_CARRE; /* Et decoupage recursif... */ Eblock ATes Bblock Eblock ETes RETI(imageR); Eblock EFonctionP /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* P A R C O U R S R E C U R S I F P A R S U B D I V I S I O N D ' U N E I M A G E : */ /* */ /*************************************************************************************************************************************/ BFonctionP DEFV(Common,DEFV(FonctionP,POINTERp(Isubdivision_recursive(imageR ,profondeur_maximale_de_la_recursivite ,visualiser_le_nombre_de_diviseurs ) ) ) ) DEFV(Argument,DEFV(image,imageR)); /* Image Resultat, telle que : imageR[X][Y]=profondeur de la recursion. */ DEFV(Argument,DEFV(Positive,profondeur_maximale_de_la_recursivite)); /* Profondeur d'arret de la recursivite ; avec 'INFINI', on est sur */ /* d'aller jusqu'au bout... */ DEFV(Argument,DEFV(Logical,visualiser_le_nombre_de_diviseurs)); /* Cet indicateur precise si l'on visualise le niveau de recursivite ('FAUX'), */ /* ou le nombre de diviseurs du numero de chaque point ('VRAI'). */ /*-----------------------------------------------------------------------------------------------------------------------------------*/ Bblock DEFV(pointI_2D,coin_bas_gauche_reduit); /* Coin bas gauche de l'image, */ DEFV(pointI_2D,coin_haut_droite_reduit); /* Coin haut droite de l'image. */ DEFV(Positive,INIT(niveau_de_la_recursivite,AVANT_PREMIER_NIVEAU_DE_RECURSIVITE)); /* Donne le niveau courant de la recursivite de decoupage. */ DEFV(Positive,DTb1(population_courante_des_niveaux,NOMBRE_DE_NIVEAUX_DE_RECURSIVITE)); /* Pour chaque niveau de recursivite, on trouve dans ce vecteur sa population, */ /* c'est-a-dire le nombre de points qui y sont presents. */ DEFV(Int,INIT(index_de_recursivite,UNDEF)); /* Index d'initialisation du vecteur de population des niveaux... */ DEFV(Positive,DTb1(population_maximale_inferieure,NOMBRE_DE_NIVEAUX_DE_RECURSIVITE)); /* Pour chaque niveau de recursivite, on trouve dans ce vecteur la population */ /* maximale cumulee des niveaux de recursivite inferieurs. */ DEFV(Int,INIT(index_de_cumul,UNDEF)); /* Index d'initialisation du vecteur de population des niveaux inferieurs... */ /*..............................................................................................................................*/ Test(IFET(IL_FAUT(visualiser_le_nombre_de_diviseurs) ,IFGE(NIVEAU_DE_PREMARQUAGE_DES_COLLISIONS,NIVA(PREMIER_NOMBRE_ENTIER)) ) ) Bblock PRINT_ATTENTION("on ne pourra faire la difference entre les points marques et les points non marques"); Eblock ATes Bblock Eblock ETes Test(IFNE(dimX,dimY)) Bblock PRINT_ATTENTION("les dimensions horizontales et verticales devraient etre egales"); Eblock ATes Bblock Eblock ETes Test(IFGE(NIVEAU_DE_PREMARQUAGE_DES_COLLISIONS,NIVA(PREMIER_NIVEAU_DE_RECURSIVITE))) Bblock PRINT_ATTENTION("on ne pourra faire la difference entre les points marques et les points non marques"); Eblock ATes Bblock Eblock ETes DoIn(index_de_recursivite ,PREMIER_NIVEAU_DE_RECURSIVITE ,LSTX(PREMIER_NIVEAU_DE_RECURSIVITE,NOMBRE_DE_NIVEAUX_DE_RECURSIVITE) ,I ) Bblock CLIR(ITb1(population_courante_des_niveaux,INDX(index_de_recursivite,PREMIER_NIVEAU_DE_RECURSIVITE))); /* Initialisation de la population de chaque niveau de recursivite, */ CLIR(ITb1(population_maximale_inferieure,INDX(index_de_recursivite,PREMIER_NIVEAU_DE_RECURSIVITE))); /* Et de la population cumulee des niveaux inferieurs... */ Test(IFGT(index_de_recursivite,PREMIER_NIVEAU_DE_RECURSIVITE)) Bblock DoIn(index_de_cumul ,PREMIER_NIVEAU_DE_RECURSIVITE ,LSTX(PREMIER_NIVEAU_DE_RECURSIVITE,PRED(index_de_recursivite)) ,I ) Bblock EGAL(ITb1(population_maximale_inferieure ,INDX(index_de_recursivite,PREMIER_NIVEAU_DE_RECURSIVITE) ) ,HORNER_1_01(ITb1(population_maximale_inferieure ,INDX(index_de_recursivite,PREMIER_NIVEAU_DE_RECURSIVITE) ) ,INTE(PUIX(NOMBRE_DE_SOMMETS_D_UN_CARRE,UN)) ,INTE(PUIX(NOMBRE_DE_SOMMETS_D_UN_CARRE,ZERO)) ) ); /* Comptage de la population des niveaux pleins inferieurs (d'ou le 'PRED'). */ /* On notera que ce comptage se fait avec la formule de Horner, c'est-a-dire */ /* de la facon suivante ('N' etant le nombre de sommets d'un carre) : */ /* */ /* n n-1 2 1 0 */ /* N + N +...+ N + N + N = N.(N.(...N.(N+1)...)+1)+1, */ /* */ /* avec : */ /* */ /* 1 0 */ /* N = N, et N = 1. */ /* */ Eblock EDoI Eblock ATes Bblock Eblock ETes Eblock EDoI Test(IFNE(ADD2(ITb1(population_maximale_inferieure,INDX(PREMIER_NIVEAU_DE_RECURSIVITE,PREMIER_NIVEAU_DE_RECURSIVITE)) ,ADD2(ITb1(population_courante_des_niveaux,INDX(PREMIER_NIVEAU_DE_RECURSIVITE,PREMIER_NIVEAU_DE_RECURSIVITE)) ,I ) ) ,PREMIER_NOMBRE_ENTIER ) ) Bblock PRINT_ATTENTION("le cardinal du premier niveau de recursivite est mauvais"); Eblock ATes Bblock Eblock ETes CALS(Iinitialisation(imageR,NIVEAU_DE_PREMARQUAGE_DES_COLLISIONS)); /* Indiquons qu'aucun point n'a encore ete atteint. */ DEFINITION_D_UN_CARRE(Xmin,Ymin,Xmax,Ymax); /* Definition du carre correspondant a l'image entiere... */ DECOUPAGE_RECURSIF_D_UN_CARRE; /* Et decoupage recursif... */ RETI(imageR); Eblock EFonctionP #undef DECOUPAGE_RECURSIF_D_UN_CARRE #undef DEFINITION_D_UN_CARRE #undef NOMBRE_DE_SOMMETS_D_UN_CARRE #undef NIVEAU_DE_PREMARQUAGE_DES_COLLISIONS #undef NOMBRE_DE_NIVEAUX_DE_RECURSIVITE #undef PREMIER_NIVEAU_DE_RECURSIVITE #undef AVANT_PREMIER_NIVEAU_DE_RECURSIVITE #undef NOMBRE_DE_NOMBRES_A_TESTER #undef PREMIER_NOMBRE_ENTIER _______________________________________________________________________________________________________________________________________ _______________________________________________________________________________________________________________________________________ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* S U I T E D E S Y R A C U S E : */ /* */ /*************************************************************************************************************************************/ BFonctionF DEFV(Common,DEFV(Int,SINT(IFsuite_de_Syracuse_____nombre_maximal_d_iterations,MILLE))); DEFV(Common,DEFV(Int,SINT(IFsuite_de_Syracuse_____premier_nombre_entier,UN))); DEFV(Common,DEFV(Int,SINT(IFsuite_de_Syracuse_____valeur_d_arret,UN))); /* Le 20130124115145 la valeur d'arret est passee de 'QUATRE' a 'UN' plus logique... */ DEFV(Common,DEFV(Int,SINT(IFsuite_de_Syracuse_____rang_initial_d_apparition_de_la_valeur_d_arret,ZERO))); DEFV(Common,DEFV(Int,SINT(IFsuite_de_Syracuse_____diviseur,DEUX))); DEFV(Common,DEFV(Int,SINT(IFsuite_de_Syracuse_____alpha___,TROIS))); DEFV(Common,DEFV(Int,SINT(IFsuite_de_Syracuse_____beta____,UN))); /* Parametres definissant par defaut la suite de Syracuse... */ DEFV(Common,DEFV(Logical,SINT(IFsuite_de_Syracuse_____editer_les_rangs,FAUX))); DEFV(Common,DEFV(Int,SINT(IFsuite_de_Syracuse_____premier_rang_d_edition,FLOT__BLANC))); /* Parametres definissant par defaut l'edition eventuelle des differents rangs (introduit */ /* le 20110306091524). */ #define NOMBRE_DE_NOMBRES_A_TESTER \ QUOE(ADD2(dimXY,DOUB(ADD2(dimX,dimY))),MUL2(pasX,pasY)) \ /* Ainsi, on ajoute une "bordure" autour de l'image compensant le fait que si */ \ /* l'on prend juste 'dimXY', etant donne la position de (Xcentre,Ycentre), on */ \ /* risque de laisser deux cotes de l'image incomplets... */ DEFV(Common,DEFV(FonctionF,POINTERF(IFsuite_de_Syracuse(imageR,dernier_nombre_a_tester,pas_entre_les_nombres)))) /* Fonction introduite le 20110305113822. Le 20110306091524, elle est passee de 'FonctionP' */ /* a 'FonctionF' pour supprimer les problemes de debordement... */ DEFV(Argument,DEFV(imageF,imageR)); /* Image Resultat, telle que : imageR[X][Y]=nombre de diviseurs du nombre valant */ /* le rang du point {X,Y} sur une spirale carree centree. */ DEFV(Argument,DEFV(Positive,dernier_nombre_a_tester)); /* Dernier nombre entier que l'on testera, */ DEFV(Argument,DEFV(Int,pas_entre_les_nombres)); /* Et pas de passage d'un nombre entier au suivant... */ /*-----------------------------------------------------------------------------------------------------------------------------------*/ Bblock DEFV(Int,INIT(nombre_entier_courant,UNDEF)); /* Numero du point courant dans [premier_nombre_entier,dernier_nombre_a_tester]. */ DEFV(pointI_2D,point_courant); /* Point (entier) courant. */ SPIRALE_DEFINITION /* Donnees de generation d'une spirale de parcours d'une image. */ /*..............................................................................................................................*/ Test(IFGE(FLOT__NOIR,IFsuite_de_Syracuse_____premier_nombre_entier)) Bblock PRINT_ATTENTION("on ne pourra faire la difference entre les points marques et les points non marques"); Eblock ATes Bblock Eblock ETes Test(IZLE(pas_entre_les_nombres)) Bblock PRINT_ERREUR("le pas de passage d'un nombre entier au suivant doit etre strictement positif"); Eblock ATes Bblock Eblock ETes SPIRALE_VALIDATION; /* Validation des pas de parcours (pasX,pasY) des images. */ INITIALISATION_POINT_2D(point_courant,Xcentre,Ycentre); /* Et on se place au centre de l'image. */ CALS(IFinitialisation(imageR,FLOT__NOIR)); /* Au cas ou l'on ne balayerait pas toute l'image... */ DoIn(nombre_entier_courant ,IFsuite_de_Syracuse_____premier_nombre_entier ,TRON(dernier_nombre_a_tester ,IFsuite_de_Syracuse_____premier_nombre_entier ,MUL2(NOMBRE_DE_NOMBRES_A_TESTER,pas_entre_les_nombres) ) ,pas_entre_les_nombres ) Bblock DEFV(Logical,INIT(iterer,VRAI)); DEFV(Int,INIT(nombre_d_iterations,ZERO)); /* Controle des iterations sachant que l'on s'arrete sur le premier 4 rencontre ou bien si */ /* le nombre d'iterations maximal est atteint... */ DEFV(Float,INIT(U_n,nombre_entier_courant)); /* Definition de U(n) passe de 'Int' a 'Float' le 20110306101744 pour avoir plus de */ /* capacite. Cela s'est vu, par exemple, avec : */ /* */ /* $xci/valeurs_Syra$X un=258207 */ /* */ /* pour lequel apparaissent rapidement des valeurs negatives... */ DEFV(Int,INIT(rang_d_apparition_de_la_valeur_d_arret ,IFsuite_de_Syracuse_____rang_initial_d_apparition_de_la_valeur_d_arret ) ); DEFV(Logical,INIT(on_a_rencontre_la_valeur_d_arret,FAUX)); /* Afin de savoir a partir de quand apparait {4,2,1} ? */ Tant(IL_FAUT(iterer)) Bblock Test(EST_FAUX(on_a_rencontre_la_valeur_d_arret)) Bblock Test(IFEQ(U_n,FLOT(IFsuite_de_Syracuse_____valeur_d_arret))) Bblock EGAL(on_a_rencontre_la_valeur_d_arret,VRAI); EGAL(iterer,FAUX); /* C'est termine... */ Eblock ATes Bblock INCR(rang_d_apparition_de_la_valeur_d_arret,I); Eblock ETes Eblock ATes Bblock Eblock ETes EGAL(U_n ,COND(fEST_PAIR(U_n) ,DIVI(U_n,FLOT(IFsuite_de_Syracuse_____diviseur)) ,AXPB(FLOT(IFsuite_de_Syracuse_____alpha___),U_n,FLOT(IFsuite_de_Syracuse_____beta____)) ) ); /* Calcul de la suite de Syracuse "generalisee" : */ /* */ /* U = U / D si U est pair, */ /* n n-1 n-1 */ /* */ /* U = A * U + B si U est impair, */ /* n n-1 n-1 */ /* */ /* avec : */ /* */ /* D = diviseur = 2 */ /* A = alpha = 3 */ /* B = beta = 1 */ /* */ /* et : */ /* */ /* U = 1 */ /* 0 */ /* */ /* par defaut. */ /* */ /* La conjecture enonce que quel que soit 'U(0)' de depart, a un moment apparait de facon */ /* periodique (et alors jusqu'a la fin des temps...) la suite {4,2,1}... */ /* */ /* Le 20110307091820 je note le danger dans l'ecriture : */ /* */ /* EST_PAIR(INTE(U_n)) */ /* */ /* car, en effet, le 'INTE(...)' ne donne pas la partie entiere de 'U_n' dans le cas ou */ /* 'U_n' est trop grand. Mais que faire d'autre ? Le probleme fut resolu le 20110308090607 */ /* par l'introduction de 'fEST_PAIR(...)'. */ INCR(nombre_d_iterations,I); Test(IFGE(nombre_d_iterations,IFsuite_de_Syracuse_____nombre_maximal_d_iterations)) Bblock EGAL(iterer,FAUX); /* On a fait trop d'iterations : on arrete... */ Eblock ATes Bblock Eblock ETes Eblock ETan Test(EST_FAUX(on_a_rencontre_la_valeur_d_arret)) /* Test essentiel introduit le 20130124080515... */ Bblock PRINT_ATTENTION("la valeur d'arret n'a pas ete atteinte"); CAL1(Prer2("(U0=%d avec %d iterations au maximum)\n" ,nombre_entier_courant ,IFsuite_de_Syracuse_____nombre_maximal_d_iterations ) ); Eblock ATes Bblock Eblock ETes Test(IL_FAUT(IFsuite_de_Syracuse_____editer_les_rangs)) Bblock Test(IFGE(rang_d_apparition_de_la_valeur_d_arret,IFsuite_de_Syracuse_____premier_rang_d_edition)) Bblock CAL3(Prme2("Rang(%d)[/%d]" ,nombre_entier_courant ,IFsuite_de_Syracuse_____rang_initial_d_apparition_de_la_valeur_d_arret ) ); Test(EST_VRAI(on_a_rencontre_la_valeur_d_arret)) Bblock CALS(FPrme0("=")); Eblock ATes Bblock CALS(FPrme0(">")); Eblock ETes CAL3(Prme1("%d\n",rang_d_apparition_de_la_valeur_d_arret)); Eblock ATes Bblock Eblock ETes Eblock ATes Bblock Eblock ETes storeF_point_valide(FLOT(rang_d_apparition_de_la_valeur_d_arret) ,imageR ,ASD1(point_courant,x),ASD1(point_courant,y) ); /* Et on marque le point courant avec le nombre de diviseurs de son rang... */ /* */ /* ATTENTION : le point marque est correct, c'est 'point_courant', et non pas {X,Y} ce qui */ /* serait incorrect. On notera que dans le cas d'une image non carree (de type 'Pal', par */ /* exemple), il y aura donc des bandes 'NOIR' dans l'image... */ SPIRALE_INITIALISATION; /* Initialisation dynamique de 'spirale_nombre_de_points_a_traiter'. */ SPIRALE_DEPLACEMENT(ASD1(point_courant,x),ASD1(point_courant,y)); /* Deplacement du point courant de la spirale... */ /* ATTENTION : on n'utilise pas 'SPIRALE_DEPLACEMENT_ET_PARCOURS(...)' afin de garantir le */ /* traitement de tous les points de l'image... */ SPIRALE_PARCOURS; /* Parcours de la spirale avec rotation eventuelle de PI/2 du bras courant... */ Eblock EDoI RETIF(imageR); Eblock EFonctionF #undef NOMBRE_DE_NOMBRES_A_TESTER _______________________________________________________________________________________________________________________________________ _______________________________________________________________________________________________________________________________________ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* R E C H E R C H E D U " PGCD " D E D E U X N O M B R E S : */ /* */ /*************************************************************************************************************************************/ BFonctionI DEFV(Common,DEFV(Logical,ZINT(PlusGrandCommunDiviseur_____compatibilite_20250128,FAUX))); /* Introduit le 20250128083957 afin de permettre de retablir le comportement anterieur... */ DEFV(Common,DEFV(FonctionI,PlusGrandCommunDiviseur(nombre_A,nombre_B))) /* Fonction introduite le 20081116084109... */ DEFV(Argument,DEFV(Int,nombre_A)); DEFV(Argument,DEFV(Int,nombre_B)); /* Nombres dont on cherche le "PGCD"... */ /*-----------------------------------------------------------------------------------------------------------------------------------*/ Bblock DEFV(Logical,INIT(iterer_le_calcul,VRAI)); /* Pour controler le 'Tant(...)' qui va suivre... */ DEFV(Int,INIT(nombre_A_effectif,UNDEF)); DEFV(Int,INIT(nombre_B_effectif,UNDEF)); /* Extrema des deux nombres 'A' et 'B'... */ DEFV(Int,INIT(minimum,UNDEF)); DEFV(Int,INIT(maximum,UNDEF)); /* Extrema des deux nombres 'A' et 'B'... */ DEFV(Int,INIT(PGCD_des_nombres_A_et_B,UNDEF)); /* "PGCD" des deux nombres 'A' et 'B'... */ /*..............................................................................................................................*/ EGAL(nombre_A_effectif,COND(IL_FAUT(PlusGrandCommunDiviseur_____compatibilite_20250128),NEUT(nombre_A),ABSO(nombre_A))); EGAL(nombre_B_effectif,COND(IL_FAUT(PlusGrandCommunDiviseur_____compatibilite_20250128),NEUT(nombre_B),ABSO(nombre_B))); /* Reformatage des deux nombres 'A' et 'B'... */ EGAL(minimum,MIN2(nombre_A_effectif,nombre_B_effectif)); EGAL(maximum,MAX2(nombre_A_effectif,nombre_B_effectif)); /* Extrema des deux nombres 'A' et 'B'... */ Test(IZNE(minimum)) Bblock Tant(IL_FAUT(iterer_le_calcul)) Bblock DEFV(Int,INIT(reste,REST(maximum,minimum))); /* Division euclidienne du plus grand nombre par le plus petit... */ Test(IZNE(reste)) Bblock EGAL(maximum,minimum); EGAL(minimum,reste); Eblock ATes Bblock EGAL(PGCD_des_nombres_A_et_B,minimum); EGAL(iterer_le_calcul,FAUX); Eblock ETes Eblock ETan Eblock ATes Bblock EGAL(PGCD_des_nombres_A_et_B,maximum); Eblock ETes RETU(PGCD_des_nombres_A_et_B); Eblock EFonctionI /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* R E C H E R C H E D U " PPCM " D E D E U X N O M B R E S : */ /* */ /*************************************************************************************************************************************/ BFonctionI DEFV(Common,DEFV(FonctionI,PlusPetitCommunMultiple(nombre_A,nombre_B))) /* Fonction introduite le 20081116084109... */ DEFV(Argument,DEFV(Int,nombre_A)); DEFV(Argument,DEFV(Int,nombre_B)); /* Nombres dont on cherche le "PPCM"... */ /*-----------------------------------------------------------------------------------------------------------------------------------*/ Bblock DEFV(Float,INIT(produit_des_nombres_A_et_B,MUL2(FLOT(nombre_A),FLOT(nombre_B)))); DEFV(Int,INIT(PGCD_des_nombres_A_et_B,PGCD(nombre_A,nombre_B))); DEFV(Int,INIT(PPCM_des_nombres_A_et_B,UNDEF)); /* "PGCD" et "PPCM" des deux nombres 'A' et 'B'... */ /* */ /* Le 20081212094335, le 'Int' a ete remplace par un 'Float' en ce qui concerne le produit */ /* des deux nombres A et B afin d'augmenter la capacite de cette fonction... */ /*..............................................................................................................................*/ Test(IZNE(produit_des_nombres_A_et_B)) Bblock EGAL(PPCM_des_nombres_A_et_B,INTE(DIVI(produit_des_nombres_A_et_B,FLOT(PGCD_des_nombres_A_et_B)))); /* En effet : */ /* */ /* PGCD(A,B)xPPCM(A,B) = AxB */ /* */ Test(IFEQ(MUL2(FLOT(PPCM_des_nombres_A_et_B),FLOT(PGCD_des_nombres_A_et_B)) ,produit_des_nombres_A_et_B ) ) /* Le 20081212094335, le test : */ /* */ /* Test(IZEQ(REST(produit_des_nombres_A_et_B,PGCD_des_nombres_A_et_B))) */ /* */ /* a ete remplace par ce qui precede lors du passage de 'Int' a 'Float' pour le produit */ /* de 'A' et de 'B'... */ Bblock Eblock ATes Bblock begin_nouveau_block Bblock DEFV(CHAR,INIC(POINTERc(format_EGAq____PlusPetitCommunMultiple) ,chain_Aconcaten3("le produit des deux nombres n'est pas divisible par leur 'PGCD'" ," (la capacite des 'Int's ne serait-elle pas insuffisante " ,"?)" ) ) ); PRINT_ERREUR(format_EGAq____PlusPetitCommunMultiple); /* Le 'chain_Aconcaten3(...)' est destine uniquement a faire apparaitre correctement */ /* l'espace qui precede le point d'interrogation (" ?")... */ CALZ_FreCC(format_EGAq____PlusPetitCommunMultiple); Eblock end_nouveau_block CAL1(Prer3("(PGCD(%d,%d)=%d)\n",nombre_A,nombre_B,PGCD_des_nombres_A_et_B)); Eblock ETes Eblock ATes Bblock EGAL(PPCM_des_nombres_A_et_B,produit_des_nombres_A_et_B); Eblock ETes RETU(PPCM_des_nombres_A_et_B); Eblock EFonctionI _______________________________________________________________________________________________________________________________________