Atividade obrigatória 3
Geração de números primos
Escreva um programa estruturado (ou seja, com subrotinas comentadas) em linguagem
de montagem do ARM, para
obter e armazenar em palavras (32 bits) da memória RAM os pimeiros 32 números primos,
usando um dos 2 algoritmos do tipo "Crivo de Eratóstenes", cujos fontes em C aparecem abaixo
(teste-os!).
A sequencia de números primos deve ser exibida no vídeo com o formato "%10d\n" e deve ter o valor:
1
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
Importante: (i) traduza manualmente para assembler ("dicas" serão dadas em aula),
um dos algoritmos em C, a seguir: o 1o, adaptado
de Knuth, vol 1, p. 143(*), e o 2o, de J. P. Sundaran (1934)(**)
(ii) teste inicialmente o seu programa com um crivo pequeno, digamos, com 16 posições e depure-o com gdb;
Observe que, em princípio, o seu programa poderia gerar números primos sendo limitado unicamente
pela capacidade da memória RAM do processador alvo. Uma tabela de números primos é exibida no diretório
docs. Você pode usá-la para testar seu programa com uma quantidade maior de números primos.
(*)
//kprimes.c - adaptado de Knuth, "The Art of Computer Programming", Vol 1, p.143
#include <stdio.h>
#define MAXPRIMES 32
unsigned int primes[MAXPRIMES];
unsigned int next, prindex;
int main(){
unsigned int i;
primes[0]=1; primes[1]=2; primes[2]=3;
printf("%10d\n", primes[0]);
printf("%10d\n", primes[1]);
next=3;
prindex=2;
printf("%10d\n", next);
while(1){ //loop1
loop1:
next +=2;
for (i=2; ; i++){
if ((next % primes[i])==0) goto loop1;
if (next / primes[i] <= primes[i]) break;
}
prindex++;
primes[prindex]=next;
printf("%10d\n", next);
if (prindex==MAXPRIMES-1) break;
}
}
Explicação do algoritmo:
O laço interno (for (i=2...etc) verifica se o candidato ímpar "next" é primo dividindo-o
pelos primos encontrados até agora, até um valor limite primos[i] determinado
pelas seguintes asserções:
(i) todo inteiro não primo n pode se fatorado como produto de potencias de primos da forma: n= p1j1...pkjk
(p1<p2<...<pk);
(ii)se next % primes [i] == 0 então next é múltiplo de um dos primos da tabela e pode ser ignorado;
(iii)senão, se primes[i]>=sqrt(next) então por (i) acima next é primo, mas isto implica em:
primes[i]2 >= next, ou seja, primes[i]>=next/primes[i] > floor(next/primes[i]),
logo, next é primo.
(**)
/* sund.c - Geração de números primos usando o Crivo de Sundaran (1934)
http://en.wikipedia.org/wiki/Sieve_of_Sundaram
*/
#include <stdio.h>
#define N 64
int crivo[N+1];
int main(){
int i,j,k;
for (i=1;i<=N; i++)
crivo[i]=i;
for (j=1; j<=N; j++){
for (i=1; i<=j; i++){
k = i +j +2*i*j;
if (k<=N) crivo[k]=0;
}
}
for (i=1;i<=N; i++)
if(crivo[i]>0)
crivo[i]=2*crivo[i] +1;
printf ("%10d\n%10d\n", 1, 2);
for (i=1;i<=N; i++)
if(crivo[i]>0) printf("%10d\n", crivo[i]);
}