line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
#include |
2
|
|
|
|
|
|
|
#include |
3
|
|
|
|
|
|
|
|
4
|
|
|
|
|
|
|
#define FUNC_is_prime_in_sieve 1 |
5
|
|
|
|
|
|
|
#define FUNC_gcd_ui 1 |
6
|
|
|
|
|
|
|
#include "sieve.h" |
7
|
|
|
|
|
|
|
#include "ptypes.h" |
8
|
|
|
|
|
|
|
#include "util.h" |
9
|
|
|
|
|
|
|
#include "primality.h" |
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
#define NSMALLPRIMES 168 |
12
|
|
|
|
|
|
|
static const unsigned short sprimes[NSMALLPRIMES] = {2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997}; |
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
typedef struct { |
15
|
|
|
|
|
|
|
uint32_t nmax; |
16
|
|
|
|
|
|
|
uint32_t nsize; |
17
|
|
|
|
|
|
|
UV* list; |
18
|
|
|
|
|
|
|
} vlist; |
19
|
|
|
|
|
|
|
#define INIT_VLIST(v) \ |
20
|
|
|
|
|
|
|
v.nsize = 0; \ |
21
|
|
|
|
|
|
|
v.nmax = 100; \ |
22
|
|
|
|
|
|
|
New(0, v.list, v.nmax, UV); |
23
|
|
|
|
|
|
|
#define PUSH_VLIST(v, n) \ |
24
|
|
|
|
|
|
|
do { \ |
25
|
|
|
|
|
|
|
if (v.nsize >= v.nmax) \ |
26
|
|
|
|
|
|
|
Renew(v.list, v.nmax += 100, UV); \ |
27
|
|
|
|
|
|
|
v.list[v.nsize++] = n; \ |
28
|
|
|
|
|
|
|
} while (0) |
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
#define ADDVAL32(v, n, max, val) \ |
31
|
|
|
|
|
|
|
do { if (n >= max) Renew(v, max += 512, UV); v[n++] = val; } while (0) |
32
|
|
|
|
|
|
|
#define SWAPL32(l1, n1, m1, l2, n2, m2) \ |
33
|
|
|
|
|
|
|
{ UV t_, *u_ = l1; l1 = l2; l2 = u_; \ |
34
|
|
|
|
|
|
|
t_ = n1; n1 = n2; n2 = t_; \ |
35
|
|
|
|
|
|
|
t_ = m1; m1 = m2; m2 = t_; } |
36
|
|
|
|
|
|
|
|
37
|
32
|
|
|
|
|
|
static int is_admissible(uint32_t nc, uint32_t* cl) { |
38
|
|
|
|
|
|
|
uint32_t i, j, c; |
39
|
32
|
|
|
|
|
|
char rset[sprimes[NSMALLPRIMES-1]]; |
40
|
|
|
|
|
|
|
|
41
|
32
|
50
|
|
|
|
|
if (nc > NSMALLPRIMES) return 1; /* TODO */ |
42
|
241
|
100
|
|
|
|
|
for (i = 0; i < nc; i++) { |
43
|
211
|
|
|
|
|
|
uint32_t p = sprimes[i]; |
44
|
211
|
|
|
|
|
|
memset(rset, 0, p); |
45
|
1906
|
100
|
|
|
|
|
for (c = 0; c < nc; c++) |
46
|
1695
|
|
|
|
|
|
rset[cl[c] % p] = 1; |
47
|
676
|
100
|
|
|
|
|
for (j = 0; j < p; j++) |
48
|
674
|
100
|
|
|
|
|
if (rset[j] == 0) |
49
|
209
|
|
|
|
|
|
break; |
50
|
211
|
100
|
|
|
|
|
if (j == p) /* All values were 1 */ |
51
|
2
|
|
|
|
|
|
return 0; |
52
|
|
|
|
|
|
|
} |
53
|
32
|
|
|
|
|
|
return 1; |
54
|
|
|
|
|
|
|
} |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
/* Given p prime, is this a cluster? */ |
57
|
88
|
|
|
|
|
|
static int is_cluster(UV p, uint32_t nc, uint32_t* cl) { |
58
|
|
|
|
|
|
|
uint32_t c; |
59
|
153
|
100
|
|
|
|
|
for (c = 1; c < nc; c++) |
60
|
141
|
100
|
|
|
|
|
if (!is_prob_prime(p+cl[c])) |
61
|
76
|
|
|
|
|
|
break; |
62
|
88
|
|
|
|
|
|
return (c == nc); |
63
|
|
|
|
|
|
|
} |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
/* This is fine for small ranges. Low overhead. */ |
66
|
32
|
|
|
|
|
|
UV* sieve_cluster_simple(UV beg, UV end, uint32_t nc, uint32_t* cl, UV* numret) |
67
|
|
|
|
|
|
|
{ |
68
|
|
|
|
|
|
|
vlist retlist; |
69
|
|
|
|
|
|
|
|
70
|
32
|
50
|
|
|
|
|
INIT_VLIST(retlist); |
71
|
32
|
100
|
|
|
|
|
if (beg <= 2 && end >= 2 && is_cluster(2, nc, cl)) PUSH_VLIST(retlist, 2); |
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
72
|
32
|
100
|
|
|
|
|
if (beg <= 3 && end >= 3 && is_cluster(3, nc, cl)) PUSH_VLIST(retlist, 3); |
|
|
50
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
73
|
32
|
100
|
|
|
|
|
if (beg <= 5 && end >= 5 && is_cluster(5, nc, cl)) PUSH_VLIST(retlist, 5); |
|
|
50
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
74
|
32
|
100
|
|
|
|
|
if (beg < 7) beg = 7; |
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
/* If not admissible, then don't keep looking. */ |
77
|
32
|
100
|
|
|
|
|
if (!is_admissible(nc, cl) && end > sprimes[nc]) |
|
|
50
|
|
|
|
|
|
78
|
2
|
|
|
|
|
|
end = sprimes[nc]; |
79
|
|
|
|
|
|
|
|
80
|
32
|
50
|
|
|
|
|
if (beg <= end) { |
81
|
|
|
|
|
|
|
uint32_t c; |
82
|
|
|
|
|
|
|
unsigned char* segment; |
83
|
|
|
|
|
|
|
UV seg_base, seg_beg, seg_end; |
84
|
|
|
|
|
|
|
|
85
|
32
|
|
|
|
|
|
void* ctx = start_segment_primes(beg, end, &segment); |
86
|
67
|
100
|
|
|
|
|
while (next_segment_primes(ctx, &seg_base, &seg_beg, &seg_end)) { |
87
|
35
|
100
|
|
|
|
|
UV sp, last_sieve_cluster = (seg_end >= cl[nc-1]) ? seg_end-cl[nc-1] : 0; |
88
|
273643
|
50
|
|
|
|
|
START_DO_FOR_EACH_SIEVE_PRIME( segment, seg_base, seg_beg, seg_end ) |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
89
|
259643
|
100
|
|
|
|
|
if (p <= last_sieve_cluster) { |
90
|
259591
|
|
|
|
|
|
sp = p - seg_base; |
91
|
289914
|
100
|
|
|
|
|
for (c = 1; c < nc; c++) |
92
|
277909
|
100
|
|
|
|
|
if (!is_prime_in_sieve(segment, sp+cl[c])) |
93
|
247586
|
|
|
|
|
|
break; |
94
|
259591
|
100
|
|
|
|
|
if (c == nc) |
95
|
259591
|
100
|
|
|
|
|
PUSH_VLIST(retlist,p); |
|
|
50
|
|
|
|
|
|
96
|
|
|
|
|
|
|
} else { |
97
|
52
|
100
|
|
|
|
|
if (is_cluster(p, nc, cl)) |
98
|
2
|
50
|
|
|
|
|
PUSH_VLIST(retlist, p); |
|
|
0
|
|
|
|
|
|
99
|
|
|
|
|
|
|
} |
100
|
13963
|
|
|
|
|
|
END_DO_FOR_EACH_SIEVE_PRIME |
101
|
|
|
|
|
|
|
} |
102
|
32
|
|
|
|
|
|
end_segment_primes(ctx); |
103
|
|
|
|
|
|
|
} |
104
|
32
|
|
|
|
|
|
*numret = retlist.nsize; |
105
|
32
|
|
|
|
|
|
return retlist.list; |
106
|
|
|
|
|
|
|
} |
107
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
#define addmodded(r,a,b,n) do { r = a + b; if (r >= n) r -= n; } while(0) |
110
|
|
|
|
|
|
|
|
111
|
32
|
|
|
|
|
|
UV* sieve_cluster(UV low, UV high, uint32_t nc, uint32_t* cl, UV* numret) |
112
|
|
|
|
|
|
|
{ |
113
|
|
|
|
|
|
|
vlist retlist; |
114
|
|
|
|
|
|
|
UV i, ppr, nres, allocres; |
115
|
32
|
|
|
|
|
|
uint32_t const targres = 100000; |
116
|
32
|
|
|
|
|
|
UV *residues, *cres, num_mr = 0, num_lucas = 0; |
117
|
|
|
|
|
|
|
uint32_t pp_0, pp_1, pp_2, *resmod_0, *resmod_1, *resmod_2; |
118
|
|
|
|
|
|
|
uint32_t rem_0, rem_1, rem_2, remadd_0, remadd_1, remadd_2; |
119
|
32
|
|
|
|
|
|
uint32_t pi, startpi = 1, maxpi = 150; |
120
|
32
|
|
|
|
|
|
uint32_t lastspr = sprimes[maxpi-1]; |
121
|
|
|
|
|
|
|
uint32_t c, smallnc; |
122
|
|
|
|
|
|
|
char crem_0[43*47], crem_1[53*59], crem_2[61*67], **VPrem; |
123
|
32
|
|
|
|
|
|
int const _verbose = _XS_get_verbose(); |
124
|
|
|
|
|
|
|
|
125
|
32
|
50
|
|
|
|
|
if ((UV_MAX - cl[nc-1]) < high) return 0; /* Overflow */ |
126
|
|
|
|
|
|
|
|
127
|
32
|
100
|
|
|
|
|
if ( ((high-low) < 10000) |
128
|
11
|
100
|
|
|
|
|
|| (nc == 3 && ((high>>31) >> 16) == 0) /* sieving large vals is slow */ |
|
|
50
|
|
|
|
|
|
129
|
8
|
100
|
|
|
|
|
|| (nc == 2 && ((high>>31) >> 27) == 0) |
|
|
50
|
|
|
|
|
|
130
|
7
|
50
|
|
|
|
|
|| (nc < 2) ) |
131
|
25
|
|
|
|
|
|
return sieve_cluster_simple(low, high, nc, cl, numret); |
132
|
|
|
|
|
|
|
|
133
|
7
|
100
|
|
|
|
|
if (!(low&1)) low++; |
134
|
7
|
50
|
|
|
|
|
if (!(high&1)) high--; |
135
|
|
|
|
|
|
|
|
136
|
7
|
50
|
|
|
|
|
INIT_VLIST(retlist); |
137
|
|
|
|
|
|
|
|
138
|
7
|
50
|
|
|
|
|
if (low < lastspr) { |
139
|
7
|
|
|
|
|
|
UV t, chigh = (high > lastspr) ? lastspr : high; |
140
|
7
|
|
|
|
|
|
UV* s = sieve_cluster_simple(low, chigh, nc, cl, &t); |
141
|
22
|
100
|
|
|
|
|
for (i = 0; i < t; i++) |
142
|
15
|
50
|
|
|
|
|
PUSH_VLIST(retlist, s[i]); |
|
|
0
|
|
|
|
|
|
143
|
7
|
|
|
|
|
|
Safefree(s); |
144
|
7
|
|
|
|
|
|
low = chigh + 2; |
145
|
|
|
|
|
|
|
} |
146
|
7
|
50
|
|
|
|
|
if (low > high) { |
147
|
0
|
|
|
|
|
|
*numret = retlist.nsize; |
148
|
0
|
|
|
|
|
|
return retlist.list; |
149
|
|
|
|
|
|
|
} |
150
|
7
|
50
|
|
|
|
|
if (low&1) low--; |
151
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
/* Determine the primorial size and acceptable residues */ |
153
|
7
|
|
|
|
|
|
New(0, residues, allocres = 1024, UV); |
154
|
|
|
|
|
|
|
{ |
155
|
|
|
|
|
|
|
UV remr, *res2, allocres2, nres2, maxppr; |
156
|
|
|
|
|
|
|
/* Calculate residues for a small primorial */ |
157
|
28
|
100
|
|
|
|
|
for (pi = 2, ppr = 1, i = 0; i <= pi; i++) ppr *= sprimes[i]; |
158
|
7
|
|
|
|
|
|
remr = low % ppr; |
159
|
7
|
|
|
|
|
|
nres = 0; |
160
|
112
|
100
|
|
|
|
|
for (i = 1; i <= ppr; i += 2) { |
161
|
216
|
100
|
|
|
|
|
for (c = 0; c < nc; c++) { |
162
|
210
|
|
|
|
|
|
UV v = (remr + i + cl[c]) % ppr; |
163
|
210
|
100
|
|
|
|
|
if (gcd_ui(v, ppr) != 1) break; |
164
|
|
|
|
|
|
|
} |
165
|
105
|
100
|
|
|
|
|
if (c == nc) |
166
|
6
|
50
|
|
|
|
|
ADDVAL32(residues, nres, allocres, i); |
|
|
0
|
|
|
|
|
|
167
|
|
|
|
|
|
|
} |
168
|
|
|
|
|
|
|
/* Raise primorial size until we have plenty of residues */ |
169
|
7
|
|
|
|
|
|
New(0, res2, allocres2 = 1024, UV); |
170
|
7
|
|
|
|
|
|
maxppr = high - low; |
171
|
|
|
|
|
|
|
#if BITS_PER_WORD == 64 |
172
|
31
|
50
|
|
|
|
|
while (pi++ < 12) { |
173
|
|
|
|
|
|
|
#else |
174
|
|
|
|
|
|
|
while (pi++ < 8) { |
175
|
|
|
|
|
|
|
#endif |
176
|
31
|
|
|
|
|
|
uint32_t j, p = sprimes[pi]; |
177
|
31
|
|
|
|
|
|
UV r, newppr = ppr * p; |
178
|
31
|
100
|
|
|
|
|
if (nres == 0 || nres > targres/(p/2) || newppr > maxppr) break; |
|
|
50
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
179
|
24
|
50
|
|
|
|
|
if (_verbose > 1) printf("cluster sieve found %"UVuf" residues mod %"UVuf"\n", nres, ppr); |
180
|
24
|
|
|
|
|
|
remr = low % newppr; |
181
|
24
|
|
|
|
|
|
nres2 = 0; |
182
|
312
|
100
|
|
|
|
|
for (i = 0; i < p; i++) { |
183
|
9082
|
100
|
|
|
|
|
for (j = 0; j < nres; j++) { |
184
|
8794
|
|
|
|
|
|
r = i*ppr + residues[j]; |
185
|
43800
|
100
|
|
|
|
|
for (c = 0; c < nc; c++) { |
186
|
37642
|
|
|
|
|
|
UV v = remr + r + cl[c]; |
187
|
37642
|
100
|
|
|
|
|
if ((v % p) == 0) break; |
188
|
|
|
|
|
|
|
} |
189
|
8794
|
100
|
|
|
|
|
if (c == nc) |
190
|
6158
|
100
|
|
|
|
|
ADDVAL32(res2, nres2, allocres2, r); |
|
|
50
|
|
|
|
|
|
191
|
|
|
|
|
|
|
} |
192
|
|
|
|
|
|
|
} |
193
|
24
|
|
|
|
|
|
ppr = newppr; |
194
|
24
|
|
|
|
|
|
SWAPL32(residues, nres, allocres, res2, nres2, allocres2); |
195
|
|
|
|
|
|
|
} |
196
|
7
|
|
|
|
|
|
startpi = pi; |
197
|
7
|
|
|
|
|
|
Safefree(res2); |
198
|
|
|
|
|
|
|
} |
199
|
7
|
50
|
|
|
|
|
if (_verbose) printf("cluster sieve using %"UVuf" residues mod %"UVuf"\n", nres, ppr); |
200
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
/* Return if not admissible, maybe with a single small value */ |
202
|
7
|
100
|
|
|
|
|
if (nres == 0) { |
203
|
1
|
|
|
|
|
|
Safefree(residues); |
204
|
1
|
|
|
|
|
|
*numret = retlist.nsize; |
205
|
1
|
|
|
|
|
|
return retlist.list; |
206
|
|
|
|
|
|
|
} |
207
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
/* Pre-mod the residues with first two primes for fewer modulos every chunk */ |
209
|
|
|
|
|
|
|
{ |
210
|
6
|
|
|
|
|
|
uint32_t p1 = sprimes[startpi+0], p2 = sprimes[startpi+1]; |
211
|
6
|
|
|
|
|
|
uint32_t p3 = sprimes[startpi+2], p4 = sprimes[startpi+3]; |
212
|
6
|
|
|
|
|
|
uint32_t p5 = sprimes[startpi+4], p6 = sprimes[startpi+5]; |
213
|
6
|
|
|
|
|
|
pp_0 = p1*p2; pp_1 = p3*p4; pp_2 = p5*p6; |
214
|
6
|
|
|
|
|
|
memset(crem_0, 1, pp_0); |
215
|
6
|
|
|
|
|
|
memset(crem_1, 1, pp_1); |
216
|
6
|
|
|
|
|
|
memset(crem_2, 1, pp_2); |
217
|
|
|
|
|
|
|
/* Mark remainders that indicate a composite for this residue. */ |
218
|
120
|
100
|
|
|
|
|
for (i = 0; i < p1; i++) { crem_0[i*p1]=0; crem_0[i*p2]=0; } |
219
|
30
|
100
|
|
|
|
|
for ( ; i < p2; i++) { crem_0[i*p1]=0; } |
220
|
180
|
100
|
|
|
|
|
for (i = 0; i < p3; i++) { crem_1[i*p3]=0; crem_1[i*p4]=0; } |
221
|
18
|
100
|
|
|
|
|
for ( ; i < p4; i++) { crem_1[i*p3]=0; } |
222
|
228
|
100
|
|
|
|
|
for (i = 0; i < p5; i++) { crem_2[i*p5]=0; crem_2[i*p6]=0; } |
223
|
30
|
100
|
|
|
|
|
for ( ; i < p6; i++) { crem_2[i*p5]=0; } |
224
|
34
|
100
|
|
|
|
|
for (c = 1; c < nc; c++) { |
225
|
28
|
|
|
|
|
|
uint32_t c1=cl[c], c2=cl[c], c3=cl[c], c4=cl[c], c5=cl[c], c6=cl[c]; |
226
|
28
|
100
|
|
|
|
|
if (c1 >= p1) c1 %= p1; |
227
|
28
|
50
|
|
|
|
|
if (c2 >= p2) c2 %= p2; |
228
|
560
|
100
|
|
|
|
|
for (i = 1; i <= p1; i++) { crem_0[i*p1-c1]=0; crem_0[i*p2-c2]=0; } |
229
|
140
|
100
|
|
|
|
|
for ( ; i <= p2; i++) { crem_0[i*p1-c1]=0; } |
230
|
28
|
50
|
|
|
|
|
if (c3 >= p3) c3 %= p3; |
231
|
28
|
50
|
|
|
|
|
if (c4 >= p4) c4 %= p4; |
232
|
840
|
100
|
|
|
|
|
for (i = 1; i <= p3; i++) { crem_1[i*p3-c3]=0; crem_1[i*p4-c4]=0; } |
233
|
84
|
100
|
|
|
|
|
for ( ; i <= p4; i++) { crem_1[i*p3-c3]=0; } |
234
|
28
|
50
|
|
|
|
|
if (c5 >= p5) c5 %= p5; |
235
|
28
|
50
|
|
|
|
|
if (c6 >= p6) c6 %= p6; |
236
|
1064
|
100
|
|
|
|
|
for (i = 1; i <= p5; i++) { crem_2[i*p5-c5]=0; crem_2[i*p6-c6]=0; } |
237
|
140
|
100
|
|
|
|
|
for ( ; i <= p6; i++) { crem_2[i*p5-c5]=0; } |
238
|
|
|
|
|
|
|
} |
239
|
6
|
50
|
|
|
|
|
New(0, resmod_0, nres, uint32_t); |
240
|
6
|
50
|
|
|
|
|
New(0, resmod_1, nres, uint32_t); |
241
|
6
|
50
|
|
|
|
|
New(0, resmod_2, nres, uint32_t); |
242
|
5632
|
100
|
|
|
|
|
for (i = 0; i < nres; i++) { |
243
|
5626
|
|
|
|
|
|
resmod_0[i] = residues[i] % pp_0; |
244
|
5626
|
|
|
|
|
|
resmod_1[i] = residues[i] % pp_1; |
245
|
5626
|
|
|
|
|
|
resmod_2[i] = residues[i] % pp_2; |
246
|
|
|
|
|
|
|
} |
247
|
|
|
|
|
|
|
} |
248
|
|
|
|
|
|
|
|
249
|
|
|
|
|
|
|
/* Precalculate acceptable residues for more primes */ |
250
|
6
|
50
|
|
|
|
|
New(0, VPrem, maxpi, char*); |
251
|
6
|
|
|
|
|
|
memset(VPrem, 0, maxpi); |
252
|
828
|
100
|
|
|
|
|
for (pi = startpi+6; pi < maxpi; pi++) { |
253
|
822
|
|
|
|
|
|
uint32_t p = sprimes[pi]; |
254
|
822
|
|
|
|
|
|
New(0, VPrem[pi], p, char); |
255
|
822
|
|
|
|
|
|
memset(VPrem[pi], 1, p); |
256
|
|
|
|
|
|
|
} |
257
|
828
|
100
|
|
|
|
|
for (pi = startpi+6, smallnc = 0; pi < maxpi; pi++) { |
258
|
822
|
|
|
|
|
|
uint32_t p = sprimes[pi]; |
259
|
822
|
|
|
|
|
|
char* prem = VPrem[pi]; |
260
|
822
|
|
|
|
|
|
prem[0] = 0; |
261
|
856
|
100
|
|
|
|
|
while (smallnc < nc && cl[smallnc] < p) smallnc++; |
|
|
50
|
|
|
|
|
|
262
|
4658
|
100
|
|
|
|
|
for (c = 1; c < smallnc; c++) prem[p-cl[c]] = 0; |
263
|
822
|
50
|
|
|
|
|
for ( ; c < nc; c++) prem[p-(cl[c]%p)] = 0; |
264
|
|
|
|
|
|
|
} |
265
|
|
|
|
|
|
|
|
266
|
6
|
50
|
|
|
|
|
New(0, cres, nres, UV); |
267
|
|
|
|
|
|
|
|
268
|
6
|
|
|
|
|
|
rem_0 = low % pp_0; remadd_0 = ppr % pp_0; |
269
|
6
|
|
|
|
|
|
rem_1 = low % pp_1; remadd_1 = ppr % pp_1; |
270
|
6
|
|
|
|
|
|
rem_2 = low % pp_2; remadd_2 = ppr % pp_2; |
271
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
/* Loop over their range in chunks of size 'ppr' */ |
273
|
24
|
100
|
|
|
|
|
while (low <= high) { |
274
|
|
|
|
|
|
|
uint32_t r, nr, remr, ncres; |
275
|
|
|
|
|
|
|
|
276
|
|
|
|
|
|
|
/* Reduce the allowed residues for this chunk using more primes */ |
277
|
|
|
|
|
|
|
|
278
|
|
|
|
|
|
|
{ /* Start making a list of this chunk's residues using three pairs */ |
279
|
16896
|
100
|
|
|
|
|
for (r = 0, ncres = 0; r < nres; r++) { |
280
|
16878
|
100
|
|
|
|
|
addmodded(remr, rem_0, resmod_0[r], pp_0); |
281
|
16878
|
100
|
|
|
|
|
if (crem_0[remr]) { |
282
|
9995
|
100
|
|
|
|
|
addmodded(remr, rem_1, resmod_1[r], pp_1); |
283
|
9995
|
100
|
|
|
|
|
if (crem_1[remr]) { |
284
|
7113
|
100
|
|
|
|
|
addmodded(remr, rem_2, resmod_2[r], pp_2); |
285
|
7113
|
100
|
|
|
|
|
if (crem_2[remr]) { |
286
|
5520
|
|
|
|
|
|
cres[ncres++] = residues[r]; |
287
|
|
|
|
|
|
|
} |
288
|
|
|
|
|
|
|
} |
289
|
|
|
|
|
|
|
} |
290
|
|
|
|
|
|
|
} |
291
|
18
|
100
|
|
|
|
|
addmodded(rem_0, rem_0, remadd_0, pp_0); |
292
|
18
|
50
|
|
|
|
|
addmodded(rem_1, rem_1, remadd_1, pp_1); |
293
|
18
|
100
|
|
|
|
|
addmodded(rem_2, rem_2, remadd_2, pp_2); |
294
|
|
|
|
|
|
|
} |
295
|
|
|
|
|
|
|
|
296
|
|
|
|
|
|
|
/* Sieve through more primes one at a time, removing residues. */ |
297
|
2455
|
100
|
|
|
|
|
for (pi = startpi+6; pi < maxpi && ncres > 0; pi++) { |
|
|
100
|
|
|
|
|
|
298
|
2437
|
|
|
|
|
|
uint32_t p = sprimes[pi]; |
299
|
2437
|
|
|
|
|
|
uint32_t rem = low % p; |
300
|
2437
|
|
|
|
|
|
char* prem = VPrem[pi]; |
301
|
|
|
|
|
|
|
/* Check divisibility of each remaining residue with this p */ |
302
|
|
|
|
|
|
|
/* If we extended prem we could remove the add in the loop below */ |
303
|
2437
|
50
|
|
|
|
|
if (startpi <= 9) { /* Residues are 32-bit */ |
304
|
142234
|
100
|
|
|
|
|
for (r = 0, nr = 0; r < ncres; r++) { |
305
|
139797
|
100
|
|
|
|
|
if (prem[ (rem+(uint32_t)cres[r]) % p ]) |
306
|
134664
|
|
|
|
|
|
cres[nr++] = cres[r]; |
307
|
|
|
|
|
|
|
} |
308
|
|
|
|
|
|
|
} else { /* Residues are 64-bit */ |
309
|
0
|
0
|
|
|
|
|
for (r = 0, nr = 0; r < ncres; r++) { |
310
|
0
|
0
|
|
|
|
|
if (prem[ (rem+cres[r]) % p ]) |
311
|
0
|
|
|
|
|
|
cres[nr++] = cres[r]; |
312
|
|
|
|
|
|
|
} |
313
|
|
|
|
|
|
|
} |
314
|
2437
|
|
|
|
|
|
ncres = nr; |
315
|
|
|
|
|
|
|
} |
316
|
18
|
50
|
|
|
|
|
if (_verbose > 2) printf("cluster sieve range has %u residues left\n", ncres); |
317
|
|
|
|
|
|
|
|
318
|
|
|
|
|
|
|
/* Now check each of the remaining residues for inclusion */ |
319
|
286
|
100
|
|
|
|
|
for (r = 0; r < ncres; r++) { |
320
|
272
|
|
|
|
|
|
UV p = low + cres[r]; |
321
|
272
|
100
|
|
|
|
|
if (p > high) break; |
322
|
|
|
|
|
|
|
/* PRP test. Split to save time. */ |
323
|
1425
|
100
|
|
|
|
|
for (c = 0; c < nc; c++) |
324
|
1166
|
100
|
|
|
|
|
if (num_mr++,!is_euler_plumb_pseudoprime(p+cl[c])) |
325
|
9
|
|
|
|
|
|
break; |
326
|
268
|
100
|
|
|
|
|
if (c < nc) continue; |
327
|
1393
|
100
|
|
|
|
|
for (c = 0; c < nc; c++) |
328
|
1134
|
50
|
|
|
|
|
if (num_lucas++,!is_almost_extra_strong_lucas_pseudoprime(p+cl[c], 1)) |
329
|
0
|
|
|
|
|
|
break; |
330
|
259
|
50
|
|
|
|
|
if (c < nc) continue; |
331
|
259
|
100
|
|
|
|
|
PUSH_VLIST(retlist, p); |
|
|
50
|
|
|
|
|
|
332
|
|
|
|
|
|
|
} |
333
|
18
|
|
|
|
|
|
low += ppr; |
334
|
18
|
50
|
|
|
|
|
if (low < ppr) low = UV_MAX; |
335
|
|
|
|
|
|
|
} |
336
|
|
|
|
|
|
|
|
337
|
6
|
50
|
|
|
|
|
if (_verbose) printf("cluster sieve ran %"UVuf" MR and %"UVuf" Lucas tests\n", num_mr, num_lucas); |
338
|
828
|
100
|
|
|
|
|
for (pi = startpi+6; pi < maxpi; pi++) |
339
|
822
|
|
|
|
|
|
Safefree(VPrem[pi]); |
340
|
6
|
|
|
|
|
|
Safefree(VPrem); |
341
|
6
|
|
|
|
|
|
Safefree(resmod_0); |
342
|
6
|
|
|
|
|
|
Safefree(resmod_1); |
343
|
6
|
|
|
|
|
|
Safefree(resmod_2); |
344
|
6
|
|
|
|
|
|
Safefree(cres); |
345
|
6
|
|
|
|
|
|
Safefree(residues); |
346
|
6
|
|
|
|
|
|
*numret = retlist.nsize; |
347
|
32
|
|
|
|
|
|
return retlist.list; |
348
|
|
|
|
|
|
|
} |