| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
#include |
|
2
|
|
|
|
|
|
|
#include |
|
3
|
|
|
|
|
|
|
#include |
|
4
|
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
#include "ptypes.h" |
|
6
|
|
|
|
|
|
|
#include "constants.h" |
|
7
|
|
|
|
|
|
|
#include "cache.h" |
|
8
|
|
|
|
|
|
|
#include "sieve.h" |
|
9
|
|
|
|
|
|
|
#include "twin_primes.h" |
|
10
|
|
|
|
|
|
|
#include "prime_counts.h" |
|
11
|
|
|
|
|
|
|
#include "inverse_interpolate.h" |
|
12
|
|
|
|
|
|
|
#include "real.h" |
|
13
|
|
|
|
|
|
|
#include "mathl.h" |
|
14
|
|
|
|
|
|
|
#include "util.h" |
|
15
|
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
/******************************************************************************/ |
|
17
|
|
|
|
|
|
|
/* TWIN PRIMES */ |
|
18
|
|
|
|
|
|
|
/******************************************************************************/ |
|
19
|
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
/* Twin prime counts (X * 10^Y to (X+1) * 10^Y). */ |
|
21
|
|
|
|
|
|
|
#if BITS_PER_WORD < 64 |
|
22
|
|
|
|
|
|
|
static const UV twin_steps[] = |
|
23
|
|
|
|
|
|
|
{58980,48427,45485,43861,42348,41457,40908,39984,39640,39222, |
|
24
|
|
|
|
|
|
|
373059,353109,341253,332437,326131,320567,315883,312511,309244, |
|
25
|
|
|
|
|
|
|
2963535,2822103,2734294,2673728, |
|
26
|
|
|
|
|
|
|
}; |
|
27
|
|
|
|
|
|
|
static const unsigned int twin_num_exponents = 3; |
|
28
|
|
|
|
|
|
|
static const unsigned int twin_last_mult = 4; /* 4000M */ |
|
29
|
|
|
|
|
|
|
#else |
|
30
|
|
|
|
|
|
|
static const UV twin_steps[] = |
|
31
|
|
|
|
|
|
|
{58980,48427,45485,43861,42348,41457,40908,39984,39640,39222, |
|
32
|
|
|
|
|
|
|
373059,353109,341253,332437,326131,320567,315883,312511,309244, |
|
33
|
|
|
|
|
|
|
2963535,2822103,2734294,2673728,2626243,2585752,2554015,2527034,2501469, |
|
34
|
|
|
|
|
|
|
/* pi2(1e10,2e10) = 24096420; pi2(2e10,3e10) = 23046519; ... */ |
|
35
|
|
|
|
|
|
|
24096420,23046519,22401089,21946975,21590715,21300632,21060884,20854501,20665634, |
|
36
|
|
|
|
|
|
|
199708605,191801047,186932018,183404596,180694619,178477447,176604059,174989299,173597482, |
|
37
|
|
|
|
|
|
|
1682185723,1620989842,1583071291,1555660927,1534349481,1517031854,1502382532,1489745250, 1478662752, |
|
38
|
|
|
|
|
|
|
14364197903,13879821868,13578563641,13361034187,13191416949,13053013447,12936030624,12835090276, 12746487898, |
|
39
|
|
|
|
|
|
|
124078078589,120182602778,117753842540,115995331742,114622738809,113499818125,112551549250,111732637241,111012321565, |
|
40
|
|
|
|
|
|
|
1082549061370,1050759497170,1030883829367,1016473645857,1005206830409,995980796683,988183329733,981441437376,975508027029, |
|
41
|
|
|
|
|
|
|
9527651328494, 9264843314051, 9100153493509, 8980561036751, 8886953365929, 8810223086411, 8745329823109, 8689179566509, 8639748641098, |
|
42
|
|
|
|
|
|
|
84499489470819, 82302056642520, 80922166953330, 79918799449753, 79132610984280, 78487688897426, 77941865286827, 77469296499217, 77053075040105, |
|
43
|
|
|
|
|
|
|
754527610498466, 735967887462370, 724291736697048, |
|
44
|
|
|
|
|
|
|
}; |
|
45
|
|
|
|
|
|
|
static const unsigned int twin_num_exponents = 12; |
|
46
|
|
|
|
|
|
|
static const unsigned int twin_last_mult = 4; /* 4e18 */ |
|
47
|
|
|
|
|
|
|
#endif |
|
48
|
|
|
|
|
|
|
|
|
49
|
438
|
|
|
|
|
|
UV twin_prime_count(UV n) |
|
50
|
|
|
|
|
|
|
{ |
|
51
|
438
|
50
|
|
|
|
|
return (n < 3) ? 0 : twin_prime_count_range(0,n); |
|
52
|
|
|
|
|
|
|
} |
|
53
|
449
|
|
|
|
|
|
UV twin_prime_count_range(UV beg, UV end) |
|
54
|
|
|
|
|
|
|
{ |
|
55
|
|
|
|
|
|
|
unsigned char* segment; |
|
56
|
449
|
|
|
|
|
|
UV sum = 0; |
|
57
|
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
/* First use the tables of #e# from 1e7 to 4e18. */ |
|
59
|
449
|
100
|
|
|
|
|
if (beg <= 3 && end >= 10000000) { |
|
|
|
100
|
|
|
|
|
|
|
60
|
6
|
|
|
|
|
|
UV mult, exp, step = 0, base = 10000000; |
|
61
|
40
|
50
|
|
|
|
|
for (exp = 0; exp < twin_num_exponents && end >= base; exp++) { |
|
|
|
100
|
|
|
|
|
|
|
62
|
312
|
100
|
|
|
|
|
for (mult = 1; mult < 10 && end >= mult*base; mult++) { |
|
|
|
100
|
|
|
|
|
|
|
63
|
278
|
|
|
|
|
|
sum += twin_steps[step++]; |
|
64
|
278
|
|
|
|
|
|
beg = mult*base; |
|
65
|
278
|
50
|
|
|
|
|
if (exp == twin_num_exponents-1 && mult >= twin_last_mult) break; |
|
|
|
0
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
} |
|
67
|
34
|
|
|
|
|
|
base *= 10; |
|
68
|
|
|
|
|
|
|
} |
|
69
|
|
|
|
|
|
|
} |
|
70
|
449
|
100
|
|
|
|
|
if (beg <= 3 && end >= 3) sum++; |
|
|
|
50
|
|
|
|
|
|
|
71
|
449
|
100
|
|
|
|
|
if (beg <= 5 && end >= 5) sum++; |
|
|
|
50
|
|
|
|
|
|
|
72
|
449
|
100
|
|
|
|
|
if (beg < 11) beg = 7; |
|
73
|
449
|
50
|
|
|
|
|
if (beg <= end) { |
|
74
|
|
|
|
|
|
|
/* Make end points odd */ |
|
75
|
449
|
|
|
|
|
|
beg |= 1; |
|
76
|
449
|
|
|
|
|
|
end = (end-1) | 1; |
|
77
|
|
|
|
|
|
|
/* Cheesy way of counting the partial-byte edges */ |
|
78
|
5795
|
100
|
|
|
|
|
while ((beg % 30) != 1) { |
|
79
|
5346
|
100
|
|
|
|
|
if (is_prime(beg) && is_prime(beg+2) && beg <= end) sum++; |
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
80
|
5346
|
|
|
|
|
|
beg += 2; |
|
81
|
|
|
|
|
|
|
} |
|
82
|
3687
|
100
|
|
|
|
|
while ((end % 30) != 29) { |
|
83
|
3255
|
100
|
|
|
|
|
if (is_prime(end) && is_prime(end+2) && beg <= end) sum++; |
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
84
|
3255
|
100
|
|
|
|
|
end -= 2; if (beg > end) break; |
|
85
|
|
|
|
|
|
|
} |
|
86
|
|
|
|
|
|
|
} |
|
87
|
449
|
100
|
|
|
|
|
if (beg <= end) { |
|
88
|
|
|
|
|
|
|
UV seg_base, seg_low, seg_high; |
|
89
|
432
|
|
|
|
|
|
void* ctx = start_segment_primes(beg, end, &segment); |
|
90
|
864
|
100
|
|
|
|
|
while (next_segment_primes(ctx, &seg_base, &seg_low, &seg_high)) { |
|
91
|
432
|
|
|
|
|
|
UV bytes = seg_high/30 - seg_low/30 + 1; |
|
92
|
|
|
|
|
|
|
unsigned char s, x; |
|
93
|
432
|
|
|
|
|
|
const unsigned char* sp = segment; |
|
94
|
432
|
|
|
|
|
|
const unsigned char* const spend = segment + bytes - 1; |
|
95
|
54294
|
100
|
|
|
|
|
for (s = x = *sp; sp++ < spend; s = x) { |
|
96
|
53862
|
|
|
|
|
|
x = *sp; |
|
97
|
53862
|
100
|
|
|
|
|
if (!(s & 0x0C)) sum++; |
|
98
|
53862
|
100
|
|
|
|
|
if (!(s & 0x30)) sum++; |
|
99
|
53862
|
100
|
|
|
|
|
if (!(s & 0x80) && !(x & 0x01)) sum++; |
|
|
|
100
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
} |
|
101
|
432
|
100
|
|
|
|
|
x = is_prime(seg_high+2) ? 0x00 : 0xFF; |
|
102
|
432
|
100
|
|
|
|
|
if (!(s & 0x0C)) sum++; |
|
103
|
432
|
100
|
|
|
|
|
if (!(s & 0x30)) sum++; |
|
104
|
432
|
100
|
|
|
|
|
if (!(s & 0x80) && !(x & 0x01)) sum++; |
|
|
|
100
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
} |
|
106
|
432
|
|
|
|
|
|
end_segment_primes(ctx); |
|
107
|
|
|
|
|
|
|
} |
|
108
|
449
|
|
|
|
|
|
return sum; |
|
109
|
|
|
|
|
|
|
} |
|
110
|
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
/* See http://numbers.computation.free.fr/Constants/Primes/twin.pdf, page 5 */ |
|
112
|
|
|
|
|
|
|
/* Upper limit is in Wu, Acta Arith 114 (2004). 4.48857*x/(log(x)*log(x) */ |
|
113
|
|
|
|
|
|
|
/* Lichtman (2021) improved the limit: https://arxiv.org/pdf/2109.02851.pdf */ |
|
114
|
557
|
|
|
|
|
|
UV twin_prime_count_approx(UV n) |
|
115
|
|
|
|
|
|
|
{ |
|
116
|
|
|
|
|
|
|
/* Best would be another estimate for n < ~ 5000 */ |
|
117
|
557
|
100
|
|
|
|
|
if (n < 2000) return twin_prime_count(n); |
|
118
|
|
|
|
|
|
|
{ |
|
119
|
|
|
|
|
|
|
/* Sebah and Gourdon 2002 */ |
|
120
|
119
|
|
|
|
|
|
const long double two_C2 = 1.32032363169373914785562422L; |
|
121
|
119
|
|
|
|
|
|
const long double two_over_log_two = 2.8853900817779268147198494L; |
|
122
|
119
|
|
|
|
|
|
long double ln = (long double) n; |
|
123
|
119
|
|
|
|
|
|
long double logn = logl(ln); |
|
124
|
119
|
|
|
|
|
|
long double li2 = Ei(logn) + two_over_log_two-ln/logn; |
|
125
|
|
|
|
|
|
|
/* Try to minimize MSE. */ |
|
126
|
|
|
|
|
|
|
/* We compromise to prevent discontinuities. */ |
|
127
|
119
|
100
|
|
|
|
|
if (n < 32000000) { |
|
128
|
|
|
|
|
|
|
long double fm; |
|
129
|
51
|
50
|
|
|
|
|
if (n < 4000) fm = 0.2952; |
|
130
|
51
|
100
|
|
|
|
|
else if (n < 8000) fm = 0.3102; |
|
131
|
50
|
50
|
|
|
|
|
else if (n < 16000) fm = 0.3090; |
|
132
|
50
|
100
|
|
|
|
|
else if (n < 32000) fm = 0.3096; |
|
133
|
48
|
100
|
|
|
|
|
else if (n < 64000) fm = 0.3097; |
|
134
|
38
|
100
|
|
|
|
|
else if (n < 128000) fm = 0.3094; |
|
135
|
25
|
50
|
|
|
|
|
else if (n < 256000) fm = 0.3099; |
|
136
|
25
|
100
|
|
|
|
|
else if (n < 600000) fm = .3098 + (n-256000) * (.3056-.3098) / (600000-256000); |
|
137
|
14
|
100
|
|
|
|
|
else if (n < 1000000) fm = .3062 + (n-600000) * (.3042-.3062) / (1000000-600000); |
|
138
|
13
|
50
|
|
|
|
|
else if (n < 4000000) fm = .3067 + (n-1000000) * (.3041-.3067) / (4000000-1000000); |
|
139
|
13
|
50
|
|
|
|
|
else if (n <16000000) fm = .3041 + (n-4000000) * (.2983-.3041) / (16000000-4000000); |
|
140
|
0
|
|
|
|
|
|
else fm = .2983 + (n-16000000) * (.2961-.2983) / (32000000-16000000); |
|
141
|
51
|
|
|
|
|
|
li2 *= fm * logl(12+logn); |
|
142
|
|
|
|
|
|
|
} |
|
143
|
119
|
|
|
|
|
|
return (UV) (two_C2 * li2 + 0.5L); |
|
144
|
|
|
|
|
|
|
} |
|
145
|
|
|
|
|
|
|
} |
|
146
|
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
|
|
148
|
54
|
|
|
|
|
|
UV nth_twin_prime(UV n) |
|
149
|
|
|
|
|
|
|
{ |
|
150
|
|
|
|
|
|
|
unsigned char* segment; |
|
151
|
|
|
|
|
|
|
double dend; |
|
152
|
54
|
|
|
|
|
|
UV nth = 0; |
|
153
|
|
|
|
|
|
|
UV beg, end; |
|
154
|
|
|
|
|
|
|
|
|
155
|
54
|
100
|
|
|
|
|
if (n < 6) { |
|
156
|
6
|
|
|
|
|
|
switch (n) { |
|
157
|
0
|
|
|
|
|
|
case 0: nth = 0; break; |
|
158
|
1
|
|
|
|
|
|
case 1: nth = 3; break; |
|
159
|
1
|
|
|
|
|
|
case 2: nth = 5; break; |
|
160
|
1
|
|
|
|
|
|
case 3: nth =11; break; |
|
161
|
1
|
|
|
|
|
|
case 4: nth =17; break; |
|
162
|
2
|
|
|
|
|
|
case 5: |
|
163
|
2
|
|
|
|
|
|
default: nth =29; break; |
|
164
|
|
|
|
|
|
|
} |
|
165
|
6
|
|
|
|
|
|
return nth; |
|
166
|
|
|
|
|
|
|
} |
|
167
|
|
|
|
|
|
|
|
|
168
|
48
|
|
|
|
|
|
end = UV_MAX - 16; |
|
169
|
48
|
|
|
|
|
|
dend = 800.0 + 1.01L * (double)nth_twin_prime_approx(n); |
|
170
|
48
|
50
|
|
|
|
|
if (dend < (double)end) end = (UV) dend; |
|
171
|
|
|
|
|
|
|
|
|
172
|
48
|
|
|
|
|
|
beg = 2; |
|
173
|
48
|
50
|
|
|
|
|
if (n > 58980) { /* Use twin_prime_count tables to accelerate if possible */ |
|
174
|
0
|
|
|
|
|
|
UV mult, exp, step = 0, base = 10000000; |
|
175
|
0
|
0
|
|
|
|
|
for (exp = 0; exp < twin_num_exponents && end >= base; exp++) { |
|
|
|
0
|
|
|
|
|
|
|
176
|
0
|
0
|
|
|
|
|
for (mult = 1; mult < 10 && n > twin_steps[step]; mult++) { |
|
|
|
0
|
|
|
|
|
|
|
177
|
0
|
|
|
|
|
|
n -= twin_steps[step++]; |
|
178
|
0
|
|
|
|
|
|
beg = mult*base; |
|
179
|
0
|
0
|
|
|
|
|
if (exp == twin_num_exponents-1 && mult >= twin_last_mult) break; |
|
|
|
0
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
} |
|
181
|
0
|
|
|
|
|
|
base *= 10; |
|
182
|
|
|
|
|
|
|
} |
|
183
|
|
|
|
|
|
|
} |
|
184
|
48
|
50
|
|
|
|
|
if (beg == 2) { beg = 31; n -= 5; } |
|
185
|
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
{ |
|
187
|
|
|
|
|
|
|
UV seg_base, seg_low, seg_high; |
|
188
|
48
|
|
|
|
|
|
void* ctx = start_segment_primes(beg, end, &segment); |
|
189
|
144
|
100
|
|
|
|
|
while (n && next_segment_primes(ctx, &seg_base, &seg_low, &seg_high)) { |
|
|
|
50
|
|
|
|
|
|
|
190
|
48
|
|
|
|
|
|
UV p, bytes = seg_high/30 - seg_low/30 + 1; |
|
191
|
48
|
|
|
|
|
|
UV s = ((UV)segment[0]) << 8; |
|
192
|
4428
|
50
|
|
|
|
|
for (p = 0; p < bytes; p++) { |
|
193
|
4428
|
|
|
|
|
|
s >>= 8; |
|
194
|
4428
|
50
|
|
|
|
|
if (p+1 < bytes) s |= (((UV)segment[p+1]) << 8); |
|
195
|
0
|
0
|
|
|
|
|
else if (!is_prime(seg_high+2)) s |= 0xFF00; |
|
196
|
4428
|
100
|
|
|
|
|
if (!(s & 0x000C) && !--n) { nth=seg_base+p*30+11; break; } |
|
|
|
100
|
|
|
|
|
|
|
197
|
4409
|
100
|
|
|
|
|
if (!(s & 0x0030) && !--n) { nth=seg_base+p*30+17; break; } |
|
|
|
100
|
|
|
|
|
|
|
198
|
4396
|
100
|
|
|
|
|
if (!(s & 0x0180) && !--n) { nth=seg_base+p*30+29; break; } |
|
|
|
100
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
} |
|
200
|
|
|
|
|
|
|
} |
|
201
|
48
|
|
|
|
|
|
end_segment_primes(ctx); |
|
202
|
|
|
|
|
|
|
} |
|
203
|
48
|
|
|
|
|
|
return nth; |
|
204
|
|
|
|
|
|
|
} |
|
205
|
|
|
|
|
|
|
|
|
206
|
57
|
|
|
|
|
|
UV nth_twin_prime_approx(UV n) |
|
207
|
|
|
|
|
|
|
{ |
|
208
|
57
|
|
|
|
|
|
long double fn = (long double) n; |
|
209
|
57
|
|
|
|
|
|
long double flogn = logl(n); |
|
210
|
57
|
|
|
|
|
|
long double fnlog2n = fn * flogn * flogn; |
|
211
|
|
|
|
|
|
|
UV lo, hi; |
|
212
|
|
|
|
|
|
|
|
|
213
|
57
|
100
|
|
|
|
|
if (n < 6) |
|
214
|
1
|
|
|
|
|
|
return nth_twin_prime(n); |
|
215
|
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
/* Binary search on the TPC estimate. |
|
217
|
|
|
|
|
|
|
* Good results require that the TPC estimate is both fast and accurate. |
|
218
|
|
|
|
|
|
|
* These bounds are good for the actual nth_twin_prime values. |
|
219
|
|
|
|
|
|
|
*/ |
|
220
|
56
|
|
|
|
|
|
lo = (UV) (0.9 * fnlog2n); |
|
221
|
166
|
50
|
|
|
|
|
hi = (UV) ( (n >= 1e16) ? (1.04 * fnlog2n) : |
|
|
|
100
|
|
|
|
|
|
|
222
|
56
|
50
|
|
|
|
|
(n >= 1e13) ? (1.10 * fnlog2n) : |
|
223
|
56
|
100
|
|
|
|
|
(n >= 1e7 ) ? (1.31 * fnlog2n) : |
|
224
|
5
|
|
|
|
|
|
(n >= 1200) ? (1.70 * fnlog2n) : |
|
225
|
49
|
|
|
|
|
|
(2.3 * fnlog2n + 5) ); |
|
226
|
56
|
50
|
|
|
|
|
if (hi <= lo) hi = UV_MAX; |
|
227
|
56
|
|
|
|
|
|
return inverse_interpolate(lo, hi, n, &twin_prime_count_approx, 0); |
|
228
|
|
|
|
|
|
|
} |
|
229
|
|
|
|
|
|
|
|
|
230
|
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
#if 0 |
|
232
|
|
|
|
|
|
|
/* Generic cluster sieve. Works but not as fast as we'd like. */ |
|
233
|
|
|
|
|
|
|
#include "sieve_cluster.h" |
|
234
|
|
|
|
|
|
|
UV range_twin_prime_sieve(UV** list, UV beg, UV end) |
|
235
|
|
|
|
|
|
|
{ |
|
236
|
|
|
|
|
|
|
const uint32_t cl[2] = {0,2}; |
|
237
|
|
|
|
|
|
|
UV ntwin; |
|
238
|
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
*list = sieve_cluster(beg, end, 2, cl, &ntwin); |
|
240
|
|
|
|
|
|
|
return ntwin; |
|
241
|
|
|
|
|
|
|
} |
|
242
|
|
|
|
|
|
|
#endif |
|
243
|
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
#if 0 |
|
245
|
|
|
|
|
|
|
/* Prime sieve and look for twins */ |
|
246
|
|
|
|
|
|
|
UV range_twin_prime_sieve(UV** list, UV beg, UV end) |
|
247
|
|
|
|
|
|
|
{ |
|
248
|
|
|
|
|
|
|
UV nalloc, *L, ntwin; |
|
249
|
|
|
|
|
|
|
if (end > MPU_MAX_TWIN_PRIME) end = MPU_MAX_TWIN_PRIME; |
|
250
|
|
|
|
|
|
|
/* overshoot bounds, could also compare to 3*((end+29)/30 - beg/30) */ |
|
251
|
|
|
|
|
|
|
nalloc = prime_count_upper(end) - prime_count_lower(beg); |
|
252
|
|
|
|
|
|
|
New(0, L, nalloc + 1 + 3, UV); |
|
253
|
|
|
|
|
|
|
ntwin = 0; |
|
254
|
|
|
|
|
|
|
if (beg <= 3 && end >= 3) L[ntwin++] = 3; |
|
255
|
|
|
|
|
|
|
if (beg <= 5 && end >= 5) L[ntwin++] = 5; |
|
256
|
|
|
|
|
|
|
if (beg < 11) beg = 7; |
|
257
|
|
|
|
|
|
|
if (beg <= end) { |
|
258
|
|
|
|
|
|
|
unsigned char* segment; |
|
259
|
|
|
|
|
|
|
UV seg_base, seg_low, seg_high, lastp = 0; |
|
260
|
|
|
|
|
|
|
void* ctx = start_segment_primes(beg, end+2, &segment); |
|
261
|
|
|
|
|
|
|
while (next_segment_primes(ctx, &seg_base, &seg_low, &seg_high)) { |
|
262
|
|
|
|
|
|
|
START_DO_FOR_EACH_SIEVE_PRIME( segment, seg_base, seg_low, seg_high ) |
|
263
|
|
|
|
|
|
|
if (lastp+2 == p) |
|
264
|
|
|
|
|
|
|
L[ntwin++] = lastp; |
|
265
|
|
|
|
|
|
|
lastp = p; |
|
266
|
|
|
|
|
|
|
END_DO_FOR_EACH_SIEVE_PRIME |
|
267
|
|
|
|
|
|
|
} |
|
268
|
|
|
|
|
|
|
end_segment_primes(ctx); |
|
269
|
|
|
|
|
|
|
} |
|
270
|
|
|
|
|
|
|
*list = L; |
|
271
|
|
|
|
|
|
|
return ntwin; |
|
272
|
|
|
|
|
|
|
} |
|
273
|
|
|
|
|
|
|
#endif |
|
274
|
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
#if 1 |
|
276
|
|
|
|
|
|
|
/* Also just using the prime sieve and pulling out twins. */ |
|
277
|
16
|
|
|
|
|
|
UV range_twin_prime_sieve(UV** list, UV beg, UV end) |
|
278
|
|
|
|
|
|
|
{ |
|
279
|
|
|
|
|
|
|
UV nalloc, *L, ntwin; |
|
280
|
16
|
50
|
|
|
|
|
if (end > MPU_MAX_TWIN_PRIME) end = MPU_MAX_TWIN_PRIME; |
|
281
|
|
|
|
|
|
|
/* overshoot bounds, could also compare to 3*((end+29)/30 - beg/30) */ |
|
282
|
16
|
|
|
|
|
|
nalloc = prime_count_upper(end) - prime_count_lower(beg); |
|
283
|
16
|
50
|
|
|
|
|
New(0, L, nalloc + 1 + 3, UV); |
|
284
|
16
|
|
|
|
|
|
ntwin = 0; |
|
285
|
|
|
|
|
|
|
|
|
286
|
16
|
50
|
|
|
|
|
if (beg <= 3 && end >= 3) L[ntwin++] = 3; |
|
|
|
0
|
|
|
|
|
|
|
287
|
16
|
50
|
|
|
|
|
if (beg <= 5 && end >= 5) L[ntwin++] = 5; |
|
|
|
0
|
|
|
|
|
|
|
288
|
16
|
100
|
|
|
|
|
if (beg < 11) beg = 7; |
|
289
|
16
|
50
|
|
|
|
|
if (beg <= end) { |
|
290
|
|
|
|
|
|
|
/* Make end points odd */ |
|
291
|
16
|
|
|
|
|
|
beg |= 1; |
|
292
|
16
|
|
|
|
|
|
end = (end-1) | 1; |
|
293
|
42
|
|
|
|
|
|
while (1) { /* Get us to the start of a sieve byte. */ |
|
294
|
58
|
|
|
|
|
|
uint32_t beg30 = beg % 30; |
|
295
|
58
|
100
|
|
|
|
|
if (beg30 == 1) break; |
|
296
|
42
|
100
|
|
|
|
|
else if (beg30 <= 11) beg = beg-beg30+11; |
|
297
|
29
|
100
|
|
|
|
|
else if (beg30 <= 17) beg = beg-beg30+17; |
|
298
|
16
|
50
|
|
|
|
|
else if (beg30 <= 29) beg = beg-beg30+29; |
|
299
|
42
|
100
|
|
|
|
|
if (beg <= end && is_prime(beg) && is_prime(beg+2)) L[ntwin++] = beg; |
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
300
|
42
|
100
|
|
|
|
|
beg = (beg30 <= 11) ? beg+6 : (beg30 <= 17) ? beg+12 : beg+2; |
|
|
|
100
|
|
|
|
|
|
|
301
|
|
|
|
|
|
|
} |
|
302
|
|
|
|
|
|
|
} |
|
303
|
16
|
100
|
|
|
|
|
if (beg <= end) { |
|
304
|
|
|
|
|
|
|
unsigned char* segment; |
|
305
|
|
|
|
|
|
|
UV seg_base, seg_low, seg_high; |
|
306
|
5
|
|
|
|
|
|
void* ctx = start_segment_primes(beg, end, &segment); |
|
307
|
10
|
100
|
|
|
|
|
while (next_segment_primes(ctx, &seg_base, &seg_low, &seg_high)) { |
|
308
|
5
|
|
|
|
|
|
UV bytes = seg_high/30 - seg_low/30 + 1; |
|
309
|
5
|
|
|
|
|
|
UV pos = seg_base; |
|
310
|
|
|
|
|
|
|
unsigned char s, x; |
|
311
|
5
|
|
|
|
|
|
const unsigned char* sp = segment; |
|
312
|
5
|
|
|
|
|
|
const unsigned char* const spend = segment + bytes - 1; |
|
313
|
91
|
100
|
|
|
|
|
for (s = x = *sp; sp++ < spend; s = x) { |
|
314
|
86
|
|
|
|
|
|
x = *sp; |
|
315
|
86
|
100
|
|
|
|
|
if (!(s & 0x0C)) L[ntwin++] = pos+11; |
|
316
|
86
|
100
|
|
|
|
|
if (!(s & 0x30)) L[ntwin++] = pos+17; |
|
317
|
86
|
100
|
|
|
|
|
if (!(s & 0x80) && !(x & 0x01)) L[ntwin++] = pos+29; |
|
|
|
100
|
|
|
|
|
|
|
318
|
86
|
|
|
|
|
|
pos += 30; |
|
319
|
|
|
|
|
|
|
} |
|
320
|
5
|
100
|
|
|
|
|
x = is_prime(seg_high+2) ? 0x00 : 0xFF; |
|
321
|
5
|
100
|
|
|
|
|
if (!(s & 0x0C)) L[ntwin++] = pos+11; |
|
322
|
5
|
100
|
|
|
|
|
if (!(s & 0x30)) L[ntwin++] = pos+17; |
|
323
|
5
|
100
|
|
|
|
|
if (!(s & 0x80) && !(x & 0x01)) L[ntwin++] = pos+29; |
|
|
|
100
|
|
|
|
|
|
|
324
|
|
|
|
|
|
|
} |
|
325
|
5
|
|
|
|
|
|
end_segment_primes(ctx); |
|
326
|
|
|
|
|
|
|
/* Remove anything from the end because we did full bytes. */ |
|
327
|
8
|
50
|
|
|
|
|
while (ntwin > 0 && L[ntwin-1] > end) ntwin--; |
|
|
|
100
|
|
|
|
|
|
|
328
|
|
|
|
|
|
|
} |
|
329
|
16
|
|
|
|
|
|
*list = L; |
|
330
|
16
|
|
|
|
|
|
return ntwin; |
|
331
|
|
|
|
|
|
|
} |
|
332
|
|
|
|
|
|
|
#endif |