In cases of low memory available I thought it was possible to implement a double-segment sieve to find prime numbers in a neighborhood of n. In practice, a segmented sieve has dimension dim_seg_1 for smaller primes than sqrt (n) and a sieve of size dim_seg_2 for larger numbers. This is the function to find prime numbers in the range [n_start, n_start + dim_seg_2]:
import numpy as np
def double_segmented_sieve(dim_seg_1,dim_seg_2,n_start):
dim1=dim_seg_1//6
dim2=dim_seg_2//6+1
kmin=n_start//6-1
sqrt_nmax=int(((n_start+dim_seg_2)**0.5+1)/6)+1
if sqrt_nmax>(dim_seg_1**2)//6:
return -1
# vectors used to sieve prime numbers in the interval [n_start, n_start+dim_seg_2]
sieve5m6 =np.ones((dim2+1), dtype=bool)
sieve1m6 =np.ones((dim2+1), dtype=bool)
# vectors used to sieve smaller primes of sqrt (n)
sieve5m6_1 =np.ones((dim1+1), dtype=bool)
sieve1m6_1 =np.ones((dim1+1), dtype=bool)
for i in range(1,int((dim_seg_1**0.5+1)/6)+1):
if sieve5m6_1[i]:
sieve5m6_1[6*i*i::6*i-1]=[False]
sieve1m6_1[6*i*i-2*i::6*i-1]=[False]
if sieve1m6_1[i]:
sieve5m6_1[6*i*i::6*i+1]=[False]
sieve1m6_1[6*i*i+2*i::6*i+1]=[False]
sieve5m6_2 =sieve5m6_1
sieve1m6_2 =sieve1m6_1
for j in range(0,sqrt_nmax//dim1):
for i in range(1,dim1+1):
if sieve5m6_2[i]:
sieve5m6[(-kmin+i+j*dim1)%(6*(i+j*dim1)-1)::6*(i+j*dim1)-1]=[False]
sieve1m6[(-kmin-i-j*dim1)%(6*(i+j*dim1)-1)::6*(i+j*dim1)-1]=[False]
if sieve1m6_2[i]:
sieve5m6[(-kmin-i-j*dim1)%(6*(i+j*dim1)+1)::6*(i+j*dim1)+1]=[False]
sieve1m6[(-kmin+i+j*dim1)%(6*(i+j*dim1)+1)::6*(i+j*dim1)+1]=[False]
sieve5m6_2 =np.ones((dim1+1), dtype=bool)
sieve1m6_2 =np.ones((dim1+1), dtype=bool)
for i in range(1,int(((-1+(1+6*(j+1)*dim1))**0.5)/6)+1):
if sieve5m6_1[i]:
sieve5m6_2[(-(j+1)*dim1+i)%(6*i-1)::6*i-1]=[False]
sieve1m6_2[(-(j+1)*dim1-i)%(6*i-1)::6*i-1]=[False]
if sieve1m6_1[i]:
sieve5m6_2[(-(j+1)*dim1-i)%(6*i+1)::6*i+1]=[False]
sieve1m6_2[(-(j+1)*dim1+i)%(6*i+1)::6*i+1]=[False]
sieve5m6[0:1:]=[False]
sieve1m6[0:0:]=[False]
return np.r_[ (6 *(kmin+ np.nonzero(sieve5m6)[0]) - 1),(6 *(kmin+ np.nonzero(sieve1m6)[0]) + 1)]
P=np.sort(double_segmented_sieve(2**26,2**14,2**60))
Is it possible to speed up the function somehow?