/*
* Filename: primus.cpp
* Author: Igor V. Krassikov
* Created: Thu Sep 22 2016
*/
// Простые числа до 2^32-1
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
constexpr inline unsigned long pow2(unsigned long i) { return 1 << i; }
unsigned long isqrt(unsigned long a)
{
unsigned long x = a;
for(unsigned long z = 0; x != z; )
{
z = x;
x = (x + a/x)/2;
x = (x + a/x)/2;
}
return x;
}
constexpr unsigned long MAX_LIM = pow2(20) - 1;
constexpr unsigned long ARR_LIM = (MAX_LIM >> 6) + 1;
const unsigned long SQR_LIM = isqrt(MAX_LIM);;
unsigned long primes[ARR_LIM] = { 0 }; // 0 - простое, 1 - составное
auto set_primes = [](unsigned long idx) { primes[idx >> 6] |= pow2((idx&0x0000003F)>>1); };
auto get_primes = [](unsigned long idx) { return primes[idx >> 6] & pow2((idx&0x0000003F)>>1); };
int main(int argc, const char * argv[])
{
clock_t start = clock();
unsigned long Min = 2, Max = MAX_LIM;
if (argc > 1)
{
unsigned long x = strtoul(argv[1],0,0);
if (Min < x) Min = x;
if (argc > 2)
{
x = strtoul(argv[2],0,0);
if (x < Max) Max = x;
}
}
unsigned long Sqr = isqrt(Max);
{
for(unsigned long j = 9; j <= Max; j += 3)
{
if (j%2) set_primes(j);
}
for(unsigned long i = 5; i <= Sqr; i += 6)
{
if (get_primes(i)) continue;
for(unsigned long j = i * i; j <= Max; j += i)
{
if (j%2) set_primes(j);
}
}
for(unsigned long i = 7; i <= Sqr; i += 6)
{
if (get_primes(i)) continue;
for(unsigned long j = i * i; j <= Max; j += i)
{
if (j%2) set_primes(j);
}
}
}
//return 0;
int total = 0;
if (Min <= 2 && Max >= 2)
{
//puts("2");
++total;
}
if (Min <= 2) Min = 3;
for(unsigned long i = Min; i <= Max; i+=2)
{
if (get_primes(i)) continue;
++total;
//printf("%lu\n",i);
}
printf("%d primes in [1,2^20] for %lf ms\n",total,
double(clock()-start)*1000.0/CLOCKS_PER_SEC);
}