Research and decomposition into prime factor of 1 to 2 ^ 64-

Share your advanced PureBasic knowledge/code with the community.
PAPIPP
User
User
Posts: 49
Joined: Mon Aug 17, 2009 10:48 pm
Location: France

Research and decomposition into prime factor of 1 to 2 ^ 64-

Post by PAPIPP »

Hello everyone

Here are the 2 prg that explore the area from 1 to 2 ^ 64-1 considering any number as a positive integer. Indeed the Zone from 2 ^ 63 to 2 ^ 64-1 in PB is signed and the numbers are seen as negative values. Prg must work in 32 and 64 bits

1) The first decomposes a number into prime factors with on each side a search area.
2) The second searches the prime numbers in a window. (Results in printn (...)

The basic number can be provided in 3 different ways
Respect the 3 possible formats "
1) $ 0FFFFFFFF00000 value from $ 1 to $ FFFFFFFFFFFFFFFE
2) 1897654390 value from 1 to 2 ^ 64-1 hence from 1 to 18446744073709551614
3) 45E10 1E0 to 1844.6744073709551614E16

Before launching one of the 2 prg you have to create the differences table in the same directory.
If possible, use the difference table of p_fact (23) which gives a better search time.
To check the improvement of the execution time create several different tables.
The one that takes the most time to create is the table of p_fact (23) close to 3mn
The other tables only take a few seconds. For example Table p-fact (19) <10 seconds
These tables are only to be created once

Place the 4 prg in the same directory.

First prg creation of tables of differences

Code: Select all

; exemple des p_fact(x)
; p_fact(x)--modulo-----------------Nb_occurrences des différences--------Taux-----------Gain
; 3__________6__________________________2_________________________________0,3333_________66,66%
; 5__________30_________________________8_________________________________0,2666_________73,33%
; 7__________210________________________48________________________________0,2285_________77,14%
; 11_________2310_______________________480_______________________________0,2078_________79,22%
; 13_________30030______________________5760______________________________0,1918_________80,81%
; 17_________510510 ____________________92160_____________________________0,18052________81,94%
; 19_________9699690____________________1658880___________________________0,17102________82,89%
; 23_________223092870__________________36495360__________________________0,16358________83,64%

Macro _q_t_
				"
EndMacro
Macro _n (__n)
_q_t_#__n#=_q_t_+Str(__n)+" "
EndMacro
Macro _Q (__Q)
_q_t_#__Q#=_q_t_+Str(__Q)+" "
EndMacro
EnableExplicit

OpenConsole("Résultats partiel")
Dim T_MODULO.l(12)
Structure colonne
;   nb.q
		prem.a
;    dif_prec.l
		dif_prec.a

;    Dif_act.l
EndStructure
Structure DIVIS
	NBPFACT.a
	PREMDIV.l
	NBSEQ.l
	MODULO.q
	;   Array TDIF.a(40000000)  ;; *** ATTENTION   A utiliser avec DATA.A et read.A  mais très lent avec p_fact(23) P_fact(19) est préférable remplacer 40 par 2
	Array TDIF.a(40000000)  
EndStructure
define SEQD.DIVIS,mess$,nb$,nbs,rest.l,i,modulo,elem,NBprem,Tdep.q,inb,inbp,prem_p,PREM_NB_PREM_AV,NB_PREM,SOM_DIF,vecteur$,NBSEQ,lvecteur,rapportq.d,RAPPORT.D
define ADRDSEQ.q,AdresdebF.q,AdresFinF.q,Adresdeb.q,delta

; **************** Réalisation du vecteur modulo npp à partir d'une table des nombres premiers des 100 premiers nombres *********
;***** Choix du premier Nb premier pour lequel le vecteur modulo sera appliqué.
;***** pour éviter la génération d'un vesteur trop important nous limiterons ce choix aux 23 premiers nombres premiers soit :2 3 5 7 11 13 17 19 23 29 31
;***** Recherche du modulo < 2*3*5*7*11=2310 éléments du vecteur
SAISIE0:
mess$+"Filtre de réduction des diviseurs"
If Len(mess$)>120
		MessageRequester("Erreur","Colonne Div max 2 3 5 7 11 13 17 19 23"+#CR$+"Relancez le prg") ;
		End
EndIf
nb$=InputRequester(mess$,"Colonne Div max 2 3 5 7 11 13 17 19 23","5") ;
If val(nb$)>23
	goto SAISIE0
EndIf
nbs=Val(nb$)
If nbs<1 Or nbs>31
		Goto SAISIE0
EndIf
rest.l=nbs%30
If rest=2 Or rest=3 Or rest=5 Or rest=7 Or rest=11 Or rest=13 Or rest=17 Or rest=19 Or rest=23
Else
	Goto SAISIE0
EndIf 
; NBPFACT=NBS
; FINSAISIE0:
Restore lab_pnbp
i=0
Modulo=1
Repeat
		Read.l ELEM
		If ELEM<>0
				T_modulo(I)=elem
				Modulo*elem
				i+1
		EndIf
Until ELEM=0 Or ELEM=>nbs
redim SEQD\TDIF(Modulo+10)
SEQD\MODULO=MODULO 
SEQD\NBPFACT=nbs
NBprem=i-1
nbs=ELEM
Dim tcol.colonne(SEQD\MODULO+2)
;*** Recherche des colonnes ayant des nb premiers ***
tcol(0)\prem=2
tcol(1)\prem=2
Tdep.q=ElapsedMilliseconds()
For inb=2 To modulo+1
		For inbp=0 To nbprem
				If inb%t_modulo(inbp)=0
						tcol(inb)\prem=2
				EndIf
		Next
Next
prem_p=0
PREM_NB_PREM_AV=0
NB_PREM=0
SOM_DIF=0
vecteur$="DIV_"+Str(nbs)+":"+#CRLF$
;****** Recherche des différence entre NB premiers *****
If CreateFile(0,"DIVA_"+Str(nbs)+".PB")         ; création d'un nouveau fichier texte...
	NBSEQ=0
	For inb=2 To modulo+1
;     tcol(inb)\nb=inb
				If tcol(inb)\prem=0 And inb>nbs
						If prem_p=0
								prem_p=inb
								PREM_NB_PREM_AV=inb
								vecteur$+"DATA.A  "+Str(inb)+","
								SEQD\PREMDIV=inb
								NBSEQ+1
						Else
								NB_PREM+1
								If nb_prem%101=0
									If nb_prem%201=0
										PrintN(_n(NB_prem)+_n(prem_p)+_n(tcol(inb)\dif_prec)+_n(som_dif)+_n(ElapsedMilliseconds()-Tdep)+_n(lvecteur))
										EndIf
										If nb_prem%5=0  ; ici tous les =101*x  c'est avec 5 que l'on obtient le meilleur résultat
											vecteur$+Str(inb-prem_p)+#CRLF$
;                  SEQD\TDIF(NBSEQ-1)=inb-prem_p
											SEQD\TDIF(NBSEQ)=inb-prem_p

											NBSEQ+1
												lvecteur=Len(vecteur$)
												WriteString(0,vecteur$) ;
												vecteur$="Data.A "
										Else
											vecteur$+Str(inb-prem_p)+#CRLF$+"Data.A "
;                  SEQD\TDIF(NBSEQ-1)=inb-prem_p
											SEQD\TDIF(NBSEQ)=inb-prem_p

											NBSEQ+1
										EndIf
										
										tcol(inb)\dif_prec=inb-prem_p
										SOM_DIF+(inb-prem_p)
;                tcol(prem_p)\Dif_act=inb-prem_p
										prem_p=inb
								Else
										tcol(inb)\dif_prec=inb-prem_p
										vecteur$+Str(inb-prem_p)+","
;                SEQD\TDIF(NBSEQ-1)=inb-prem_p
										SEQD\TDIF(NBSEQ)=inb-prem_p
										NBSEQ+1
										SOM_DIF+(inb-prem_p)
;                tcol(prem_p)\Dif_act=inb-prem_p
										prem_p=inb
								EndIf
						EndIf
				EndIf
		Next
		;  tcol(modulo+2)\dif_prec=nb_prem+modulo-(modulo+1)
		NB_PREM+1
		tcol(modulo+2)\dif_prec=PREM_NB_PREM_AV-1
		SEQD\TDIF(NBSEQ)=PREM_NB_PREM_AV-1
		SEQD\TDIF(0)=PREM_NB_PREM_AV-1
		SEQD\NBSEQ=NBSEQ
		redim SEQD\TDIF(NBSEQ+2)

;    tcol(1)\Dif_act=PREM_NB_PREM_AV-1
;    tcol(1)\nb=1
		SOM_DIF+(PREM_NB_PREM_AV-1)
		rapportq.d=100.0*(modulo-Nb_prem)/modulo
		vecteur$+Str(PREM_NB_PREM_AV-1)+",0 ;"+#CRLF$+";; Modulo="+Str(modulo)+" Nb Elements dans vecteur="+Str(NB_prem)+"  NBPFACT="+str(SEQD\NBPFACT)+" Nb sequences="+str(NBSEQ)+"  GAin="+Str(rapportq)+"%"
		
		WriteString(0,vecteur$) ;
		CloseFile(0)            ; ferme le fichier précédemment ouvert et enregistre les données
		PrintN(_n(ElapsedMilliseconds()-Tdep))
		RAPPORT.D=modulo/NB_PREM
		MessageRequester("C'est tout bon","Somme des nb du vecteur="+_n(SOM_DIF)+#CRLF$+_n(modulo)+#CRLF$+"voir le fichier pour le détail du vecteur"+#CRLF$+"Fichier: "+GetCurrentDirectory()+"DIVA_"+Str(nbs)+".PB"+#CRLF$+"Nomnre d'éléments dans le vecteur="+Str(NB_PREM)+" Rapport="+StrD(RAPPORT))
Else
		MessageRequester("Information","Impossible de créer le fichier! DIVA_"+Str(nbs)+".PB")
EndIf
; Adresdeb.l=@SEQD\NBPFACTStructure DIVIS
;   NBPFACT.a
;   PREMDIV.l
;   NBSEQ.l
;   MODULO.q
;   ;   Array TDIF.a(40000000)  ;; *** ATTENTION   A utiliser avec DATA.A et read.A  mais très lent avec p_fact(23) P_fact(19) est préférable remplacer 40 par 2
;   Array TDIF.a(40000000)  
ADRDSEQ.q=@SEQD
AdresdebF.q=@SEQD\NBPFACT
AdresFinF.q=@SEQD\MODULO+sizeof(quad)
Adresdeb.q=@SEQD\TDIF(0)
delta=AdresFinF-AdresdebF
If CreateFile(1, "MEMA_"+Str(nbs)+".bin")
	WriteData(1,ADRDSEQ ,delta )
;   WriteData(1,Adresdebf , 17)
	WriteData(1,Adresdeb , SEQD\NBSEQ+1)
	closefile(1)
Else
	messagerequester("ATTENTION", "Fichier "+ "MEMA_"+Str(nbs)+".bin non créer")
endif

Input()
CloseConsole()

DataSection
		lab_pnbp:
		Data.l 2,3,5,7,11,13,17,19,23,29,31,0
EndDataSection

DataSection
	lab_pnbp2:
	Data.L   2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97
	Data.L  101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199
	Data.L  211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293
	Data.L  307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397
	Data.L  401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499
	Data.L  503,509,521,523,541,547,557,563,569,571,577,587,593,599
	Data.L  601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691
	Data.L  701,709,719,727,733,739,743,751,757,761,769,773,787,797
	Data.L  809,811,821,823,827,829,839,853,857,859,863,877,881,883,887
	Data.L  907,911,919,929,937,941,947,953,967,971,977,983,991,997,0
EndDataSection
; ***************** Ci dessous les Nombres premiers pour les 1000 premiers nombres
; 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
; 101 103 107 109 113 127 131 137 139 149 151 157 163 167 173 179 181 191 193 197 199
; 211 223 227 229 233 239 241 251 257 263 269 271 277 281 283 293
; 307 311 313 317 331 337 347 349 353 359 367 373 379 383 389 397
; 401 409 419 421 431 433 439 443 449 457 461 463 467 479 487 491 499
; 503 509 521 523 541 547 557 563 569 571 577 587 593 599
; 601 607 613 617 619 631 641 643 647 653 659 661 673 677 683 691
; 701 709 719 727 733 739 743 751 757 761 769 773 787 797
; 809 811 821 823 827 829 839 853 857 859 863 877 881 883 887
; 907 911 919 929 937 941 947 953 967 971 977 983 991 997


Second prg Essai_form.pbf

Code: Select all

;
; This code is automatically generated by the FormDesigner.
; Manual modification is possible to adjust existing commands, but anything else will be dropped when the code is compiled.
; Event procedures needs to be put in another source file.
;

Global Window_0

Global ListIcon_0, Spin_0, String_0, Button_0, Frame_0, Frame_1, Frame_2, Text_0, Text_1, Text_2, Text_3, Text_4, Frame_3, Option_0, Option_2


Procedure OpenWindow_0(x = 0, y = 0, width = 1080, height = 700)
	Window_0 = OpenWindow(#PB_Any, x, y, width, height, "Decomposition en facteurs premiers", #PB_Window_SystemMenu)
	ListIcon_0 = ListIconGadget(#PB_Any, 20, 90, 1020, 590, "Nombre", 150)
	AddGadgetColumn(ListIcon_0, 1, "Contrôle", 150)
	AddGadgetColumn(ListIcon_0, 2, "Tps en ms", 70)
	AddGadgetColumn(ListIcon_0, 3, "Décomposition  en facteurs premiers", 700)
	Spin_0 = SpinGadget(#PB_Any, 920, 50, 50, 20, 0, 100, #PB_Spin_ReadOnly | #PB_Spin_Numeric)
	String_0 = StringGadget(#PB_Any, 750, 50, 160, 20, "$80123456789ABCDE")
	Button_0 = ButtonGadget(#PB_Any, 980, 50, 70, 20, "OK/FIN")
	Frame_0 = FrameGadget(#PB_Any, 30, 0, 1000, 20, " Donnez un nombre >1 et <$FFFFFFFFFFFFFFFE  en décimal en Hexa ou en format scientifique 2E10 et la zone à explorer + OU - entre 0 et 100")
	Frame_1 = TextGadget(#PB_Any, 45, 50, 275, 25, "Recherche manuelle du vecteur des différences")
	Frame_2 = TextGadget(#PB_Any, 45, 25, 275, 25, "Recherche automatique du vecteur des différences")
	Text_0 = TextGadget(#PB_Any, 340, 30, 110, 25, "")
	Text_1 = TextGadget(#PB_Any, 610, 30, 130, 25, "")
	Text_2 = TextGadget(#PB_Any, 340, 60, 110, 25, "")
	Text_3 = TextGadget(#PB_Any, 610, 60, 130, 25, "")
	Text_4 = TextGadget(#PB_Any, 460, 40, 130, 25, "")
	Frame_3 = TextGadget(#PB_Any, 750, 25, 270, 25, "Nombre à décomposer               Zone à explorer")
	Option_0 = OptionGadget(#PB_Any, 30, 30, 10, 10, "")
	SetGadgetState(Option_0, 1)
	Option_2 = OptionGadget(#PB_Any, 30, 55, 10, 10, "")
EndProcedure 
Third prg Decomposing a number and its zone into prime factors.

Code: Select all

Macro _q_t_
				"
EndMacro
Macro _n (__n)
_q_t_#__n#=_q_t_+Str(__n)+" "
EndMacro
Macro _Q (__Q)
_q_t_#__Q#=_q_t_+Str(__Q)+" "
EndMacro
EnableExplicit
Macro _HHQ (_HHQ,_pr="$")
	_PR+RSet(Hex(PeekQ(@_HHQ),#PB_Quad),16,"0")
EndMacro

EnableExplicit
; DisableDebugger
; 2 3 5 7 11 13 17 19 23
GLOBAL DIM TABTERMIN.Q(4)
structure ldec 
	DIFF.l
	IND.l
endstructure
structure synchro 
	structureunion
		SYNCDEC.ldec
		SYNCALP.q
	EndStructureUnion 
	
EndStructure  
Structure DIVIS
	NBPFACT.a
	PREMDIV.l
	NBSEQ.l
	MODULO.q
	Array TDIF.a(37000000)  ;; *** ATTENTION   A utiliser avec DATA.A et read.A  
EndStructure
structure INFOTEMP
	NBASE$
	NBASE.Q
	NBASEHEX$
	NBASEDIFB.q
	NBASEIND.q
	NBASEDIFS.q
	NBASERAC.Q
	NBASEP.Q
	NBASEPHEX$
	NBASEPDIF.Q
	NBASEPIND.q
	NBASEPRAC.q
	
	NPLAGE$
	NPLAGE.Q
	NPLAGEHEX$
	
	NPLAGEMAX$    
	
	NBASEM$
	NBASEM.Q
	NBASEMHEX$
	NBASEMP.Q
	NBASEMPHEX$
	NBASEMIND.q
	NBASEMRAC.Q
	
	;   FUTBASE$
	;   FUTBASED.D
	;   FUTBASE.q
	;   FUTBASEHEX$
	;   ;     FUTBASEP.Q
	;   ;     FUTBASEPHEX$
	;   FUTBASEIND.q
	;   FUTBASERAC.Q
	
endstructure 
STRUCTURE INFOCALC
	NBASE$
	NBASE.Q
	NBASEHEX$
	NBASEDIFB.q
	NBASEIND.q
	NBASEDIFS.q
	NBASERAC.Q
	NBASEP.Q
	NBASEPHEX$
	NBASEPDIF.Q
	NBASEPIND.q
	NBASEPRAC.q
endstructure  
global INFOSAISIE.INFOTEMP

Global result$,rest,SEQD.DIVIS,delta_deb.q
; Global nbs.l,NBSEQ.l,SEQD.DIVIS,LIMIT$="7FFFFFFFFFFFFFFF",LIMITQ.Q=$7FFFFFFFFFFFFFFF,RACLIM.d=SQR(LIMITQ)

Define B2DIVIS.q,B2PAS,quotient.q,B1MIN.Q=1E12,pos, logB1MIN, logmax, rmes,B1MIN_DEP.Q,ZONEP.Q,presultat$,resultat$
Define MAX.Q=B1MIN+1E4,nbg$,nbd$,pose.l,t_ind.l,t_col.l,t_ind_dep.l,MAXMAXDIV.q,RAC2.Q,B1MINRAC2.Q,nbseqp,B2IND_MAXDIV,DIF_MAXDIV
Define ind_dep,DIFF,FLAGFIN,IND_NB,CENTM,B2DIVISM,B2INDDD, B2DIVIS$,B2MAXDIV.q,dep_time.q,cent,nbseq_1.q,P_MAXDIV.q,MAXHEX$
Define nb$,nb.q,l2nb.d,nbl2.q,DIVMAX.q,NBREC.q,DIVIS.q,i,ipas,fact_prem$,j,deb1.q,mess$,quotientp.q,iprem,indt,Restd.q,ind.l,pas,idivis,FICHIER$
Global nbs.l,NBSEQ.l,SEQD.DIVIS,LIMIT$="7FFFFFFFFFFFFFFF",LIMITQ.Q=$7FFFFFFFFFFFFFFF,RACLIM.d=SQR(LIMITQ),ecart_MAX.l=10
Dim Tab.q(65) ;;; max = pow(2,64)-1 donc 64 éléments au max
Define *Tab=@Tab(), ADRDSEQ.q,AdresdebF.q,AdresFinF.q,Adresdeb.q,delta,DIVMAXD.d,flag00,NB_DEB.q
; 2 3 5 7 11 13 17 19 23
Dim Nbprem(10)
Nbprem(0)=2:Nbprem(1)=3:Nbprem(2)=5:Nbprem(3)=7:Nbprem(4)=11:Nbprem(5)=13:Nbprem(6)=17:Nbprem(7)=19:Nbprem(8)=23:Nbprem(9)=29
OpenConsole()

procedure CHARGE_SEQD(FICHIER$)
	EnableExplicit
	protected deb00.q , ADRDSEQ.q,AdresdebF.q,AdresFinF.q,Adresdeb.q,delta,DIVMAXD.d
	deb00.q=ElapsedMilliseconds()
	;************************************************************************************************************************************
	ADRDSEQ=@SEQD
	AdresdebF=@SEQD\NBPFACT
	AdresFinF=@SEQD\MODULO+SizeOf(quad)
	Adresdeb=@SEQD\TDIF(0)
	delta=AdresFinF-AdresdebF
	
	If OpenFile(2,FICHIER$);,#PB_File_SharedRead|#PB_File_NoBuffering)
		ReadData(2,ADRDSEQ ,delta)
		;     ReDim SEQD\TDIF(SEQD\NBSEQ+1) ;;; cette instruction crée une erreur en cas d'augmentation de la dimension
		ReadData(2, Adresdeb,SEQD\NBSEQ+1)
		CloseFile(2)
	EndIf
	;   deb0.q=ElapsedMilliseconds()
	delta_deb.q=ElapsedMilliseconds()-deb00
	EnableExplicit
	
EndProcedure
procedure.q SYNCHRO(NBASYNCHRO.Q)
	protected restd.q,t_ind.q,t_col,ind,INFO.SYNCHRO,t_ind_dep,MODULO.Q
	EnableExplicit
	MODULO.q=SEQD\MODULO 
	restd.q=0
	enableasm 
	MOV ecx,dword[p.v_MODULO]  ;;;; la division euclidienne X=kQ+R avec R<Q nous oblige à utiliser une astuce
	XOR EDX,EDX                ;;;; pour éviter avec un diviseur trop petit et un dividente trop grand d'avoir un reste de type qword or EDX est de type dword 
	MOV eax,dword[p.v_NBASYNCHRO+4]
	DIV ecx
	;    MOV dword[v_quotientp],eax
	MOV eax,dword[p.v_NBASYNCHRO]
	DIV ecx
	mov dword[p.v_restd],edx
	disableasm 
	; 
	; ;   restd=NBASYNCHRO%SEQD\MODULO 
	t_ind=0
	t_col=1
	
	For ind=0 To SEQD\MODULO 
		If restd<=t_col
			t_ind_dep=t_ind
			Break
		Else 
			t_col+seqd\TDIF(t_ind)
			t_ind+1
		EndIf
	Next
	INFO\SYNCDEC\DIFF=t_col-restd
	INFO\SYNCDEC\IND=t_ind_dep
	procedurereturn info\SYNCALP
	DisableExplicit
endprocedure  

Procedure.s HEX2DEC(HEXS.S)
	EnableExplicit
	Static Dim t_rest.a(1000)
	Protected DIVIDENDE$,vald.q,longt,resultat$,DIVIDP$,DIVIDPR$,QUOTP.q,RESTP.q,quotp$,j,ii,DIVIDP.Q,Irest
	DIVIDENDE$=LTrim(UCase(HEXS))
	vald.q=Val("$"+DIVIDENDE$)
	longt=Len(DIVIDENDE$)
	If vald>0 And longt<17
		resultat$=Str(vald)
	Else  
		Irest=0
		DIVIDP$=""
		DIVIDPR$=""
		quotp$=""
		Repeat 
			For ii=1 To longt
				DIVIDP$=DIVIDPR$+Mid(DIVIDENDE$,ii,1)
				DIVIDP.Q=Val("$"+DIVIDP$)
				EnableASM
				MOV ax,word [p.v_DIVIDP]  
				MOV cl,10
				;   idiv Cl 
				DIV cl  ; utilise moins de cycles machine que idiv
				MOV  [p.v_QUOTP],al
				MOV [p.v_RESTP],AH
				DisableASM
				
				DIVIDPR$=HEX(RESTP)
				quotp$+HEX(QUOTP)
			Next 
			t_rest(Irest)=RESTP
			Irest+1 
			DIVIDENDE$=QUOTP$
			longt=Len(DIVIDENDE$) 
			DIVIDP$=""
			DIVIDPR$=""
			quotp$=""
			
		Until Val("$"+ dividende$)=0
		For j=Irest-1 To 0 Step-1
			resultat$+Str( t_rest(j))
			t_rest(j)=0
		Next
	EndIf
	ProcedureReturn  resultat$
	DisableExplicit
EndProcedure

Procedure.s DEC2HEX(DECI.S)
	EnableExplicit
	Static Dim t_rest.a(1000)
	Protected DIVIDENDE$,vald.q,longt,resultat$,DIVIDP$,DIVIDPR$,QUOTP.q,RESTP.q,quotp$,i,j,ii,DIVIDP.Q,Irest
	DIVIDENDE$=UCase(DECI)
	longt=Len(DIVIDENDE$)
	If Val(DIVIDENDE$)=>0  And longt<20
		vald.q=Val(DIVIDENDE$)
		resultat$=Hex(vald)
	Else  
		irest=0
		DIVIDP$=""
		DIVIDPR$=""
		quotp$=""
		Repeat 
			For ii=1 To longt
				DIVIDP$=DIVIDPR$+Mid(DIVIDENDE$,ii,1)
				DIVIDP.Q=Val(DIVIDP$)
				EnableASM
				MOV ax,word [p.v_DIVIDP]  
				MOV cl,16
				;   div Cl 
				DIV Cl  ; utilise moins de cycles machine que idiv
				MOV  [p.v_QUOTP],al
				MOV [p.v_RESTP],AH
				DisableASM
				
				DIVIDPR$=Str(RESTP)
				quotp$+Str(QUOTP)
			Next 
			t_rest(Irest)=RESTP
			Irest+1 
			DIVIDENDE$=QUOTP$
			longt=Len(DIVIDENDE$) 
			DIVIDP$=""
			DIVIDPR$=""
			quotp$=""
			
		Until Val(dividende$)=0
		For j=Irest-1 To 0 Step-1
			resultat$+Hex( t_rest(j))
			t_rest(j)=0
		Next
	EndIf
	ProcedureReturn  resultat$
	DisableExplicit
EndProcedure
PROCEDURE CALCUL(_NB.S,*SCALCUL.INFOCALC )
	EnableExplicit
	; PROCEDURE CALCUL(_NB.S,SCALCUL.INFOCALC )
	static ADR1.q,ADR2.q,ADR3.Q,ADR4.q,FLAG=0 
	PROTECTED POSE,BASEMIN.q,nbasehex$,lnbh,A1.q,A2.q,NBASE.Q,DIFFB.q,difd.d,limitd.d,K.d,RACK.d,DIVMAX.q,NBASEP.q,SYNCDIVIS.SYNCHRO
	PROTECTED MAX_DIV.SYNCHRO,DIVMAXD.d,DIVMAXPD.d,DIVMAXP.q
	if mid(_NB,1,1)="$"
		nbasehex$=right(_NB,len(_NB)-1)
	else
		POSE=FindString(_NB,"E")
		If pose>0
			BASEMIN.q=ValD(_NB)
			nbasehex$=_HHQ(basemin,"")
		Else 
			nbasehex$=dec2hex(_NB)   
		endif 
	EndIf 
	lnbh=len(nbasehex$)
	nbasehex$=right("0000000000000000"+nbasehex$,16)
	
	if lnbh>16 OR nbasehex$>"FFFFFFFFFFFFFFFE" 
		INFOSAISIE\nbase$=""
		INFOSAISIE\NPLAGE$=""
		ProcedureReturn 2 
		Goto FIN
	EndIf
	;;;;; recherche d'une racine carré de nb à partir de la différence 
	A1.q=val("$"+mid(nbasehex$,9,16))
	A2.q=val("$"+mid(nbasehex$,1,8))
	;   debug _n(A1)+_n(A2)
	
	NBASE.q=0 
	DIFFB.Q=0
	EnableASM  ;; ici recherche en cours pour évaluer le plus précisément la racine carré des nombres >2^63-1
	mov eax,dword[p.v_A1]
	mov dword[p.v_NBASE],eax 
	mov edx,dword[p.v_A2]
	mov dword [p.v_NBASE+4],edx
	sub eax,dword[v_LIMITQ] 
	sbb edx,dword[v_LIMITQ+4]
	mov dword[p.v_DIFFB],eax 
	mov dword [p.v_DIFFB+4],edx
	if nbasehex$>LIMIT$
		;;;;; recherche d'une racine carré de nb à partir de la différence 
		difd.d=DIFFB 
		limitd.d=limitq
		K.d=DIFd/LIMITd ;;;; k est défini sur la plage -1 +1 pour une plage div de +$7FFFFFFFFFFFFFFF à -$7FFFFFFFFFFFFFFF
		RACK.D=SQR(1+K) ;;;; plage de 0 sqr(2)
		DIVMAXD.d=RACLIM *RACK
		DIVMAX.q=divmaxd  ;;limite de recherche des facteurs premiers  de la base
	Else 
		DIVMAX=SQR(VAL("$"+nbasehex$))
	endif  
	;   IF NBASE < SEQD\PREMDIV
	SYNCDIVIS\SYNCALP=SYNCHRO(NBASE)
	*SCALCUL\NBASEP=NBASE+SYNCDIVIS\SYNCDEC\DIFF 
	*SCALCUL\NBASEDIFS=SYNCDIVIS\SYNCDEC\DIFF
	*SCALCUL\NBASEIND=SYNCDIVIS\SYNCDEC\IND
	*SCALCUL\NBASEPHEX$=_HHQ(*SCALCUL\NBASEP,"")
	*SCALCUL\NBASE=NBASE
	*SCALCUL\NBASE$=_NB
	*SCALCUL\NBASEHEX$=nbasehex$
	*SCALCUL\NBASERAC=DIVMAX
	*SCALCUL\NBASEDIFB=DIFFB
	; *SCALCUL\NBASEIND=INDBASE
	; *SCALCUL\NBASEP=NBASEP
	IF NBASE>0 AND NBASE<SEQD\PREMDIV
		*SCALCUL\NBASEP=SEQD\PREMDIV
	endif  
	*SCALCUL\NBASEPHEX$=_HHQ(*SCALCUL\NBASEP,"")
	SYNCDIVIS\SYNCALP=SYNCHRO(*SCALCUL\NBASEP)
	*SCALCUL\NBASEPDIF=SYNCDIVIS\SYNCDEC\DIFF 
	*SCALCUL\NBASEPIND=SYNCDIVIS\SYNCDEC\IND
	difd.d=SYNCDIVIS\SYNCDEC\DIFF
	K.d=DIFd/*SCALCUL\NBASEP ;;;; 
	RACK.D=SQR(1+K)          ;;;; plage de 0 sqr(2)
	DIVMAXPD.d=*SCALCUL\NBASERAC *RACK
	DIVMAXP.q=divmaxpd  ;;
	*SCALCUL\NBASEPRAC=DIVMAXP
	FIN:
	DisableExplicit
endprocedure  
PROCEDURE.l EXTRINFO(NBE$)  
	protected pose, basmin.q,nbasehex$,lnbh,A1.q,A2.q,NBASE.Q,DIFFE.Q,difd.d,limitd.d,K.d,RACK.d,DIVMAXD.d,DIVMAX.q,NB$,DIFFB.Q
	;   static FLAG=0 
	SHARED INF_CAL.INFOCALC, INF_CAL3.INFOCALC
	protected NBl3$,NB_A_TESTER.Q,NB_DE_DIVISEUR_MPAR.Q,NB_DE_DIVISEUR_MAX.d,KEFFICACE.D,NBDIVISIONE.D,LOG2X.d,RET0
	EnableExplicit
	global T1.Q=ElapsedMilliseconds()
	;   select FLAG 
	;     case 0
	;   if INFOSAISIE\nbase$=""
	ret0=calcul (NBE$,INF_CAL)
	CopyMemory(INF_CAL,INFOSAISIE,SIZEOF(INFOCALC))
	;   endselect
	;   PRiNTN("X PASSAGE  "+_n(FLAG)+_s(NBE$))
	;   FLAG+1 
	
	;   ProcedureReturn 0
	; FIN:
	; logB1MIN=Log10(B1MIN)
	; logmax=Log10(max-B1MIN)
	; If logB1MIN+logmax>22
	;   rmes=MessageRequester(" ATTENTION Temps très long","Oui=>continuez Non=>donnez autre zone",#PB_MessageRequester_YesNo)
	;   If Rmes = 6        ; le bouton Oui a été choisi (Resultat = 6)
	;   Else               ; le bouton Non a été choisi (Resultat = 7)
	;     Goto SAISIE2
	;   EndIf
	; EndIf
	procedurereturn ret0
	DisableExplicit
endprocedure

Procedure.s choixdiv()
	Protected     COUR_DIR$,Filtre$,fichier$,Tfichier,fichierp$,leftfich$,RIGHTfich$,deb00.q,deb0.q,ADRDSEQ.q,AdresdebF.q,AdresFinF.q,Adresdeb.q,delta
	EnableExplicit
	COUR_DIR$ = GetCurrentDirectory()
	Filtre$ = "MEMA (MEMA_*.BIN)|MEMA_*.BIN;|Tous les fichiers (*.*)|*.*"
	fichier$=OpenFileRequester("Choisissez un fichier MEMA ou annulez", COUR_DIR$+"\MEMA_17.BIN", Filtre$, 0)
	fichierp$=UCase(Trim(GetFilePart(fichier$)))
	Tfichier=FileSize(Fichier$)
	leftfich$=Left(fichierp$,5)
	RIGHTfich$=Right(fichierp$,4)
	If Tfichier<1 Or Left(fichierp$,5)<>"MEMA_" Or Right(fichierp$,4) <>".BIN"
		MessageRequester( "ATTENTION", "fichier vide ou le nom n'est pas conforme "+ _n(Tfichier)+"  "+_s(fichierp$))
		End
	EndIf
	CHARGE_SEQD( FICHIER$)
	EnableExplicit
EndProcedure
procedure RECHERCHE_AUTO()
	EnableExplicit
	protected file$,pose,valfilt,Valfil,filem$,Repertoire$
	Repertoire$=GetCurrentDirectory()
	Valfil=0
	If ExamineDirectory(0, Repertoire$, "mema_*.bin")  
		While NextDirectoryEntry(0)
			If DirectoryEntryType(0) = #PB_DirectoryEntry_File
				file$=DirectoryEntryName(0)
				if UCase(left(file$,5))="MEMA_"
					pose=findstring(file$,".")
					valfilt=val(mid(file$,6,pose-6))
					if valfilt>valfil 
						valfil=valfilt
						filem$=file$
					endif
					;           debug file$
				endif
			EndIf
		Wend
		FinishDirectory(0)
	EndIf
	if filem$=""
		messagerequester("Pas de fichier MEMA_XX.bin","executer dans le même répertoire de prg de création")
		end
	endif
	CHARGE_SEQD(Repertoire$+FILEM$)
	;  ProcedureReturn filem$
EndProcedure 
PROCEDURE SAISIEBASE(nb$)
	protected mess$,pos,NBASE$,NPLAGE$,reto.l,NBASE.q,DIFFF.Q,NPLAGEMAX$
	EnableExplicit
	mess$=""
	NBASE$=Trim(nb$)
	reto.l=EXTRINFO(NBASE$)
	if retO>0
		MESS$="Respecter les 3 formats possibles "+#CRLF$+" $FFFFFFFFF00000 de 1 à $FFFFFFFFFFFFFFFE "+#CRLF$+" 1897654390 de 1 à 2^64-1"
		MESS$+#CRLF$+" 45E10 de 1E0 à 1844,6744073709551614E16"
		messagerequester("Attention", MESS$) 
		end
	endif 
	;;;;;;************* Recherche de la plage max possible à utiliser *****************
	NBASE.q=INFOSAISIE\NBASE
	DIFFF.Q=0
	mov eax,$FFFFFFFE
	mov edx,$FFFFFFFF
	sub eax,dword[p.v_NBASE] 
	sbb edx,dword[p.v_NBASE+4]
	mov dword[p.v_DIFFF],eax 
	mov dword [p.v_DIFFF+4],edx
	NPLAGEMAX$=_HHQ(DIFFF,"" )
	
	INFOSAISIE\NPLAGEMAX$=NPLAGEMAX$
	;;;*******************************  recherche de la plage à explorer   **************************
	;   if EXTRINFO(NPLAGE$)
	;     goto saisie2
	;   endif 
	;   INFOSAISIE\NPLAGEMAX$=NPLAGEMAX$
	DisableExplicit
endprocedure

enableExplicit
XIncludeFile "ESSAI_FORM.pbf"
define  wwe,quit,ECART_MAX$,MESSAG$,nbhex$,lnbh,NBo.q,jjj,NBCONT$,A1.q,A2.q,DIFFQQ.Q,difd.d,limitd.d,K.d,RACK.D,Kpj,NBPR$,NBRECH$,NBREC$,flag2

OpenWindow_0()
; while Window_0_Events(WaitWindowEvent() )
; wend 
Repeat
	wwe = WaitWindowEvent()
	Select wwe                       
		Case #PB_Event_CloseWindow     
			quit=1
		Case #PB_Event_Gadget 
			;       text0$=getgadgettext(TEXT_0)
			if flag00=0
				Select EventGadget()         
					Case   Button_0
						flag00+1
						;           debug eventGadget()
						if GetGadgetState(Option_0)=1
							recherche_AUTO()
						else 
							CHOIXDIV()
						endif 
						setgadgettext(TEXT_0,"P_Fact="+str(SEQD\NBPFACT))
						setgadgettext(TEXT_1,"Modulo="+str(SEQD\MODULO))
						setgadgettext(TEXT_2,"P_divis="+str(SEQD\PREMDIV))
						setgadgettext(TEXT_3,"Nb_seq="+str(SEQD\NBSEQ))
						setgadgettext(TEXT_4,"Time Prep="+str(delta_deb)+"ms")
						;           debug _s( GetGadgetText(Spin_0))
						nb$=GetGadgetText(String_0)
						SAISIEBASE(nb$)
						ecart_max=val(GetGadgetText(Spin_0))
						ECART_MAX$=_hhq(ECART_MAX,"")
						;           printn(_n(ecart_max)+_s(ECART_MAX$)+_s(infosaisie\NPLAGEMAX$))
						; if ECART_MAX$>infosaisie\NPLAGEMAX$
						;  MESSAG$="Le nombre à décomposer=$"+infosaisie\NBASEHEX$+chr(10) +"+ la plage de recherche demandée=$"+ECART_MAX$
							; MESSAG$+CHR(10)+"Dépassent les limites de la machine >$FFFFFFFFFFFFFFFF"+chr(10)+"Plage de recherche diminuée="+infosaisie\NPLAGEMAX$
							;messagerequester("ATTENTION",MESSAG$)
							;ECART_MAX=VAL("$"+infosaisie\NPLAGEMAX$)
							;SetGadgetText(Spin_0,str(ECART_MAX))
							
						;endif  
;             if infosaisie\NBASE>0 and (infosaisie\NBASE-ECART_MAX)<0  ;;;;
;               MESSAG$="Le nombre à décomposer=$"+infosaisie\NBASEHEX$+chr(10) +"- la plage de recherche demandée=$"+ECART_MAX$
;               MESSAG$+CHR(10)+"Dépassent les limites de la machine <0 "+chr(10)+"Plage de recherche diminuée="+str(infosaisie\NBASE-1)
;               messagerequester("ATTENTION",MESSAG$)
;               ECART_MAX=infosaisie\NBASE-1
;               SetGadgetText(Spin_0,str(ECART_MAX))
;             endif  
						
						;;;;**************************************************************************************************************************************
						;           nb$="$"+infosaisie\NBASEHEX$
						nb$=infosaisie\NBASE$
						if findstring(nb$,"E")>0 and mid(nb$,1,1)<>"$"
							nb$=str(infosaisie\NBASE)
						endif  
						if mid(nb$,1,1)="$"
							nbhex$=right(nb$,len(nb$)-1)
						else 
							nbhex$=dec2hex(nb$)   
						endif 
						;;;;; ******************* mise en forme du nombre à décomposer et recherche d'une racine carrée****************************************
						lnbh=len(nbhex$)
						if lnbh>16 OR nbhex$>"FFFFFFFFFFFFFFFE"
							;             Goto saisie
						EndIf
						;;;***********************************************************************************************************************************
						;;;******************************************************* FIN DE LA SAISIE **********************************************************
						;;;***********************************************************************************************************************************
						;    ecart_max.l=seqd\PREMDIV-1
						;    ecart_max=10
						NBo.q=val("$"+nbhex$)
						nbo-ecart_max
						for jjj=-ecart_max to ecart_max   
							nbhex$=_hhq(nbo,"")
							if mid(nb$,1,1)="$"
								nb$=_hhq(nbo)
							else 
								nb$=HEX2DEC(nbhex$)
							endif
							gosub subrout  ;;;  ListView_1 
															;             AddGadgetItem( ListView_1, jjj+ecart_max,nb$ +Chr(10)+NBCONT$+Chr(10)+Str(ElapsedMilliseconds()-deb1)+"ms"+chr(10)+fact_prem$)
							AddGadgetItem( ListIcon_0, -1,nb$ +Chr(10)+NBCONT$+Chr(10)+Str(ElapsedMilliseconds()-deb1)+"ms"+chr(10)+fact_prem$)
							SmartWindowRefresh(Window_0, #True ) 
							;             printn(nb$ +Chr(10)+NBCONT$+Chr(10)+Str(ElapsedMilliseconds()-deb1)+"ms"+chr(10)+fact_prem$)
							
							nbo+1
							nb=nbo
						next
						
					Case ListIcon_0
					Case Spin_0
					case  String_0  
					case Option_0 , Option_2 
						if GetGadgetState(Option_0)=1
							recherche_AUTO()
							setgadgettext(TEXT_0,"P_Fact="+str(SEQD\NBPFACT))
							setgadgettext(TEXT_1,"Modulo="+str(SEQD\MODULO))
							setgadgettext(TEXT_2,"P_divis="+str(SEQD\PREMDIV))
							setgadgettext(TEXT_3,"Nb_seq="+str(SEQD\NBSEQ))
							setgadgettext(TEXT_4,"Time Prep="+str(delta_deb)+"ms")
							
							;           else 
							;             CHOIXDIV()
						endif 
						
				EndSelect
			Else 
				delay(10)
				if EventGadget()= Button_0
					quit+1
				endif  
			endif 
	EndSelect
	SmartWindowRefresh(Window_0, #True ) 
	;   AddGadgetItem( ListIcon_0, -1,nb$ +Chr(10)+NBCONT$+Chr(10)+Str(ElapsedMilliseconds()-deb1)+"ms"+chr(10)+fact_prem$)
	
Until quit > 0
CloseWindow(Window_0)
printn("C'est fini")
Input()
CloseConsole()

End
;;;***********************************************************************************************************************************
;;;******************************************************* Subroutine ****************************************************************
;;;***********************************************************************************************************************************
subrout:
deb1.q=ElapsedMilliseconds()
; nbhex$=ReplaceString(space(16-lnbh)," ","0")+nbhex$
A1.q=val("$"+mid(nbhex$,9,16))
A2.q=val("$"+mid(nbhex$,1,8))
NB.q=0 
DIFFQQ.Q=0
EnableASM  ;; ici recherche en cours pour évaluer le plus précisément la racine carré des nombres >2^63-1
mov eax,dword[v_A1]
mov dword[v_nb],eax 
mov edx,dword[v_A2]
mov dword [v_nb+4],edx
sub eax,dword[v_LIMITQ] 
sbb edx,dword[v_LIMITQ+4]
mov dword[v_DIFFQQ],eax 
mov dword [v_DIFFQQ+4],edx
;;;;; recherche d'une racine carré de nb à partir de la différence 
difd.d=DIFFQQ 
limitd.d=limitq
K.d=DIFd/LIMITd ;;;; k est défini sur la plage -1 +1 pour une plage div de +$7FFFFFFFFFFFFFFF à -$7FFFFFFFFFFFFFFF
RACK.D=SQR(1+K)
DIVMAXD.d=RACLIM *RACK
DIVMAX=divmaxd  ;;limite de recherche des facteurs premiers
if divmax<4294967296
		divmax+1
endif 

IF DIVMAX<sqr(SEQD\NBPFACT)
	DIVMAX=SQR(SEQD\NBPFACT)
endif  
;   printn(_n(nb)+_n(DIVMAX)+_hq(DIVMAX)+_n(divmax)+_d(divmaxd))
; printn(_q(DIVMAX))
;*********************************************************************************************************************************************************

NBREC.Q=1
DIVIS=2
i=0
fact_prem$=nb$+"="
; deb1.q=ElapsedMilliseconds()
;************************************** Recherche des diviseurs premiers qui se trouvent dans p_fact(x) ***********************
iprem=0
DIVIS=nbprem(iprem)
indt=0
NB_DEB=NB
if nb<>0 ;  or nb<>1
While DIVIS<=SEQD\NBPFACT And DIVIS<=DIVMAX 
	enableasm
	MOV ecx,dword[v_DIVIS]  ;;;; la division euclidienne X=kQ+R avec R<Q nous oblige à utiliser une astuce
	XOR EDX,EDX             ;;;; pour éviter avec un diviseur trop petit et un dividente trop grand d'avoir un reste de type qword or EDX est de type dword 
	MOV eax,dword[v_nb+4]
	DIV ecx
	MOV dword[v_quotientp],eax
	MOV eax,dword[v_nb]
	DIV ecx
	CMP edx,0
	JNZ @f
	MOV edx,dword[v_quotientp]
	MOV dword[v_nb+4],edx
	MOV dword[v_nb],eax
	;************************************************ Recherche de la racine carré ***************************************************************
	FILD qword[v_nb]
	FSQRT
	; !FISTTP dword [v_DIVMAX] ; avec arrondi si vous décommentez cette instruction commentez la précédente
	;                           et laissez le ! car l'instruction FISTTP n'est pas reconnue par PureBasic avec !FISTTP c'est bon !!!!
	FISTP qword[v_DIVMAX] ; sans arrondi
	tab(indt)=DIVIS
	indt+1
	DIVMAX=Sqr(nb)
	JMP lab0
	!@@:
	iprem+1
	DIVIS=nbprem(iprem)
	!lab0: 
	disableasm 
Wend

;****************  Partie principale pour le reste de la décomposition **************************************
If DIVIS<=seqd\PREMDIV
	DIVIS=SEQD\PREMDIV
EndIf
ipas=0
;************************************************************************************************************************
pas=SEQD\TDIF(1)
idivis=1
NBSEQ=SEQD\NBSEQ
;   ind=indt*8
Repeat
	;   printn(_n(divis)+_n(pas)+_n(idivis))
	;     ;Le nom de @@: signifie étiquette anonyme,vous pouvez avoir défini un grand nombre d'entre eux dans la source.
	;     ;Symbole @b(ou l'équivalent @r)le plus proche des références du label précédent anonyme
	;     ;,symbole @f références plus proche de l'étiquette suivante anonyme.
	;     ;Ces symboles spéciaux sont insensibles à la casse.
	;;*******************************  TESTS EN ASM ********************************************************************
	;*************************************** Division d'un nombre de 64 bits par un nombre de 32 bits ******************************************
	EnableASM
	MOV ecx,dword[v_DIVIS]  ;;;; la division euclidienne X=kQ+R avec R<Q nous oblige à utiliser une astuce
	XOR EDX,EDX             ;;;; pour éviter avec un diviseur trop petit et un dividente trop grand d'avoir un reste de type qword or EDX est de type dword 
	MOV eax,dword[v_nb+4]
	DIV ecx
	MOV dword[v_quotientp],eax
	MOV eax,dword[v_nb]
	DIV ecx
	CMP edx,0
	JNZ @f
	;     MOV dword[v_reste],edx
	; quotientp
	
	MOV edx,dword[v_quotientp]
	MOV dword[v_nb+4],edx
	MOV dword[v_nb],eax
	;*************************************************************************************************************************************
	;**** Recherche de la racine carré  pas de pb ici le prg à trouver un diviseur qui n'est pas négatif car (2^64-2)/2 <(2^63-1)*********
	;*************************************************************************************************************************************
	FILD qword[v_nb]
	FSQRT
	; !FISTTP dword [v_DIVMAX] ; avec arrondi si vous décommentez cette instruction commentez la précédente
	;                           et laissez le ! car l'instruction FISTTP n'est pas reconnue par PureBasic avec !FISTTP c'est bon !!!!
	FISTP qword[v_DIVMAX] ; sans arrondi
												;                          ;*********************************************** Affectation de la valeur du DIViseur dans la table *******************************************
												;     MOV ecx, [v_DIVIS]; à decommenter si ecx est effacée
												;     mov ebx, [p_Tab]
												;     mov edx, [v_ind]
												;     add ebx,edx
												;     mov[ebx],ecx
												;     add edx,8
												;     mov[v_ind],edx
	DisableASM
	tab(indt)=DIVIS   ;;;; Plus rapide que l'option ASM
	indt+1
	If nb<=1:Break:EndIf
	EnableASM
	;     JMP lab#MacroExpandedCount
	JMP lab
	!@@:
	MOV edx,dword[v_pas]
	ADD dword[v_DIVIS],edx  ; pas de PB l'addition est réalisée en valeur absolue 
	ADC dword[v_DIVIS+4],0  ; pas de PB l'addition est réalisée en valeur absolue 
													;     donc $FFFFFFFF =>4294967295 donc pas de risque de dépassement sqr(pow(2,63)-1))=>3037000499,9760496922867524030306 <4294967295
	DisableASM
	;********************************************************************************************************************************************************
	;********************************************************************************************************************************************************
	; ;***********************************  Pour accélerer encore l' algo  *******************************
	idivis+1
	If idivis=NBSEQ+1  ;;; inutil de passer en ASM  voir ci dessous c'est plus long de 5 à 6 secondes  sur la recherche de 9223372036854770999
		idivis=1
	EndIf
	pas=SEQD\TDIF(idivis)
	EnableASM
	;     mov EAX, dword [v_idivis]
	;     xor edx,edx
	;     mov ECX, dword [v_NBSEQ]
	;     div ECX 
	;     mov  dword [v_idivis],EDX
	;     idivis=idivis%NBSEQ
	;************************************  Pour accélerer encore l' algo vous pouvez décommentez les 7 lignes PB précedentes ******************************
	;*******************************************************************************************************************************************************
	;     !lab#MacroExpandedCount:
	!lab:
	;       If DIVIS>DIVMAX Or DIVIS<0:Break:EndIf
Until DIVIS>DIVMAX    
;    ForEver
;*************************************************Fin macro decompose2****************************************************************************************************
;    printn(_q(divis)+_q(DIVMAX)+_Q(NB)+_s(nbhex$) +_hhq(NB,"")+"  "+_hhq(DIVMAX))
if nb<>1
	tab(indt)=NB
Else 
	indt-1
endif
Else
;   indt=0
;  tab(indt)=NB_DEB
	tab(indt)=0
endif
if NB_DEB=1
	indt=0
	tab(indt)=1
endif  

;************************************   EDITION ***********************************************
Kpj=0
For j=0 To indt
;   printn(_n(tab(J)))
	if j>0 
		if tab(j-1)=tab(j)
			Kpj+1
		else  
			if Kpj=0
				;         fact_prem$+str(tab(j))
			else  
				fact_prem$+"^"+str(Kpj+1)
				kpj=0
			endif
			If j<=indt 
				fact_prem$+" * "+str(tab(j))
			EndIf
		endif 
	else 
			if tab(J)>0
						fact_prem$+str(tab(j))
					else
						NBPR$=_hhq(tab(j),"")
						fact_prem$+HEX2DEC(NBPR$)
					endif  
;     fact_prem$+str(tab(j))
	endif  
	NBREC *tab(j) ; Vérification de la décomposition
Next

if Kpj>0
	fact_prem$+"^"+str(Kpj+1)
endif  
NBRECH$=HEX(NBREC)
NBREC$=HEX2DEC(NBRECH$)
if mid(nb$,1,1)="$"
	NBCONT$="$"+NBRECH$
else 
	NBCONT$=NBREC$
endif  
;essai pour ces nombres 9223372036854769861, 9223372036854770317, 9223372036854770999, 9223372036854773927 et 9223372036854775309 qui ne sont pas premiers.
if flag2=0
	PrintN("Recherche des diviseurs <=:"+Str(SEQD\NBPFACT)+" + diviseurs =>"+Str(SEQD\NBPFACT))
	PrintN("Nombre d'éléments du vecteur =:"+Str(SEQD\NBSEQ)+"  temps de préparation ="+Str(delta_deb.q))
	;   MessageRequester("Résultat",fact_prem$+#CR$+NBCONT$+": contrôle"+#CR$+"temps="+Str(ElapsedMilliseconds()-deb1)+"ms"+#CR$+"Recherche des diviseurs <=:"+Str(SEQD\NBPFACT)+" + diviseurs =>"+Str(SEQD\NBPFACT)+#CR$+"Nombre d'éléments du vecteur =:"+Str(SEQD\NBSEQ))
	FLAG2+1
endif
;  AddGadgetItem(ListIcon_0, -1,nb$ +Chr(10)+NBCONT$+Chr(10)+Str(ElapsedMilliseconds()-deb1)+"ms"+chr(10)+fact_prem$)

printn("____________________________________________________________________")
PrintN(fact_prem$)
PrintN(NBCONT$+": contrôle")
PrintN("temps="+Str(ElapsedMilliseconds()-deb1)+"ms")
return 
; ces nombres 9223372036854769861, 9223372036854770317, 9223372036854770999, 9223372036854773927 et 9223372036854775309 qui ne sont pas premiers; 2295911257* 4017303373=9223372036854769861;==> div=-2147483645 divm=2147483647 DIVMAX=3037000500
; ***************** Ci dessous les Nombres premiers pour les 1000 premiers nombres
; 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
; 101 103 107 109 113 127 131 137 139 149 151 157 163 167 173 179 181 191 193 197 199
; 211 223 227 229 233 239 241 251 257 263 269 271 277 281 283 293
; 307 311 313 317 331 337 347 349 353 359 367 373 379 383 389 397
; 401 409 419 421 431 433 439 443 449 457 461 463 467 479 487 491 499
; 503 509 521 523 541 547 557 563 569 571 577 587 593 599
; 601 607 613 617 619 631 641 643 647 653 659 661 673 677 683 691
; 701 709 719 727 733 739 743 751 757 761 769 773 787 797
; 809 811 821 823 827 829 839 853 857 859 863 877 881 883 887
; 907 911 919 929 937 941 947 953 967 971 977 983 991 997

Here is the 4th prg that searches for prime numbers between 0 and 2 ^ 64-1 using a window to limit exploration. The results are in the raw state.


Ps:
During the development of the 2 prg, I had some problems to achieve satisfactory results in the area between 2 ^ 63 and 2 ^ 64-1
As the traps in this area are frequent and the tests represent an extremely large number it is not impossible that you find a bug.
Please let me know and thank you in advance.
PAPIPP
User
User
Posts: 49
Joined: Mon Aug 17, 2009 10:48 pm
Location: France

Re: Research and decomposition into prime factor of 1 to 2 ^

Post by PAPIPP »

Here is the 4th prg that searches for prime numbers between 0 and 2 ^ 64-1 using a window to limit exploration. The results are in the raw state.

Code: Select all

; algorithme de recherche des nombres PREMIERS par zones 
; ATTENTION ENTRE 1E2-1E1 =90 entre 1E3-1E2=900 entre 1E4-1E3=9000 entre 1E12-1E11= 900000000000
;; et entre 2^63 et 2^64 différence 2^63 = 9223372036854775808
; Le nombre 1 n'est pas par convention un nombre premier.
; Tous les nombres premiers >5 se terminent par 1 3 7 ou 9 seulement
; exemple des p_fact(x)
; p_fact(x)--modulo-----------------Nb_occurrences des différences--------Taux-----------Gain
; 3__________6__________________________2_________________________________0,3333_________66,66%
; 5__________30_________________________8_________________________________0,2666_________73,33%
; 7__________210________________________48________________________________0,2285_________77,14%
; 11_________2310_______________________480_______________________________0,2078_________79,22%
; 13_________30030______________________5760______________________________0,1918_________80,81%
; 17_________510510 ____________________92160_____________________________0,18052________81,94%
; 19_________9699690____________________1658880___________________________0,17102________82,89%
; 23_________223092870__________________36495360__________________________0,16358________83,64%

Macro _HHQ (_HHQ,_pr="$")
	_PR+RSet(Hex(PeekQ(@_HHQ),#PB_Quad),16,"0")
EndMacro

EnableExplicit
; DisableDebugger
; 2 3 5 7 11 13 17 19 23
Global Dim TABTERMIN.Q(4)
Structure ldec 
	DIFF.l
	IND.l
EndStructure
Structure synchro 
	StructureUnion
		SYNCDEC.ldec
		SYNCALP.q
	EndStructureUnion 
	
EndStructure  
Structure DIVIS
	NBPFACT.a
	PREMDIV.l
	NBSEQ.l
	MODULO.q
	Array TDIF.a(37000000)  ;;
EndStructure
Structure INFOTEMP
	NBASE$
	NBASE.Q
	NBASEHEX$
	NBASEDIFB.q
	NBASEIND.q
	NBASEDIFS.q
	NBASERAC.Q
	NBASEP.Q
	NBASEPHEX$
	NBASEPDIF.Q
	NBASEPIND.q
	NBASEPRAC.q
	
	NPLAGE$
	NPLAGE.Q
	NPLAGEHEX$
	
	NPLAGEMAX$    
	
	NBASEM$
	NBASEM.Q
	NBASEMHEX$
	NBASEMP.Q
	NBASEMPHEX$
	NBASEMIND.q
	NBASEMRAC.Q
	
;   FUTBASE$
;   FUTBASED.D
;   FUTBASE.q
;   FUTBASEHEX$
;   ;     FUTBASEP.Q
;   ;     FUTBASEPHEX$
;   FUTBASEIND.q
;   FUTBASERAC.Q
	
EndStructure 
Structure INFOCALC
	NBASE$
	NBASE.Q
	NBASEHEX$
	NBASEDIFB.q
	NBASEIND.q
	NBASEDIFS.q
	NBASERAC.Q
	NBASEP.Q
	NBASEPHEX$
	NBASEPDIF.Q
	NBASEPIND.q
	NBASEPRAC.q
EndStructure  
Global INFOSAISIE.INFOTEMP

Global result$,rest,SEQD.DIVIS,delta_deb.q,NBDIVISIONE.D
Global nbs.l,NBSEQ.l,SEQD.DIVIS,LIMIT$="7FFFFFFFFFFFFFFF",LIMITQ.Q=$7FFFFFFFFFFFFFFF,RACLIM.d=Sqr(LIMITQ)

Define nb$,nb.q,B2DIVIS.q,B2PAS,mess$,quotient.q,ind.l,B1MIN.Q=1E12,pos,B1MIN_DEP.Q,ZONEP.Q,presultat$,resultat$
Define MAX.Q=B1MIN+1E4,nbg$,nbd$,pose.l,t_ind.l,t_col.l,t_ind_dep.l,MAXMAXDIV.q,RAC2.Q,B1MINRAC2.Q,nbseqp,B2IND_MAXDIV,DIF_MAXDIV
Define ind_dep,DIFF,FLAGFIN,IND_NB,CENTM,B2DIVISM,B2INDDD, B2DIVIS$,B2MAXDIV.q,dep_time.q,cent,nbseq_1.q,P_MAXDIV.q,MAXHEX$
Procedure.Q DIVI64_32Q(DIVIDENTE.Q,DIVISEUR.Q)
		Protected  QUOTIENTS.Q
	global RESTES_.Q  ;; impossible de le placer en shared
	EnableExplicit
	EnableASM 
	MOV ecx,dword[p.v_DIVISEUR]  ;;;; la division euclidienne X=kQ+R avec R<Q nous oblige à utiliser une astuce
	XOR EDX,EDX                  ;;;; pour éviter avec un diviseur trop petit et un dividente trop grand d'avoir un reste de type qword or EDX est de type dword 
	MOV eax,dword[p.v_DIVIDENTE+4]
	DIV ecx
	MOV dword[p.v_QUOTIENTS+4],eax
	MOV eax,dword[p.v_DIVIDENTE]
	DIV ecx
	MOV dword[p.v_QUOTIENTS],eax
	MOV dword[v_RESTES_],edx
	DisableASM 
	ProcedureReturn QUOTIENTs
	DisableExplicit
	EndProcedure  
Procedure.Q DIVI64_32R(DIVIDENTE.Q,DIVISEUR.Q)
	Shared QUOTIENTS_.Q
	Protected  RESTES_.Q
	EnableASM 
	MOV ecx,dword[p.v_DIVISEUR]  ;;;; la division euclidienne X=kQ+R avec R<Q nous oblige à utiliser une astuce
	XOR EDX,EDX                  ;;;; pour éviter avec un diviseur trop petit et un dividente trop grand d'avoir un reste de type qword or EDX est de type dword 
	MOV eax,dword[p.v_DIVIDENTE+4]
	DIV ecx
	MOV dword[v_QUOTIENTS_+4],eax
	MOV eax,dword[p.v_DIVIDENTE]
	DIV ecx
	MOV dword[v_QUOTIENTS_],eax
	MOV dword[p.v_RESTES_],edx
	DisableASM 
			ProcedureReturn RESTES_
EndProcedure  
Procedure PREM_1_3_7_9(NBprem.Q);;;; Répartition des Nb premiers par terminaison 1 3 7 9 ********************
Protected rest10.A
		EnableExplicit
Rest10.A=DIVI64_32R(NBPREM,10) 
Select REST10 
		Case 1
			TABTERMIN(1)+1
		Case 3
			TABTERMIN(2)+1
		Case 7
			TABTERMIN(3)+1
		Case 9
				TABTERMIN(4)+1
		Default 
			MessageRequester("Attention " , _HHQ(NBPREM,"")+" n'est pas premier ")
	EndSelect
	DisableExplicit
EndProcedure  

Procedure.s choixdiv()
	Protected     COUR_DIR$,Filtre$,fichier$,Tfichier,fichierp$,leftfich$,RIGHTfich$,deb00.q,deb0.q,ADRDSEQ.q,AdresdebF.q,AdresFinF.q,Adresdeb.q,delta
	EnableExplicit
	COUR_DIR$ = GetCurrentDirectory()
	Filtre$ = "MEMA (MEMA_*.BIN)|MEMA_*.BIN;|Tous les fichiers (*.*)|*.*"
	fichier$=OpenFileRequester("Choisissez un fichier MEMA ou annulez", COUR_DIR$+"\MEMA_17.BIN", Filtre$, 0)
	fichierp$=UCase(Trim(GetFilePart(fichier$)))
	Tfichier=FileSize(Fichier$)
	leftfich$=Left(fichierp$,5)
	RIGHTfich$=Right(fichierp$,4)
	If Tfichier<1 Or Left(fichierp$,5)<>"MEMA_" Or Right(fichierp$,4) <>".BIN"
		MessageRequester( "ATTENTION", "fichier vide ou le nom n'est pas conforme "+ _n(Tfichier)+"  "+_s(fichierp$))
		End
	EndIf
	;   FICHIER$=choixdiv()
	deb00.q=ElapsedMilliseconds()
	;************************************************************************************************************************************
	ADRDSEQ=@SEQD
	AdresdebF=@SEQD\NBPFACT
	AdresFinF=@SEQD\MODULO+SizeOf(quad)
	Adresdeb=@SEQD\TDIF(0)
	delta=AdresFinF-AdresdebF
	
	If OpenFile(2,FICHIER$);,#PB_File_SharedRead|#PB_File_NoBuffering)
		ReadData(2,ADRDSEQ ,delta)
		ReDim SEQD\TDIF(SEQD\NBSEQ+1)
		ReadData(2, Adresdeb,SEQD\NBSEQ+1)
		CloseFile(2)
	EndIf
	deb0.q=ElapsedMilliseconds()
	delta_deb.q=deb0-deb00
	EnableExplicit
EndProcedure
Procedure.q SYNCHRO(NBASYNCHRO.Q)
	Protected restd.q,t_ind.q,t_col,ind,INFO.SYNCHRO,t_ind_dep,MODULO.Q
	EnableExplicit
	MODULO.q=SEQD\MODULO 
	restd.q=0
	EnableASM 
	MOV ecx,dword[p.v_MODULO]  ;;;; la division euclidienne X=kQ+R avec R<Q nous oblige à utiliser une astuce
	XOR EDX,EDX                ;;;; pour éviter avec un diviseur trop petit et un dividente trop grand d'avoir un reste de type qword or EDX est de type dword 
	MOV eax,dword[p.v_NBASYNCHRO+4]
	DIV ecx
	;    MOV dword[v_quotientp],eax
	MOV eax,dword[p.v_NBASYNCHRO]
	DIV ecx
	MOV dword[p.v_restd],edx
	DisableASM 
	; 
	; ;   restd=NBASYNCHRO%SEQD\MODULO 
	t_ind=0
	t_col=1
	
	For ind=0 To SEQD\MODULO 
		If restd<=t_col
			t_ind_dep=t_ind
			Break
		Else 
			t_col+seqd\TDIF(t_ind)
			t_ind+1
		EndIf
	Next
	INFO\SYNCDEC\DIFF=t_col-restd
	INFO\SYNCDEC\IND=t_ind_dep
	ProcedureReturn info\SYNCALP
	DisableExplicit
EndProcedure  

Procedure.s HEX2DEC(HEXS.S)
	EnableExplicit
	Static Dim t_rest.a(1000)
	Protected DIVIDENDE$,vald.q,longt,resultat$,DIVIDP$,DIVIDPR$,QUOTP.q,RESTP.q,quotp$,j,ii,DIVIDP.Q,Irest
	DIVIDENDE$=LTrim(UCase(HEXS))
	vald.q=Val("$"+DIVIDENDE$)
	longt=Len(DIVIDENDE$)
	If vald>0 And longt<17
		resultat$=Str(vald)
	Else  
		Irest=0
		DIVIDP$=""
		DIVIDPR$=""
		quotp$=""
		Repeat 
			For ii=1 To longt
				DIVIDP$=DIVIDPR$+Mid(DIVIDENDE$,ii,1)
				DIVIDP.Q=Val("$"+DIVIDP$)
				;   QUOTP.q=DIVIDP/10
				;   RESTP.q=DIVIDP%10
				EnableASM
				MOV ax,word [p.v_DIVIDP]  
				MOV cl,10
				;   idiv Cl 
				DIV cl  ; utilise moins de cycles machine que idiv
				MOV  [p.v_QUOTP],al
				MOV [p.v_RESTP],AH
				DisableASM
				
				DIVIDPR$=Hex(RESTP)
				quotp$+Hex(QUOTP)
			Next 
			t_rest(Irest)=RESTP
			Irest+1 
			DIVIDENDE$=QUOTP$
			longt=Len(DIVIDENDE$) 
			DIVIDP$=""
			DIVIDPR$=""
			quotp$=""
			
		Until Val("$"+ dividende$)=0
		For j=Irest-1 To 0 Step-1
			resultat$+Str( t_rest(j))
			t_rest(j)=0
		Next
	EndIf
	ProcedureReturn  resultat$
	DisableExplicit
EndProcedure

Procedure.s DEC2HEX(DECI.S)
	EnableExplicit
	Static Dim t_rest.a(1000)
	Protected DIVIDENDE$,vald.q,longt,resultat$,DIVIDP$,DIVIDPR$,QUOTP.q,RESTP.q,quotp$,i,j,ii,DIVIDP.Q,Irest
	DIVIDENDE$=UCase(DECI)
	longt=Len(DIVIDENDE$)
	If Val(DIVIDENDE$)=>0  And longt<20
		vald.q=Val(DIVIDENDE$)
		resultat$=Hex(vald)
	Else  
		irest=0
		DIVIDP$=""
		DIVIDPR$=""
		quotp$=""
		Repeat 
			For ii=1 To longt
				DIVIDP$=DIVIDPR$+Mid(DIVIDENDE$,ii,1)
				DIVIDP.Q=Val(DIVIDP$)
				;   QUOTP.q=DIVIDP/16
				;   RESTP.q=DIVIDP%16
				EnableASM
				MOV ax,word [p.v_DIVIDP]  
				MOV cl,16
				;   div Cl 
				DIV Cl  ; utilise moins de cycles machine que idiv
				MOV  [p.v_QUOTP],al
				MOV [p.v_RESTP],AH
				DisableASM
				
				DIVIDPR$=Str(RESTP)
				quotp$+Str(QUOTP)
			Next 
			t_rest(Irest)=RESTP
			Irest+1 
			DIVIDENDE$=QUOTP$
			longt=Len(DIVIDENDE$) 
			DIVIDP$=""
			DIVIDPR$=""
			quotp$=""
			
		Until Val(dividende$)=0
		For j=Irest-1 To 0 Step-1
			resultat$+Hex( t_rest(j))
			t_rest(j)=0
		Next
	EndIf
	ProcedureReturn  resultat$
	DisableExplicit
EndProcedure
Procedure CALCUL(_NB.S,*SCALCUL.INFOCALC )
	EnableExplicit
	; PROCEDURE CALCUL(_NB.S,SCALCUL.INFOCALC )
	Static ADR1.q,ADR2.q,ADR3.Q,ADR4.q,FLAG=0 
	Protected POSE,BASEMIN.q,nbasehex$,lnbh,A1.q,A2.q,NBASE.Q,DIFFB.q,difd.d,limitd.d,K.d,RACK.d,DIVMAX.q,NBASEP.q,SYNCDIVIS.SYNCHRO
	Protected MAX_DIV.SYNCHRO,DIVMAXD.d,DIVMAXPD.d,DIVMAXP.q
	If Mid(_NB,1,1)="$"
		nbasehex$=Right(_NB,Len(_NB)-1)
	Else
		POSE=FindString(_NB,"E")
		If pose>0
			BASEMIN.q=ValD(_NB)
			nbasehex$=_HHQ(basemin,"")
		Else 
			nbasehex$=dec2hex(_NB)   
		EndIf 
	EndIf 
	;   lnbh=len(nbasehex$)
	;   nbasehex$=ReplaceString(space(16-lnbh)," ","0")+nbasehex$
	nbasehex$=Right("0000000000000000"+nbasehex$,16)
	If lnbh>16 Or nbasehex$>"FFFFFFFFFFFFFFFE" 
		INFOSAISIE\nbase$=""
		INFOSAISIE\NPLAGE$=""
		ProcedureReturn 2 
		Goto FIN
	EndIf
	;;;;; recherche d'une racine carré de nb à partir de la différence 
	A1.q=Val("$"+Mid(nbasehex$,9,16))
	A2.q=Val("$"+Mid(nbasehex$,1,8))
;   debug _n(A1)+_n(A2)
	
	NBASE.q=0 
	DIFFB.Q=0
	EnableASM  ;; ici recherche en cours pour évaluer le plus précisément la racine carré des nombres >2^63-1
	MOV eax,dword[p.v_A1]
	MOV dword[p.v_NBASE],eax 
	MOV edx,dword[p.v_A2]
	MOV dword [p.v_NBASE+4],edx
	SUB eax,dword[v_LIMITQ] 
	SBB edx,dword[v_LIMITQ+4]
	MOV dword[p.v_DIFFB],eax 
	MOV dword [p.v_DIFFB+4],edx
	If nbasehex$>LIMIT$
		;;;;; recherche d'une racine carré de nb à partir de la différence 
		difd.d=DIFFB 
		limitd.d=limitq
		K.d=DIFd/LIMITd ;;;; k est défini sur la plage -1 +1 pour une plage div de +$7FFFFFFFFFFFFFFF à -$7FFFFFFFFFFFFFFF
		RACK.D=Sqr(1+K) ;;;; plage de 0 sqr(2)
		DIVMAXD.d=RACLIM *RACK
		DIVMAX.q=divmaxd  ;;limite de recherche des facteurs premiers  de la base
	Else 
		DIVMAX=Sqr(Val("$"+nbasehex$))
	EndIf  
	;   IF NBASE < SEQD\PREMDIV
	SYNCDIVIS\SYNCALP=SYNCHRO(NBASE)
	*SCALCUL\NBASEP=NBASE+SYNCDIVIS\SYNCDEC\DIFF 
	*SCALCUL\NBASEDIFS=SYNCDIVIS\SYNCDEC\DIFF
	*SCALCUL\NBASEIND=SYNCDIVIS\SYNCDEC\IND
	*SCALCUL\NBASEPHEX$=_HHQ(*SCALCUL\NBASEP,"")
	*SCALCUL\NBASE=NBASE
	*SCALCUL\NBASE$=_NB
	*SCALCUL\NBASEHEX$=nbasehex$
	*SCALCUL\NBASERAC=DIVMAX
	*SCALCUL\NBASEDIFB=DIFFB
	; *SCALCUL\NBASEIND=INDBASE
	; *SCALCUL\NBASEP=NBASEP
	If NBASE>0 And NBASE<SEQD\PREMDIV
		*SCALCUL\NBASEP=SEQD\PREMDIV
	EndIf  
	*SCALCUL\NBASEPHEX$=_HHQ(*SCALCUL\NBASEP,"")
	SYNCDIVIS\SYNCALP=SYNCHRO(*SCALCUL\NBASEP)
	*SCALCUL\NBASEPDIF=SYNCDIVIS\SYNCDEC\DIFF 
	*SCALCUL\NBASEPIND=SYNCDIVIS\SYNCDEC\IND
	difd.d=SYNCDIVIS\SYNCDEC\DIFF
	K.d=DIFd/*SCALCUL\NBASEP ;;;; 
	RACK.D=Sqr(1+K)          ;;;; plage de 0 sqr(2)
	DIVMAXPD.d=*SCALCUL\NBASERAC *RACK
	DIVMAXP.q=divmaxpd  ;;
	if divmaxp<4294967296
		divmaxp+1
	endif 
		*SCALCUL\NBASEPRAC=DIVMAXP
	FIN:
	DisableExplicit
EndProcedure  
Procedure EXTRINFO(NBE$)  
	Protected pose, basmin.q,nbasehex$,lnbh,A1.q,A2.q,NBASE.Q,DIFFE.Q,difd.d,limitd.d,K.d,RACK.d,DIVMAXD.d,DIVMAX.q,NB$,DIFFB.Q
	Static FLAG=0 
	Shared INF_CAL.INFOCALC, INF_CAL3.INFOCALC
	Protected NBl3$,NB_A_TESTER.Q,NB_DE_DIVISEUR_MPAR.Q,NB_DE_DIVISEUR_MAX.d,KEFFICACE.D,LOG2X.d
	EnableExplicit
	Global T1.Q=ElapsedMilliseconds()
	Select FLAG 
		Case 0
			;   if INFOSAISIE\nbase$=""
			calcul (NBE$,INF_CAL)
			CopyMemory(INF_CAL,INFOSAISIE,SizeOf(INFOCALC))
		Case 1 
			;       PRiNTN("X PASSAGE  "+_n(FLAG)+_s(NBE$))
			calcul (NBE$, INF_CAL3)
			;   calcul (NB$)
			INFOSAISIE\NPLAGE$=NBe$
			INFOSAISIE\NPLAGE=INF_CAL3\NBASE
			INFOSAISIE\NPLAGEHEX$=INF_CAL3\NBASEHEX$
			If INFOSAISIE\NPLAGEHEX$>INFOSAISIE\NPLAGEMAX$
				ProcedureReturn 3
				;         goto FIN 
			EndIf  
			;**********************************  Recherche infos de NBASE MAX  *********************************** 
			INFOSAISIE\NBASEM=INFOSAISIE\NBASE+INFOSAISIE\NPLAGE
			INFOSAISIE\NBASEMHEX$=_HHQ(INFOSAISIE\NBASEM,"")
			NBl3$="$"+INFOSAISIE\NBASEMHEX$
			INFOSAISIE\NBASEM$=NBl3$
			
			If INFOSAISIE\NBASEMHEX$>LIMIT$
				A1.q=Val("$"+Mid(INFOSAISIE\NBASEMHEX$,9,16))
				A2.q=Val("$"+Mid(INFOSAISIE\NBASEMHEX$,1,8))
				NBASE.q=0 
				DIFFB.Q=0
				EnableASM  ;; ici recherche en cours pour évaluer le plus précisément la racine carré des nombres >2^63-1
				MOV eax,dword[p.v_A1]
				MOV dword[p.v_NBASE],eax 
				MOV edx,dword[p.v_A2]
				MOV dword [p.v_NBASE+4],edx
				SUB eax,dword[v_LIMITQ] 
				SBB edx,dword[v_LIMITQ+4]
				MOV dword[p.v_DIFFB],eax 
				MOV dword [p.v_DIFFB+4],edx
				;;;;; recherche d'une racine carré de nb à partir de la différence 
				difd.d=DIFFB 
				limitd.d=limitq
				K.d=DIFd/LIMITd ;;;; k est défini sur la plage -1 +1 pour une plage div de +$7FFFFFFFFFFFFFFF à -$7FFFFFFFFFFFFFFF
				RACK.D=Sqr(1+K) ;;;; plage de 0 sqr(2)
				DIVMAXD.d=RACLIM *RACK
				DIVMAX.q=divmaxd  ;;limite de recherche des facteurs premiers  de la base
			Else 
				DIVMAX=Sqr(Val("$"+INFOSAISIE\NBASEMHEX$))
			EndIf  
;       INFOSAISIE\NBASEMRAC=DIVMAX+1
			INFOSAISIE\NBASEMRAC=DIVMAX
			
			NB_A_TESTER.Q=INFOSAISIE\NPLAGE
			NB_DE_DIVISEUR_MPAR.Q=INFOSAISIE\NBASEMRAC/2+INFOSAISIE\NBASEPRAC/2
			NB_DE_DIVISEUR_MAX.d=1.00*NB_DE_DIVISEUR_MPAR*NB_A_TESTER
			KEFFICACE.D=SEQD\NBSEQ/SEQD\MODULO
			LOG2X.d=Log(NB_DE_DIVISEUR_MAX)*Log10(#E)/Log10(2)
;       NBDIVISIONE.D=KEFFICACE*NB_DE_DIVISEUR_MAX/LOG10(NB_DE_DIVISEUR_MPAR)
			NBDIVISIONE.D=KEFFICACE*NB_DE_DIVISEUR_MAX
;       LOG2X.d=log(NB_DE_DIVISEUR_MAX)*log10(#e)/log10(2)

;       NBMILIS.D=NBDIVISIONE
;       PRINTN("Nombre de divisions max à effectuer :"+strd(NBDIVISIONE,2));;+" Evaluation du temps en ms : "+strd(NBMILIS))
			PrintN("Nombre de divisions max à effectuer :"+StrD(NBDIVISIONE,2))

			;;;*********** RECXHERCHE DE LA FUTURE  RACINE  et RACINE*RACINE*************************************
			;   delta=SEQD\TDIF(INFOSAISIE\NBASEPIND)
			;   INFOSAISIE\FUTBASERAC=INFOSAISIE\NBASEPRAC+delta
			;   INFOSAISIE\FUTBASE=INFOSAISIE\FUTBASERAC*INFOSAISIE\FUTBASERAC
		Case 2
;       PRiNTN("X PASSAGE  "+_n(FLAG))
		Case 3 
;       PRiNTN("X PASSAGE  "+_n(FLAG))
		Case 4
;       PRiNTN("X PASSAGE  "+_n(FLAG))
	EndSelect
;   PRiNTN("X PASSAGE  "+_n(FLAG)+_s(NBE$))
	FLAG+1 
	
	;   ProcedureReturn 0
	; FIN:
	; logB1MIN=Log10(B1MIN)
	; logmax=Log10(max-B1MIN)
	; If logB1MIN+logmax>22
	;   rmes=MessageRequester(" ATTENTION Temps très long","Oui=>continuez Non=>donnez autre zone",#PB_MessageRequester_YesNo)
	;   If Rmes = 6        ; le bouton Oui a été choisi (Resultat = 6)
	;   Else               ; le bouton Non a été choisi (Resultat = 7)
	;     Goto SAISIE2
	;   EndIf
	; EndIf
	DisableExplicit
EndProcedure

Procedure SAISIEBASEPLAGE()
	Protected mess$,nb$,pos,NBASE$,NPLAGE$,reto.l,NBASE.q,DIFFF.Q,NPLAGEMAX$,logB1MIN.D, logmax.D, rmes,hhqhex$,NBASE2.Q
	EnableExplicit
	mess$=""
	SAISIE2:
	mess$+"Base Zone ex: 98765 1E3, $FF875 1E9 ,1E9 1E4"
	
	If Len(mess$)>120
		MessageRequester("Erreur Relancez le Prg","Base  +Zone à explorer Ex: 98765 +1E3, $FF875 1E9, 1E9 +1E4 "+#CR$+"Relancez le prg") ;
		End
	EndIf ;;;                                                                                         7FFFFFFFFFFFFFFF
	nb$=UCase(LTrim(InputRequester(mess$,"Base Zone Ex:98765 1E3, $FF875 1E9, 1E9 1E4","$7FFFFFFFFFFFFF00 +1E3")));
	pos=FindString(nb$," ")
	NBASE$=Trim(Left(nb$,pos))
	NPLAGE$=Trim(Right(NB$,Len(nb$)-pos))
	
	reto.l=EXTRINFO(NBASE$)
	If retO>0
		Goto saisie2
	EndIf 
	;;;;;;************* Recherche de la plage max possible à utiliser *****************
	NBASE.q=INFOSAISIE\NBASE
	DIFFF.Q=0
	MOV eax,$FFFFFFFE
	MOV edx,$FFFFFFFF
	SUB eax,dword[p.v_NBASE] 
	SBB edx,dword[p.v_NBASE+4]
	MOV dword[p.v_DIFFF],eax 
	MOV dword [p.v_DIFFF+4],edx
	NPLAGEMAX$=_HHQ(DIFFF,"" )
	
	;   NPLAGEMAX$=_HHQ(DIFFF,"")
	;   lnbh=len(NPLAGEMAX$)
	;   NPLAGEMAX$=ReplaceString(space(16-lnbh)," ","0")+NPLAGEMAX$
	INFOSAISIE\NPLAGEMAX$=NPLAGEMAX$
	;;;*******************************  recherche de la plage à explorer   **************************
	If EXTRINFO(NPLAGE$)
		Goto saisie2
	EndIf 
	INFOSAISIE\NPLAGEMAX$=NPLAGEMAX$
		;   ProcedureReturn 0
		; FIN:
	NBASE2.Q=DIVI64_32Q(NBDIVISIONE,10)
	logB1MIN=log10(NBASE2)+1
	logmax=log10(INFOSAISIE\NPLAGE)
	If logB1MIN+logmax>15
		rmes=MessageRequester(" ATTENTION Temps très long","Oui=>continuez Non=>donnez autre zone",#PB_MessageRequester_YesNo)
		If Rmes = 6        ; le bouton Oui a été choisi (Resultat = 6)
		Else               ; le bouton Non a été choisi (Resultat = 7)
			Goto SAISIE2
		EndIf
	EndIf

	
	DisableExplicit
EndProcedure
EnableExplicit
Define NB_TOT_DIVIS.q,pos1,k,B1MIN$,B1MINPHEX$,B1MINHEX$,MAX_DIV.SYNCHRO,PAS_IND_NB
OpenConsole()
T1.q=ElapsedMilliseconds()
choixdiv()
SAISIEBASEPLAGE()
PrintN("Fin de la mise en place  temps="+Str(ElapsedMilliseconds()-T1))
MAX=INFOSAISIE\NBASEM
MAXHEX$=_HHQ(MAX,"")
B1MIN=INFOSAISIE\NBASEP
B1MIN_DEP=B1MIN
resultat$=""
NB_TOT_DIVIS=0
presultat$="02 03 05 07 11 13 17 19 23 29 31"
If INFOSAISIE\NBASE=>0 And INFOSAISIE\NBASE < SEQD\NBPFACT 
	pos1=FindString(presultat$,right("0"+str(INFOSAISIE\NBASE),2))
;   pos1=FindString(presultat$,Str(INFOSAISIE\NBASE))
	pose=FindString(presultat$,right("0"+Str(SEQD\NBPFACT),2))+2
	resultat$=trim(Mid(presultat$,pos1,POSE-pos1))
	NB_TOT_DIVIS=CountString(resultat$," ")+1
;   CreateRegularExpression(0,"[0-9]+"
	If CreateRegularExpression(0,"[0-9]+")
		Dim TResult$(0)
		Nb = ExtractRegularExpression(0,resultat$, TResult$())
		For k = 0 To Nb-1
			Select Right(Tresult$(k),1)
				Case "1"
					TABTERMIN(1)+1
				Case "2"   
					TABTERMIN(0)+1
				Case "3"   
					TABTERMIN(2)+1
				Case "5"   
					TABTERMIN(0)+1
				Case "7"   
					TABTERMIN(3)+1
				Case "9"
					TABTERMIN(4)+1
			EndSelect
		Next
	Else
		Debug RegularExpressionError()
	EndIf
	
;   NB_TOT_DIVIS=(POSE-POS1)/2
	;   B1MIN=SEQD\NBPFACT
EndIf   

; ******** sysnchronistion des Nombres à tester avec le vecteur des différences ***********
IND_NB=INFOSAISIE\NBASEPIND
B2DIVIS.q=SEQD\PREMDIV
flagfin=0
; B2MAXDIV.q=Pow(B1MIN,0.5)
B2MAXDIV.q=INFOSAISIE\NBASEPRAC  ;;;;;******************************************************
																	; MAXMAXDIV.q=Sqr(MAX)   ;;;;;****************************************************** 
MAXMAXDIV.q=INFOSAISIE\NBASEMRAC ;;;;;****************************************************** 
; if B2MAXDIV>MAXMAXDIV
;   B2MAXDIV=MAXMAXDIV
; endif  
PrintN(_n(MAXMAXDIV) +_n(B2MAXDIV))
PrintN(resultat$)

If B1MIN<0
	centm=B1MIN/-100
Else 
	centm=B1MIN/100
EndIf  
;;;;; ***************************** Gestion des diviseurs max *********************
MAX_DIV\SYNCALP =SYNCHRO(B2MAXDIV)
B2IND_MAXDIV=MAX_DIV\SYNCDEC\IND
DIF_MAXDIV=MAX_DIV\SYNCDEC\DIFF
P_MAXDIV=B2MAXDIV+DIF_MAXDIV
; B2MAXDIV=P_MAXDIV
; if MAXMAXDIV-B2MAXDIV<>0
;   *B2MAXDIV=SYNCHRO(B2MAXDIV)
;   B2IND_MAXDIV=*MAXDIV\IND_SYNCHRO
;   DIF_MAXDIV=*MAXDIV\DIFF_SYNCRO
; B2MAXDIV+DIF_MAXDIV

;******************************************************************************************************************
;;****** le prochain B2MAXDIV (A+dif)^2=A^2+2*dif*A+dif^2=  si A=SQR(X)=RAC donc (RAC^2)=X alors => (RAC+dif)^2= (RAC^2)+dif^2+2*dif*RAC=X+dif+(2*RAC*dif)
;;;********************* X+dif(1+2*RAC)
; RAC2=DIF_MAXDIV *(2*B2MAXDIV+DIF_MAXDIV)
; B1MINRAC2=B1MIN+RAC2





; =Str(B1MIN)+" "
B2DIVISm=0
nbseq_1.q=SEQD\NBSEQ-1
nbseq=SEQD\NBSEQ
nbseqp=nbseq+1
dep_time.q=ElapsedMilliseconds()
; B2PAS=SEQD\TDIF(1)
;;;***************************************************************************************************************************
;;;***************************  Début des 2 boucles pour rechercher  les NB premiers dans une zone MIN MAX   *****************
;;;***************************************************************************************************************************
;;;***************************************************************************************************************************
;;;*****  Début de la première boucle avec incrémentation des Nombrss le la zone donnéepour savoir s'ils sont premiers  *******
;;;***  fin de la boucle jusqu'à Until où l'on teste si le nb après incrémention est toujour dan la zone donnée         *******
;;;***************************************************************************************************************************
Repeat 
	B2INDDD=1
	B2PAS=SEQD\TDIF(B2INDDD)
	;   PRINTN(_NL+_N(B2DIVIS))
	;;;***************************************************************************************************************************
	;;;*****  Début de la deuxième boucle avec incrémentation des diviseurs du premier Nb X au dessus de p_fact(X)         *******
	;;;***                                  jusqu'à la racine du Nb à tester                                               *******
	;;;***************************************************************************************************************************
	;;; Info propre à boucle div=B2
	While B2DIVIS<=B2MAXDIV; or FLAGFIN>0
		
		;   printn(_n(B2DIVIS)+_n(B2PAS)+_n(idivis))
		;     ;Le nom de @@: signifie étiquette anonyme,vous pouvez avoir défini un grand nombre d'entre eux dans la source.
		;     ;Symbole @b(ou l'équivalent @r)le plus proche des références du label précédent anonyme
		;     ;,symbole @f références plus proche de l'étiquette suivante anonyme.
		;     ;Ces symboles spéciaux sont insensibles à la casse.
		;;*******************************  TESTS EN ASM ********************************************************************
		;*************************************** Division d'un nombre de 64 bits par un nombre de 32 bits ******************************************
		EnableASM
		MOV ecx,dword[v_B2DIVIS]
		XOR EDX,EDX
		MOV eax,dword[v_B1MIN+4]
		DIV ecx
		;   MOV dword[v_quotientp],eax   ;;;; Le reste de la division nous suffit 
		MOV eax,dword[v_B1MIN]
		DIV ecx
		CMP edx,0
		JNZ @f
		INC dword [v_FLAGFIN] 
		Break
		!@@:
		MOV edx,dword[v_B2PAS]
		ADD dword[v_B2DIVIS],edx  ; pas de PB l'addition est réalisée en valeur absolue 
		ADC dword[v_B2DIVIS+4],0  ; pas de PB l'addition est réalisée en valeur absolue 
															;     donc $FFFFFFFF =>4294967295 donc pas de risque de dépassement sqr(pow(2,63)-1))=>3037000499,9760496922867524030306 <4294967295
															;********************************************************************************************************************************************************
		
		DisableASM
		;********************************************************************************************************************************************************
		;********************************************************************************************************************************************************
		; ;***********************************  Pour accélerer encore l' algo  *******************************
		B2INDDD+1
		If B2INDDD=nbseqp  ;;; inutil de passer en ASM  voir ci dessus c'est plus long de près du double en temps sur la zone  9223372036854774807 1000
			B2INDDD=1        ;;;;;9223372036854770999
		EndIf
		B2PAS=SEQD\TDIF(B2INDDD)
		EnableASM
		;************************************  Pour accélerer encore l' algo vous pouvez décommentez les 5 lignes PB précedentes ******************************
	Wend
	;;;;*******************************************************************************************************************************************************
	;;;; ***********************************************  FIN DE LA DEUXIEME  BOUCLE DES DIVISEUR *************************************************************
	;;;; ***********************************************  FIN DE LA DEUXIEME  BOUCLE DES DIVISEUR *************************************************************
	;;;;*******************************************************************************************************************************************************
	If flagfin=0 and B1MIN<>1
		If B1MIN<0
			cent=B1MIN/-100
		Else 
			cent=B1MIN/100
		EndIf  
		If centm<>cent 
			PrintN(result$)
			centm=cent 
			If B1MIN<0 
				B1MIN$=HEX2DEC(_HHQ(B1MIN,""))
			Else 
				B1MIN$=Str(B1MIN)
			EndIf  
			result$=B1MIN$+" " 
		Else 
			If B1MIN<0 
				B1MIN$=HEX2DEC(_HHQ(B1MIN,""))
			Else 
				B1MIN$=Str(B1MIN)
			EndIf  
			result$+B1MIN$+" " 
		EndIf
		NB_TOT_DIVIS+1
		PREM_1_3_7_9(B1MIN) ;;;; R&partition des Nb premiers par terminaison 1 3 7 9 ******************
	EndIf 
	;       printn(_NL+_Q(B1MIN)+_s(result$)+_n(FLAGFIN))
	flagfin=0
	B1MINPHEX$=B1MINHEX$
	PAS_IND_NB=seqd\TDIF(ind_nb)
;   B1MIN+ seqd\TDIF(ind_nb) 
	B1MIN+ PAS_IND_NB 

	B1MINHEX$=_HHQ(B1MIN,"")

	;;;*******************************************************************************************************************************************************************
	;;; On peut anticiper la prochaine racine différente de celle actuelle (A+1)^2 =A^2+1+2A si A=SQR(X)=RAC donc (RAC^2)=X alors => (RAC+1)^2= (RAC^2)+1+2*RAC=X+1+(2*RAC)
	;;; le mini de diff est 2 donc (A+2)^2 =A^2+4+4A si A=SQR(X)=RAC donc (RAC^2)=X alors => (RAC+2)^2= (RAC^2)+4+4*RAC=X+4+(4*RAC);;;*******************************************************************************************************************************************************************
	;;; le mini de diff est D donc (A+D)^2 =A^2+D^2+2AD si A=SQR(X)=RAC donc (RAC^2)=X alors => (RAC+D)^2= (RAC^2)+D^2+2D*RAC=X+D^2+(2*D*RAC);;;*******************************************************************************************************************************************************************
	;;; cette technique pose des pb pour les nombres premiers à trouver < au premier diviseur 
	If B1MIN =>B1MINRAC2 
		if B1MIN > SEQD\PREMDIV ;;;; Valeurs toujours <$7FFFFFFFFFFFFFFF;
	; Il faudrait prendre le prochain diviseur dans le vecteur des différences avec la gestion de cet indice B2IND_MAXDIV essai en cours 
;     RAC2=DIF_MAXDIV*(2*B2MAXDIV+DIF_MAXDIV)
		RAC2=2*PAS_IND_NB* B2MAXDIV +(PAS_IND_NB*PAS_IND_NB)
		B1MINRAC2=B1MIN+RAC2
		B2MAXDIV.q=Sqr(B1MIN)+PAS_IND_NB+1
		;     B1MINRAC2.Q=B1MIN+(4*B2MAXDIV)+4
		Else
		RAC2=4* B2MAXDIV +4
		B1MINRAC2=B1MIN+RAC2
		B2MAXDIV.q=Sqr(B1MIN)+2

	EndIf 
	endif
	
;   If B1MIN =>B1MINRAC2  ;;;; Valeurs toujours <$7FFFFFFFFFFFFFFF;;; avec pas mini de 2
;     RAC2=4* B2MAXDIV +4
;     B1MINRAC2=B1MIN+RAC2
;     B2MAXDIV.q=Sqr(B1MIN)+2
; ;     B1MINRAC2.Q=B1MIN+(4*B2MAXDIV)+4
;   EndIf  

	
	;   IF B1MINRAC2>0
;     printn(_NL+_S(B1MINHEX$)+_s(MAXHEX$)+_n(B2MAXDIV)+_n(B1MINRAC2)+_n(FLAGFIN))
;   endif

	;    If B2DIVIS =>B2MAXDIV
	;      
	;   endif
	B2DIVIS=SEQD\PREMDIV 
	ind_nb+1
	;    if ind_nb>SEQD\NBSEQ-1
	If ind_nb>NBSEQ_1
		ind_nb=0  ;;; remise à zéro si le cycle des différences est atteint pour incrémentation des nombres susceptibles d'être premiers
	EndIf  
;       printn(_NL+_S(B1MINHEX$)+_s(MAXHEX$)+_n(B2MAXDIV)+_s(result$)+_n(FLAGFIN)+_n(CENTM)+_n(CENT))
;       PrintN(_NL+_S(B1MINHEX$)+_s(MAXHEX$)+_n(B2MAXDIV)+_n(B1MINRAC2)+_n(B2PAS)+_n(FLAGFIN))
	If B1MINHEX$<B1MINPhex$
;         printn(_NL+_s(B1MINHEX$)+_s(MAXhex$)+_n(B2MAXDIV))
		B1MINHEX$=MAXHEX$
	EndIf
;   paspas=seqd\TDIF(ind_nb)
;     printn(_s(B1MINHEX$)+_s(MAXhex$)+_n(B2MAXDIV)+_n(paspas))
Until B1MINHEX$=>MAXHEX$ ;;; Or B1MIN<0 ;;Si vous n'allez pas aux confins de la machine =$7FFFFFFFFFFFFFFF ;;; = 9223372036854775807 valeur max positive en ..q. 
;;                        Vous pouvez retirer (or B1MIN<0) ou dépassement de $7FFFFFFFFFFFFFFF
;;;;***********************************************************************************************************************************************************
;;;; ***********************************************  FIN DE LA PREMIERE  BOUCLE DES Nb à TESTER **************************************************************
;;;; ***********************************************  FIN DE LA DEUXIEME  BOUCLE DES Nb à TESTER  *************************************************************
;;;;***********************************************************************************************************************************************************

PrintN(result$)
; PrintN( "Nombre Minimal = "+Str(INFOSAISIE\NBASE)+"  Nombre Maximal = "+Str(MAX))
PrintN( "Nombre Minimal = "+HEX2DEC(_HHQ(INFOSAISIE\NBASE,""))+"  Nombre Maximal = "+HEX2DEC(_HHQ(MAX,"")))
PrintN("Nombre d'éléments du vecteur =:"+Str(SEQD\NBSEQ)+"  temps de préparation ="+Str(delta_deb))

PrintN("Temps millisecondes ="+Str(ElapsedMilliseconds()-dep_time))
PrintN("Nombre de nb premiers ="+Str(NB_TOT_DIVIS)+"  Nb de divisions /miliseconde = "+STRd(NBDIVISIONE/(ElapsedMilliseconds()-dep_time)))
Resultat$=""
For K=1 To 4
	Select K
		Case 1
			resultat$="Termine PAR 1="+Str(TABTERMIN(1))
		Case 2
			resultat$+" PAR 3="+Str(TABTERMIN(2))
		Case 3
			resultat$+" PAR 7="+Str(TABTERMIN(3))
		Case 4
			resultat$+" PAR 9="+Str(TABTERMIN(4))
	EndSelect    
Next 
resultat$+ "  PAR 2 ET 5  ="+Str(TABTERMIN(0))
PrintN(resultat$)
Input() 
CloseConsole()

; ***************** Ci dessous les Nombres premiers pour les 1000 premiers nombres
; 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
; 101 103 107 109 113 127 131 137 139 149 151 157 163 167 173 179 181 191 193 197 199
; 211 223 227 229 233 239 241 251 257 263 269 271 277 281 283 293
; 307 311 313 317 331 337 347 349 353 359 367 373 379 383 389 397
; 401 409 419 421 431 433 439 443 449 457 461 463 467 479 487 491 499
; 503 509 521 523 541 547 557 563 569 571 577 587 593 599
; 601 607 613 617 619 631 641 643 647 653 659 661 673 677 683 691
; 701 709 719 727 733 739 743 751 757 761 769 773 787 797
; 809 811 821 823 827 829 839 853 857 859 863 877 881 883 887
; 907 911 919 929 937 941 947 953 967 971 977 983 991 997

Post Reply