Re: Turbo nombres premiers
Publié : mar. 22/juin/2021 6:29
C'est un peu beaucoup, 738 mégaoctets, non ?
Code : Tout sélectionner
Define num.q = 1548586400
Define sqrnum.q = Sqr(num)+1
Dim PrimeFlags.b(num>>1)
mill1.q = ElapsedMilliseconds()
For i.q=3 To sqrnum Step 2
If PrimeFlags(i>>1) = 0
!mov r9,[a_PrimeFlags]
!mov rdx,[v_i]
!mov rcx,rdx
!add rcx,rcx
!boucle:
!mov rbx,rcx
!shr rbx,1
!jnc xxx ; on ne gere pas les nombres paires
!mov byte [r9+rbx],1
!xxx:
!add rcx,rdx
!cmp rcx,[v_num]
!jl boucle
EndIf
Next
mill1 = ElapsedMilliseconds()-mill1
mill2.q = ElapsedMilliseconds()
count=0
OpenConsole()
For x=0 To (num-1)>>1 Step 1
If PrimeFlags(x) = 0
count+1
If count<1000
PrintN(Str(x))
EndIf ; Debug (x*2)+1 = nombre premier
EndIf
Next
mill2 = ElapsedMilliseconds()-mill2
num_ko = (num/2)/1024
num_mo = num_ko/1024
num_go = num_mo/1024
;EnableDebugger
FreeArray(PrimeFlags())
t$="part 1 : "+StrD(mill1/1000.0)+" seconds" + Chr(13)
t$=t$+"part 2 : "+StrD(mill2/1000.0)+" seconds" + Chr(13)
t$=t$+"TOTAL : "+StrD((mill1+mill2)/1000.0)+" seconds" + Chr(13)
t$=t$+Str(count)+" trouvé" + Chr(13)
t$=t$+Str(num_ko) + " Ko" + Chr(13)
t$=t$+Str(num_mo) + " Mo" + Chr(13)
t$=t$+Str(num_Go) + " Go" + Chr(13)
PrintN("C'est fini")
Input()
CloseConsole()
MessageRequester("Information",t$,#PB_MessageRequester_Ok)
Code : Tout sélectionner
#sMax = 1 << 22 - 1 ; ici c'est 22 que je fais varier pour rester autour d'une seule seconde de traitement (pas suffisamment de courant pour rester triturer le CPU 3 heures !)
sqrMax = Sqr((#sMax + 1) / 8 * 30) ; la racine... comme d'hab...
Dim s.I(#sMax) ; le crible...
s(0) = 1 ; on considère d'office que 1 (cellule numéro 0) est composite (1)
; mais ça sous-entends que toutes les autres cellules sont considérées non composites (primalité vraie, mais à prouver, comme Eratosthène s'exécutait)
Dim M.I(7) ; tableau des valeurs susceptibles de contenir des premiers dans une trentaine.
M(0) = 1 ; à l'exception de 0K+1, on testera donc 31, 61, 91, 121, 151, etc...
M(1) = 7 ; on testera 7, 37, 67, 97, 127, etc...
M(2) = 11 ; on testera 11, 41, 71, 101, 131, etc...
M(3) = 13 ; on testera 13, 43, 73, 103, 133, etc...
M(4) = 17 ; on testera 17, 47, 77, 107, 137, etc...
M(5) = 19 ; on testera 19, 49, 79, 109, 139, etc...
M(6) = 23 ; on testera 23, 53, 83, 113, 143, etc...
M(7) = 29 ; on testera 29, 59, 89, 119, 149, etc..
; Tous les autres nombres, exceptés 2, 3 et 5 ne seront pas testés officiellement et considérés, d'office multiple de 2, 3 ou 5, et ceci sera valable, quelque soit la trentaine, ainsi tous ces autres nombres (exceptés 2, 3 et 5) seront considérés composites.
K = 0 ; on commence par la trentaine entre 0 et 29.
i0 = 1 ; on pointe M(1) = 7 au départ, car pointer M(0) = 1, ce serait cribler tous les multiples de 1 donc déguelinguer la logique...
t0 = ElapsedMilliseconds() ; on regarde l'horloge
Repeat ; on démarre la boucle
K30 = 30 * K ; on calcule la trentaine
N = K30 + M(i0) ; on calcule le nombre N
If s(8 * K + i0) = 0 ; si N est premier (pas criblé)...
N2 = N * N ; on calcule son carré...
If N2 >= (#sMax + 1) / 8 * 30 ; le carré est-il hors limite ?
Break ; oui, on se casse
EndIf
Repeat ; non, alors on va cribler les multiples de ce nb premier
K_30 = N2 / 30 ; on calcule à quelle trentaine est ce nombre...
M_ = N2 % 30 ; on calcule son modulo 30
For I = 0 To 7 ; On va chercher quel est, parmi les huit nombres susceptibles d'être premiers, si notre nombre correspond...
If M_ = M(I) ; si on a une correspondance...
s((8 * K_30) + I) = 1 ; ...alors on crible
Break ; et on cesse de chercher d'autres correspondances
EndIf
Next
N2 + N ; on va tenter, de cette manière donc, de cribler les multiples de N
Until N2 >= (#sMax + 1) / 8 * 30 ; et on s'arrête quand on est hors limite.
EndIf
i0 + 1 ; on teste notre nombre suivant, susceptibles d'être premier...
If i0 > 7 ; on a testé les huit ?
i0 = 0 ; oui, on reprend le premier nombre (sans jeu de mots...)
K + 1 ; et on passe à la trentaine suivante...
EndIf
Debug N ; ça c'est pour quiconque n'y croirait pas...
Until N > sqrMax ; et ça c'est au cas, coïncidence, la racine carré de la quantité de nombres à tester serait malheureusement située dans un gap envahi de nombres composites, et donc n'aurait pas déclenché la 1ère sécurité plus haut (le fabuleux "on se casse" précédemment décrit)
t1 = ElapsedMilliseconds() ; on regarde le chrono de l'horloge...
; et on affiche quantité et durée de notre algo dont on peut apparemment assortir de la palme du boulet d'or, tellement je n'ai méga rien optimisé...
MessageRequester(Str((#sMax + 1) / 8 * 30) + " nb testés", Str(t1 - t0) + " ms")
Code : Tout sélectionner
! mov r13, $fee
Code : Tout sélectionner
110 100 010 100 010 100 110 010 (binaire par 3)
6 4 2 4 2 4 6 2 (nos gaps)
1101 0001 0100 0101 0011 0010 (binaire par 4)
D 1 4 5 3 2
1110011001101101 (sans suffixe 0)
E66D
1100110011011011 (idem décalé pour être masqué)
CCDB
Code : Tout sélectionner
29+2 = 31
31+6 = 37
37+4 = 41
41+2 = 43
43+4 = 47
47+2 = 49
49+4 = 53
53+6 = 59
Code : Tout sélectionner
-1+2 = 1
1+6 = 7
7+4 = 11
11+2 = 13
13+4 = 17
17+2 = 19
19+4 = 23
23+6 = 29
Code : Tout sélectionner
! mov rax, $D14532
Code : Tout sélectionner
! ror rax, 3
! or rdx, rax
! and rdx, 7
! add rcx, rdx
Code : Tout sélectionner
; version quasi-finale de notre tableau Dim M(7) des gaps de susceptibles premier de modulo 30
! mov eax, $E66D
! rol eax, 1
redo:
! mov dl, al
! and dl, 6
! add rcx, dl
! ror eax, 2
! jmp l_redo
Code : Tout sélectionner
; version finale
! mov eax, $CCDB
redo:
! mov dl, al
! and dl, 6
! ror eax, 2 ; anticipation pour pipe-line rax/rcx/rdx
! add rcx, dl
! jmp l_redo ; saut ultérieurement conditionnel
Code : Tout sélectionner
1
7
11
13
17
19
23
29
31
37
41
43
47
49
53
59
61
67
etc... jusquà l'infini
Code : Tout sélectionner
#sMax = 1 << 24 - 1 ; ici, je passe de 22 à 24 pour la même durée environ
sqrMax = Sqr((#sMax + 1) / 8 * 30)
Dim s.a(#sMax) ; le crible... je suis contraint de passer des quads aux octets
s(0) = 1
Dim M.I(7) ; tableau des valeurs susceptibles de contenir des premiers dans une trentaine.
M(0) = 1 ; à l'exception de 0K+1, on testera donc 31, 61, 91, 121, 151, etc...
M(1) = 7 ; on testera 7, 37, 67, 97, 127, etc...
M(2) = 11 ; on testera 11, 41, 71, 101, 131, etc...
M(3) = 13 ; on testera 13, 43, 73, 103, 133, etc...
M(4) = 17 ; on testera 17, 47, 77, 107, 137, etc...
M(5) = 19 ; on testera 19, 49, 79, 109, 139, etc...
M(6) = 23 ; on testera 23, 53, 83, 113, 143, etc...
M(7) = 29 ; on testera 29, 59, 89, 119, 149, etc...
Dim gap.I(7)
gap(0) = 6
gap(1) = 4
gap(2) = 2
gap(3) = 4
gap(4) = 2
gap(5) = 4
gap(6) = 6
gap(7) = 2
K = 0 ; on commence par la trentaine entre 0 et 29.
i0 = 1
t0 = ElapsedMilliseconds()
Repeat ; on démarre la boucle
K30 = 30 * K
N = K30 + M(i0)
If s(8 * K + i0) = 0 ; si N est premier (pas criblé)...
N2 = N * N ; on calcule son carré...
If N2 >= (#sMax + 1) / 8 * 30 ; le carré est-il hors limite ?
Break ; oui, on se casse
EndIf
i1 = i0 ; >>> NOUVEAU <<< on dupplique l'index
Repeat ; non, alors on va cribler les multiples de ce nb premier
K_30 = N2 / 30 ; on calcule à quelle trentaine est ce nombre...
M_ = N2 % 30 ; on calcule son modulo 30
For I = 0 To 7 ; On va chercher quel est, parmi les huit nombres susceptibles d'être premiers, si notre nombre correspond...
If M_ = M(I) ; si on a une correspondance...
s((8 * K_30) + I) = 1 ; ...alors on crible
Break ; et on cesse de chercher d'autres correspondances
EndIf
Next
;(((N2 + N ; on va tenter, de cette manière donc, de cribler les multiples de N)))
N2 + N * gap(i1) ; on crible désormais plus intelligemment
i1 + 1
i1 & 7
Until N2 >= (#sMax + 1) / 8 * 30 ; et on s'arrête quand on est hors limite.
EndIf
i0 + 1 ; on teste notre nombre suivant, susceptibles d'être premier...
If i0 > 7 ; on a testé les huit ?
i0 = 0 ; oui, on reprend le premier nombre (sans jeu de mots...)
K + 1 ; et on passe à la trentaine suivante...
EndIf
Debug N ; ça c'est pour quiconque n'y croirait pas...
Until N > sqrMax
t1 = ElapsedMilliseconds() ; on regarde le chrono de l'horloge...
Delay(1) ; alors, celui-là, j'ai rien compris : stabilise la durée de l'algo
; Je rajoute ceci pour que PAPIPP ou quiconque casse la baraque si je me trompe...
For I = 0 to #sMax
If s(I) = 0
P + 1
EndIf
Next
; et on affiche quantité et durée de notre algo dont on peut apparemment assortir de la palme du boulet d'or, tellement je n'ai méga rien optimisé... Technologiquement...
MessageRequester(Str((#sMax + 1) / 8 * 30) + " nb testés", Str(t1 - t0) + " ms" + Chr(10) + Str(P) + " nbs 1ers")
Code : Tout sélectionner
#P2 = 24 ; on garde notre constante d'échelle pour régler facilement l'algo à une seule seconde d'exécution.
#sMax = 1 << (#P2 - 3) - 1 ; ici, j'adapte le facteur 8 (avec -3, car 2^3=8)
Macro sGet(K0, M0) ; pour lire le crible
((s(K0) >> M0) & 1)
EndMacro
Macro sSet(K0, M0) ; pour cribler
s(K0) | (1 << M0)
EndMacro
Define.I sqrMax = Sqr((#sMax + 1) * 30) ; adapté
Dim s.a(#sMax) ; le crible...
s(0) = 1 ; réglage du 1 comme composite...
Dim M.I(7)
M(0) = 1
M(1) = 7
M(2) = 11
M(3) = 13
M(4) = 17
M(5) = 19
M(6) = 23
M(7) = 29
Dim gap.I(7)
gap(0) = 6
gap(1) = 4
gap(2) = 2
gap(3) = 4
gap(4) = 2
gap(5) = 4
gap(6) = 6
gap(7) = 2
K = 0
i0 = 1
t0 = ElapsedMilliseconds()
Repeat
K30 = 30 * K
N = K30 + M(i0)
If sGet(K, i0) = 0 ; adapté
N2 = N * N
If N2 >= (#sMax + 1) * 30 ; adapté
Break
EndIf
i1 = i0
Repeat
K_30 = N2 / 30
M_ = N2 % 30
For I = 0 To 7 ; début de la partie qui va partir en fumée bientôt
If M_ = M(I)
sSet(K_30, I) ; adapté
Break
EndIf
Next ; fin de la partie qui va partir en fumée bientôt
N2 + N * gap(i1)
i1 + 1
i1 & 7
Until N2 >= (#sMax + 1) * 30 ; adapté
EndIf
i0 + 1
If i0 > 7
i0 = 0
K + 1
EndIf
Until N > sqrMax
t1 = ElapsedMilliseconds()
Delay(1)
For I = 0 to #sMax
For J = 0 To 7
If s(I) >> J & 1 = 0 ; adapté
P + 1
EndIf
Next
Next
; On affiche quantités et durée de notre algo dont on peut apparemment assortir de la palme du boulet d'or, tellement je n'ai méga rien optimisé... Technologiquement...
MessageRequester(Str((#sMax + 1) * 30) + " nb testés", Str(t1 - t0) + " ms" + Chr(10) + Str(P) + " nbs 1ers")