File Coverage

twin_primes.c
Criterion Covered Total %
statement 145 155 93.5
branch 165 214 77.1
condition n/a
subroutine n/a
pod n/a
total 310 369 84.0


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