C#: How to make Sieve of Atkin incremental
Não sei se isso é possível ou não, mas preciso perguntar. Minhas habilidades matemáticas e algorítmicas estão me falhando aqui: P
O negócio é que agora tenho essa classe que gera números primos até um certo limite:
public class Atkin : IEnumerable<ulong>
{
private readonly List<ulong> primes;
private readonly ulong limit;
public Atkin(ulong limit)
{
this.limit = limit;
primes = new List<ulong>();
}
private void FindPrimes()
{
var isPrime = new bool[limit + 1];
var sqrt = Math.Sqrt(limit);
for (ulong x = 1; x <= sqrt; x++)
for (ulong y = 1; y <= sqrt; y++)
{
var n = 4*x*x + y*y;
if (n <= limit && (n % 12 == 1 || n % 12 == 5))
isPrime[n] ^= true;
n = 3*x*x + y*y;
if (n <= limit && n % 12 == 7)
isPrime[n] ^= true;
n = 3*x*x - y*y;
if (x > y && n <= limit && n % 12 == 11)
isPrime[n] ^= true;
}
for (ulong n = 5; n <= sqrt; n++)
if (isPrime[n])
{
var s = n * n;
for (ulong k = s; k <= limit; k += s)
isPrime[k] = false;
}
primes.Add(2);
primes.Add(3);
for (ulong n = 5; n <= limit; n++)
if (isPrime[n])
primes.Add(n);
}
public IEnumerator<ulong> GetEnumerator()
{
if (!primes.Any())
FindPrimes();
foreach (var p in primes)
yield return p;
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
Agora, o que eu gostaria é livrar-me do limite para que a sequência nunca parasse (teoricamente).
Eu estou pensando que poderia ser algo assim:
Comece com algum limite trivialEncontre todos os primos até o limiteRenda todos os primos recém-descobertosAumentar o limite (dobrando ou quadrando o limite antigo ou algo assim)Ir para o passo 2E otimamente esse passo dois só deveria ter que trabalhar entre o limite antigo e o novo. Em outras palavras, não deveria ter que encontrar os primos mais baixos de novo e de novo.
Existe uma maneira que isso possa ser feito? Meu principal problema é que eu não entendo muito bem o quex
ey
por exemplo, está neste algoritmo. Tipo, eu poderia usar o mesmo tipo de algoritmo mas definidox
ey
paraoldLimit
(inicialmente 1) e execute-o paranewLimit
? Ou como isso funcionaria? Alguma mente brilhante com alguma luz para derramar isso?
O ponto disso é que não terei que definir esse limite. Para que eu possa, por exemplo, usar o Linq e apenasTake()
no entanto muitos primos que eu preciso, não se preocupando se o limite for alto o suficiente, etc.