#include <iostream>
#include <vector>
using namespace std;
typedef unsigned int UI;
const UI MAX_N = 1000000000;
const UI RT_MAX_N = 32000; // square of max prime under this limit should exceed MAX_N
const UI B_SIZE = 20000; // not sure what optimal value for this is;
// currently must avoid overflow when squared
// assumes p, b odd and p*p won't overflow!
void crossOut(UI p, UI b, bool mark[]) {
UI si = (p - (b % p)) % p;
if (si & 1)
si += p;
if (p*p > b)
si = max(si, p*p-b);
for (UI i = si/2; i < B_SIZE/2; i += p)
mark[i] = true;
}
// mod 30, (odd) primes have remainders 1,7,11,13,17,19,23,29
// e.g. start with mark[B_SIZE/30]
// and offset[] = {1,7,11...}
// then mark[i] corresponds to 30*(i/8) + b-1 + offset[i%8]
void calcPrimes() {
int pCount = 1; UI lastP = 2;
// *** do something with first prime (2) here ***
vector<UI> smallP; smallP.push_back(2);
bool mark[B_SIZE/2] = {false};
for (UI i = 1; i < B_SIZE/2; ++i)
if (!mark[i]) {
++pCount; lastP = 2*i+1;
// *** do something with the newest prime lastP here ***
smallP.push_back(lastP);
if (lastP*lastP <= B_SIZE)
crossOut(2*i + 1, 1, mark);
}
else mark[i] = false;
for (UI b = 1+B_SIZE; b < MAX_N; b += B_SIZE) {
for (UI i = 1; smallP[i]*smallP[i] < b+B_SIZE; ++i)
crossOut(smallP[i], b, mark);
for (UI i = 0; i < B_SIZE/2; ++i)
if (!mark[i]) {
++pCount; lastP = 2*i + b;
// *** do something with the newest prime lastP here ***
if (lastP <= RT_MAX_N)
smallP.push_back(lastP);
}
else mark[i] = false;
}
cout << "Found " << pCount << " primes in total.\n";
cout << "Recorded " << smallP.size() << " small primes, up to " << RT_MAX_N << '\n';
cout << "Last prime found was " << lastP << '\n';
}
int main() {
calcPrimes();
}