Skip to content

Instantly share code, notes, and snippets.

@user140242
Last active January 4, 2023 23:28
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save user140242/ed2f0b8b93e0257ffd8e5f9bafdd20f7 to your computer and use it in GitHub Desktop.
Save user140242/ed2f0b8b93e0257ffd8e5f9bafdd20f7 to your computer and use it in GitHub Desktop.
bit wheel segmented sieve basic choice 30 210 2310
/// This is a implementation of the bit wheel segmented sieve
/// with max base wheel choice 30 , 210 , 2310
#include <iostream>
#include <cmath>
#include <algorithm>
#include <vector>
#include <cstdlib>
#include <stdint.h>
#include <time.h>
const int64_t PrimesBase[5]={2,3,5,7,11};
const int64_t n_PB_max = 5;
const int64_t del_bit[8] =
{
~(1 << 0),~(1 << 1),~(1 << 2),~(1 << 3),
~(1 << 4),~(1 << 5),~(1 << 6),~(1 << 7)
};
const int64_t bit_count[256] =
{
0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
};
int64_t Euclidean_Diophantine( int64_t coeff_a, int64_t coeff_b)
{
// return y in Diophantine equation coeff_a x + coeff_b y = 1
int64_t k=1;
std::vector<int64_t> div_t;
std::vector<int64_t> rem_t;
std::vector<int64_t> coeff_t;
div_t.push_back(coeff_a);
rem_t.push_back(coeff_b);
coeff_t.push_back((int64_t)0);
div_t.push_back((int64_t)div_t[0]/rem_t[0]);
rem_t.push_back((int64_t)div_t[0]%rem_t[0]);
coeff_t.push_back((int64_t)0);
while (rem_t[k]>1)
{
k=k+1;
div_t.push_back((int64_t)rem_t[k-2]/rem_t[k-1]);
rem_t.push_back((int64_t)rem_t[k-2]%rem_t[k-1]);
coeff_t.push_back((int64_t)0);
}
k=k-1;
coeff_t[k]=-div_t[k+1];
if (k>0)
coeff_t[k-1]=(int64_t)1;
while (k > 1)
{
k=k-1;
coeff_t[k-1]=coeff_t[k+1];
coeff_t[k]+=(int64_t)(coeff_t[k+1]*(-div_t[k+1]));
}
if (k==1)
return (int64_t)(coeff_t[k-1]+coeff_t[k]*(-div_t[k]));
else
return (int64_t)(coeff_t[0]);
}
void segmented_bit_sieve_wheel(uint64_t n,int64_t max_bW)
{
int64_t sqrt_n = (int64_t) std::sqrt(n);
int64_t count_p=(int64_t)0;
int64_t n_PB=(int64_t)3;
int64_t bW=(int64_t)30;
//get bW base wheel equal to p1*p2*...*pn <=max_bW with n=n_PB
while(n_PB<n_PB_max&&(bW*PrimesBase[n_PB]<=std::min(max_bW,sqrt_n)))
{
bW*=PrimesBase[n_PB];
n_PB++;
}
for (int64_t i=0; i< n_PB;i++)
if (n>PrimesBase[i])
count_p++;
if (n>1+PrimesBase[n_PB-1]){
int64_t k_end = (n < bW) ? (int64_t)2 :(int64_t) (n/(uint64_t)bW+1);
int64_t k_sqrt = (int64_t) std::sqrt(k_end/bW)+1;
//find possible remainder of base module
std::vector<char> Remainder_i_t(bW+1,true);
for (int64_t i=0; i< n_PB;i++)
for (int64_t j=PrimesBase[i]*PrimesBase[i];j< bW+1;j+=PrimesBase[i])
Remainder_i_t[j]=false;
std::vector<int64_t> RW;
for (int64_t j=PrimesBase[n_PB-1]+1;j< bW+1;j++)
if (Remainder_i_t[j]==true)
RW.push_back(-bW+j);
RW.push_back(1);
int64_t nR=RW.size();
std::vector<int64_t> C1(nR*nR);
std::vector<int64_t> C2(nR*nR);
for (int64_t j=0; j<nR-2; j++)
{
int64_t rW_t,rW_t1;
rW_t1=Euclidean_Diophantine(bW,-RW[j]);
for (int64_t i=0; i<nR; i++)
{
if (i==j)
{
C2[nR*i+j]=0;
C1[nR*i+j]=RW[j]+1;
}
else if(i==nR-3-j )
{
C2[nR*i+j]=1;
C1[nR*i+j]=RW[j]-1;
}
else
{
rW_t=(int64_t)(rW_t1*(-RW[i]))%bW;
if (rW_t>1)
rW_t-=bW;
C1[nR*i+j]=rW_t+RW[j];
C2[nR*i+j]=(int64_t)(rW_t*RW[j])/bW+1;
if (i==nR-1)
C2[nR*i+j]-=1;
}
}
C2[nR*j+nR-2]=(int64_t)1;
C1[nR*j+nR-2]=-(bW+RW[j])-1;
C1[nR*j+nR-1]=RW[j]+1;
C2[nR*j+nR-1]=(int64_t)0;
}
for (int64_t i=nR-2; i<nR; i++)
{
C2[nR*i+nR-2]=(int64_t)0;
C1[nR*i+nR-2]=-RW[i]-1;
C1[nR*i+nR-1]=RW[i]+1;
C2[nR*i+nR-1]=(int64_t)0;
}
int64_t nB=nR/8;
int64_t segment_size=1;
int64_t p_mask_i=(int64_t)4;
for (int64_t i=0; i<p_mask_i;i++)
segment_size*=(bW+RW[i]); //if bW=30 =7*11*13*17
while (segment_size<k_sqrt && p_mask_i<7)
{
segment_size*=(bW+RW[p_mask_i]); //if bW=30 max value =7*11*13*17*19*23*29
p_mask_i++;
}
int64_t segment_size_b=nB*segment_size;
std::vector<uint8_t> Primes(nB+segment_size_b, 0xff);
std::vector<uint8_t> Segment_i(nB+segment_size_b, 0xff);
int64_t pb,mb,mmin,ib,i,jb,j,k,kb;
int64_t kmax = (int64_t) std::sqrt(segment_size/bW)+(int64_t)1;
for (k =(int64_t)1; k <= kmax; k++)
{
kb=k*nB;
for (jb = 0; jb<nB; jb++)
{
for (j = 0; j<8; j++)
{
if(Primes[kb+jb] & (1 << j))
{
for (ib = 0; ib<nB; ib++)
{
for (i = 0; i<8; i++)
{
pb=nB*(bW*k+RW[j+jb*8]);
mmin=nB*(bW*k*k + k*C1[(i+ib*8)*nR+j+jb*8] + C2[(i+ib*8)*nR+j+jb*8]);
for (mb =mmin; mb <= segment_size_b && mb>=(int64_t)0; mb +=pb )
Primes[mb+ib] &= del_bit[i];
if (pb<nB*(bW+RW[p_mask_i]) && k_end>segment_size)
{
mb-=segment_size_b;
while (mb<(int8_t)0)
mb+=pb;
for (; mb <= segment_size_b; mb +=pb )
Segment_i[mb+ib] &= del_bit[i];
}
}
}
}
}
}
}
for (kb = nB; kb < std::min (nB+segment_size_b,nB*k_end); kb++)
count_p+=bit_count[Primes[kb]];
if (kb==nB*k_end && kb<=segment_size_b && kb>(int64_t)0)
for (ib = 0; ib<nB; ib++)
for (i = 0; i < 8; i++)
if(Primes[kb+ib]& (1 << i) && RW[i+ib*8]<(int64_t)(n%bW-bW))
count_p++;
if (k_end>segment_size)
{
int64_t k_low,kb_low;
std::vector<uint8_t> Segment_t(nB+segment_size_b);
for (int64_t k_low = segment_size; k_low < k_end; k_low += segment_size)
{
kb_low=k_low*nB;
for (kb = (int64_t)0; kb <(nB+segment_size_b); kb++)
Segment_t[kb]=Segment_i[kb];
kmax=(std::min(segment_size,(int64_t)std::sqrt((k_low+segment_size)/bW)+2));
j=p_mask_i;
for(k=(int64_t)1; k<=kmax;k++)
{
kb=k*nB;
for (jb = 0; jb<nB; jb++)
{
for (; j < 8; j++)
{
if (Primes[kb+jb]& (1 << j))
{
for (ib = 0; ib<nB; ib++)
{
for (i = 0; i < 8; i++)
{
pb=bW*k+RW[j+jb*8];
mmin=-k_low+bW*k*k+ k*C1[(i+ib*8)*nR+j+jb*8] + C2[(i+ib*8)*nR+j+jb*8];
if (mmin<0)
mmin=(mmin%pb+pb)%pb;
mmin*=nB;
pb*=nB;
for (mb =mmin; mb <= segment_size_b; mb += pb)
Segment_t[mb+ib] &= del_bit[i];
}
}
}
}
j=(int64_t)0;
}
}
for ( kb =nB+kb_low; kb <std::min (kb_low+segment_size_b+nB,nB*k_end); kb++)
count_p+=bit_count[Segment_t[kb-kb_low]];
}
if (kb==nB*k_end && kb-kb_low<=segment_size_b && kb-kb_low>(int64_t)0)
for (ib = 0; ib<nB; ib++)
for (i = 0; i < 8; i++)
if(Segment_t[kb-kb_low+ib]& (1 << i) && RW[i+ib*8]<(int64_t)(n%bW-bW))
count_p++;
}
}
std::cout << " primes < " << n << ": "<< count_p<< std::endl;
}
int main()
{
//segmented_bit_sieve_wheel(n,max_bW) with max base wheel max_bW= 30 , 210 , 2310
segmented_bit_sieve_wheel(100000000,30);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment