#include <iostream>
#include <utility>
#include <vector>
#include <list>
#include <cassert>
#include <fstream>
#include <cstring>
template <class T>
class Sieve {
uint64_t buffsize;
T *buff;
static std::pair<uint64_t, uint64_t> index(uint64_t n) {
std::pair<uint64_t, uint64_t> retv;
retv.first = (n - 1) / (8 * sizeof(T)); /* zero origin */
uint64_t bit = (n - 1) % (8 * sizeof(T)); /* zero origin */
T mask = 1;
for (uint64_t i = 0; i < bit; i++) mask = (mask << 1);
retv.second = mask;
return retv;
}
public:
Sieve(uint64_t n) {
std::pair<uint64_t, uint64_t> retindexf = index(n);
buffsize = retindexf.first + 1; /* zero origin */
buff = new T [buffsize];
for (uint64_t i = 0; i < buffsize; i++) buff[i] = 0;
}
~Sieve() {
delete buff;
}
void setSieve(uint64_t n) {
std::pair<uint64_t, uint64_t> maskpos = index(n);
buff[maskpos.first] = buff[maskpos.first] | maskpos.second;
}
bool isSieveTrue(uint64_t n) {
std::pair<uint64_t, uint64_t> maskpos = index(n);
return buff[maskpos.first] & maskpos.second;
}
};
template <class T>
class SieveDerived : private Sieve<T> {
static int index(uint64_t n) {
int r1 = n / 30;
int r2 = n % 30;
switch (r2) {
case 0:
/* 1 */
case 2:
case 3:
case 4:
case 5:
case 6:
/* 7 */
case 8:
case 9:
case 10:
/* 11 */
case 12:
/* 13 */
case 14:
case 15:
case 16:
/* 17 */
case 18:
/* 19 */
case 20:
case 21:
case 22:
/* 23 */
case 24:
case 25:
case 26:
case 27:
case 28:
/* 29 */
return 0;
case 1:
return 8 * r1 + 1;
case 7:
return 8 * r1 + 2;
case 11:
return 8 * r1 + 3;
case 13:
return 8 * r1 + 4;
case 17:
return 8 * r1 + 5;
case 19:
return 8 * r1 + 6;
case 23:
return 8 * r1 + 7;
case 29:
return 8 * r1 + 8;
default:
return 0;
}
}
public:
// SieveDerived(int n) : Sieve<T>(({int r; while((r = index(n)) == 0) n--; r;})) { } /* HERE!! */
SieveDerived(uint64_t n) : Sieve<T>([](uint64_t n)->uint64_t{uint64_t r; while ((r = index(n)) == 0) n--; return r;}(n)) { } /* HERE!! */
~SieveDerived() { }
void setSieve(uint64_t n) {
uint64_t r = index(n);
if (r == 0) return;
return ((Sieve<T> *)this)->setSieve(r);
}
bool isSieveTrue(int n) {
uint64_t r = index(n);
if (r == 0) return true;
return ((Sieve<T> *)this)->isSieveTrue(index(n));
}
};
template <class T>
class Array : public std::vector<T> {
public:
Array() : std::vector<T>() { }
~Array() { }
T &operator[](std::size_t idx) {
if (idx >= this->size()) {
while (this->size() <= idx) this->push_back(0);
}
return (*(std::vector<T> *)this)[idx];
}
};
/*------------------------------------------------------------------*/
// 123456789AB
constexpr uint64_t MAXNUM_Default = 100000000000;
constexpr unsigned int windowSize_Default = 30 * 5000000;
char const filename[] = "prime.bin";
Array<uint64_t> array;
uint64_t maxSpanLast = 0;
void spancheck(uint64_t prime, uint64_t n) {
uint64_t maxSpanNowFreq = 0; uint64_t maxSpanNow = 0;
for (uint64_t k = 1; k < array.size(); k++)
if (array[k] > maxSpanNowFreq) {
maxSpanNow = k;
maxSpanNowFreq = array[k];
}
if (maxSpanNow != maxSpanLast) {
std::cout << "span = " << maxSpanNow * 2 << ", p = " << prime << ", n = " << n << std::endl;
maxSpanLast = maxSpanNow;
}
}
void registspan(uint64_t &n, uint64_t prime, uint64_t &primeNow, uint64_t &primeLast) {
n++;
// std::cout << "size() = " << primeTable.size() << " " << std::flush;
primeNow = prime;
array[(primeNow - primeLast) / 2]++;
primeLast = primeNow;
}
static bool flag_continue = 0;
static uint64_t MAXNUM = 0;
static unsigned int windowSize = 0;
int main(int argc, char *argv[]) {
if (argc > 4) {
label_usage:
std::cerr << argv[0] << " : search prime-to-prime span." << std::endl;
std::cerr << "usage: " << argv[0] << " <search-max-range> <sieve-range>" << std::endl;
std::cerr << "option: /continue : continuing search using generated table : 'prime.bin' already :" << filename << "." << std::endl;
return 0;
}
int nowstep = 0;
for (int i = 1; i < argc; i++) {
if (strstr(argv[i], "/continue") == argv[i]) {
flag_continue = true;
continue;
}
switch (nowstep) {
case 0:
MAXNUM = atoi(argv[i]);
nowstep++;
continue;
case 1:
windowSize = atoi(argv[i]);
nowstep++;
continue;
default:
goto label_usage;
}
}
if (MAXNUM == 0) MAXNUM = MAXNUM_Default;
if (windowSize == 0) windowSize = windowSize_Default;
if (windowSize % 30 != 0) {
std::cerr << "bad windowSize, aborted." << std::endl;
return 0;
}
uint64_t n = 0;
uint64_t primeLast, primeNow;
uint64_t offset = 0;
std::fstream f;
std::fstream::pos_type hasReadPosition;
std::fstream::pos_type hasWrittenPosition;
if (!flag_continue) {
f.open(filename, std::ios::in | std::ios::out | std::ios::binary | std::ios::trunc );
} else {
f.open(filename, std::ios::in | std::ios::out | std::ios::binary);
}
if (!f) { std::cerr << "cannnot open the file, aborted." << std::endl; exit(0); }
if (!flag_continue) {
uint64_t w;
f.seekp(0, std::ios_base::beg); /* seekput1-1 */
SieveDerived<uint64_t> sieve(windowSize);
sieve.setSieve(1);
// sieve.setSieve(2); std::cout << 2 << ", ";
w = 2; f.write((char *)&w, sizeof(w));
n++;
// sieve.setSieve(3); std::cout << 3 << ", ";
w = 3; f.write((char *)&w, sizeof(w));
n++;
primeLast = 3;
sieve.setSieve(4);
// sieve.setSieve(5); std::cout << 5 << ", ";
w = 5; f.write((char *)&w, sizeof(w));
hasWrittenPosition = f.tellp();
n++;
primeNow = 5;
array[(primeNow - primeLast) / 2]++;
primeLast = primeNow;
sieve.setSieve(6);
for (uint64_t i = 7; i <= windowSize; i++) {
if (i > MAXNUM)
break;
if (!sieve.isSieveTrue(i)) {
std::cout << i << ", " << std::flush;
f.seekp(hasWrittenPosition, std::ios_base::beg);
f.write(reinterpret_cast<char *>(&i), sizeof(i));
hasWrittenPosition = f.tellp();
registspan(n, i, primeNow, primeLast);
for (uint64_t j = i * 2; j <= windowSize; j += i) sieve.setSieve(j);
spancheck(i, n);
}
}
offset = windowSize;
} else { /* continue */
uint64_t data, last;
std::cout << "continue." << std::endl;
/* step.1 */
f.seekg(0, std::ios_base::beg);
data = 0;
for (;;) {
hasReadPosition = f.tellg();
f.read((char *)&data, sizeof(data));
if (!f.good())
break;
if (data == 2) { n++; continue; }
if (data == 3) { n++; primeLast = data; continue; }
if (data <= primeLast) {
std::cerr << "data = " << data << ", primeLast = " << primeLast << std::endl;
std::cerr << "data corupted, aborted.(1)" << std::endl;
std::cerr << "prime.bin is chunked. pos = " << hasReadPosition << std::endl;
data = primeLast;
break;
}
registspan(n, data, primeNow, primeLast);
if (n % 100000000 == 0) std::cout << "n = " << n << std::endl;
}
if (data == 0) { std::cerr << "data corupted, aborted.(2)" << std::endl; exit(0); }
last = data;
std::cout << "last = " << last << std::endl;
last++;
f.clear(); /* needed */
f.seekp(hasReadPosition, std::ios_base::beg); /* seekput2-1 */
hasWrittenPosition = f.tellp();
/* step.2 */
int flag;
uint64_t primeStep2;
uint64_t near_offset = ((last + (windowSize - 1))/ windowSize) * windowSize;
for (primeStep2 = last; primeStep2 < near_offset; primeStep2++) {
f.seekg(0, std::ios_base::beg);
hasReadPosition = f.tellg();
for (;;) {
uint64_t p;
f.seekg(hasReadPosition, std::ios_base::beg);
f.read((char *)&p, sizeof(p));
hasReadPosition = f.tellg();
if (primeStep2 % p == 0) { flag = 1; break; }
if (primeStep2 / p < p) { flag = 2; break; }
}
if (flag == 1) continue;
assert(flag == 2);
f.seekp(hasWrittenPosition, std::ios_base::beg);
f.write(reinterpret_cast<char *>(&primeStep2), sizeof(primeStep2));
hasWrittenPosition = f.tellp();
std::cout << "prime = " << primeStep2 << std::endl;
registspan(n, primeStep2, primeNow, primeLast);
}
offset = primeStep2;
std::cout << "offset = " << offset << std::endl;
std::cout << "n = " << n << std::endl;
}
for (; offset < MAXNUM; offset += windowSize) {
std::cout << "offset = " << offset << std::endl;
SieveDerived<uint64_t> sieve(windowSize);
f.seekg(0, std::ios_base::beg);
hasReadPosition = f.tellg();
for (;;) {
/* loop out 1 */
if ((uint64_t)f.tellg() >= n * sizeof(uint64_t))
break;
uint64_t p;
f.seekg(hasReadPosition, std::ios_base::beg);
f.read((char *)&p, sizeof(p));
hasReadPosition = f.tellg();
/* loop out 2 */
if (p > (offset + windowSize) / 2)
break;
/* loop body */
for (uint64_t i = offset - (offset % p) + p; i < offset + windowSize; i += p)
sieve.setSieve(i - offset);
}
for (uint64_t index = 0; index < windowSize; index++) {
if (offset + index > MAXNUM)
break;
if (!sieve.isSieveTrue(index)) {
std::cout << offset + index << ", " << std::flush;
uint64_t prime = offset + index;
f.seekp(hasWrittenPosition, std::ios_base::beg);
f.write(reinterpret_cast<char *>(&prime), sizeof(prime));
hasWrittenPosition = f.tellp();
registspan(n, prime, primeNow, primeLast);
spancheck(prime, n);
}
}
} /* for (offset = windowSize; ...) */
f.close();
std::cout << std::endl << "n = " << n << std::endl;
for (uint64_t k = 0; k < array.size(); k++) {
if (array[k] > 0)
std::cout << k * 2 << ":" << array[k] << std::endl;
}
return 0;
}
/* end */