| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
#include |
|
2
|
|
|
|
|
|
|
#include |
|
3
|
|
|
|
|
|
|
#include |
|
4
|
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
#define FUNC_log2floor 1 |
|
6
|
|
|
|
|
|
|
#define FUNC_is_prime_in_sieve 1 |
|
7
|
|
|
|
|
|
|
#include "ptypes.h" |
|
8
|
|
|
|
|
|
|
#include "sieve.h" |
|
9
|
|
|
|
|
|
|
#include "util.h" |
|
10
|
|
|
|
|
|
|
#include "prime_counts.h" |
|
11
|
|
|
|
|
|
|
#include "inverse_interpolate.h" |
|
12
|
|
|
|
|
|
|
#include "ramanujan_primes.h" |
|
13
|
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
/******************************************************************************/ |
|
15
|
|
|
|
|
|
|
/* RAMANUJAN PRIMES */ |
|
16
|
|
|
|
|
|
|
/******************************************************************************/ |
|
17
|
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
static const uint8_t small_ram_primes[] = { |
|
19
|
|
|
|
|
|
|
2,11,17,29,41,47,59,67,71,97,101,107,127,149,151,167,179,181,227,229,233,239,241 |
|
20
|
|
|
|
|
|
|
}; |
|
21
|
|
|
|
|
|
|
#define NSMALL_RAM (sizeof(small_ram_primes)/sizeof(small_ram_primes[0])) |
|
22
|
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
#define FAST_SMALL_NTH(n) \ |
|
24
|
|
|
|
|
|
|
if (n <= NSMALL_RAM) \ |
|
25
|
|
|
|
|
|
|
{ return (n == 0) ? 0 : small_ram_primes[n-1]; } |
|
26
|
|
|
|
|
|
|
#define FAST_SMALL_COUNT(n) \ |
|
27
|
|
|
|
|
|
|
if (n <= small_ram_primes[NSMALL_RAM-1]) { \ |
|
28
|
|
|
|
|
|
|
UV i; \ |
|
29
|
|
|
|
|
|
|
for (i = 0; i < NSMALL_RAM; i++) \ |
|
30
|
|
|
|
|
|
|
if (n < small_ram_primes[i]) break; \ |
|
31
|
|
|
|
|
|
|
return i; \ |
|
32
|
|
|
|
|
|
|
} |
|
33
|
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
/******************************* Bounds *******************************/ |
|
36
|
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
/* Upper and lower bounds done using Axler 2017: |
|
38
|
|
|
|
|
|
|
* https://arxiv.org/pdf/1711.04588.pdf |
|
39
|
|
|
|
|
|
|
* The parameter values have been computed using exact nth_prime, |
|
40
|
|
|
|
|
|
|
* so does not depend on the nth_prime_upper / nth_prime_lower method. |
|
41
|
|
|
|
|
|
|
*/ |
|
42
|
|
|
|
|
|
|
|
|
43
|
418
|
|
|
|
|
|
UV nth_ramanujan_prime_upper(UV n) { |
|
44
|
418
|
|
|
|
|
|
long double R = 0, D = 0.565; |
|
45
|
|
|
|
|
|
|
|
|
46
|
418
|
100
|
|
|
|
|
FAST_SMALL_NTH(n); |
|
|
|
50
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
|
|
48
|
381
|
100
|
|
|
|
|
if (n < 12581) { |
|
49
|
359
|
100
|
|
|
|
|
if (n < 168) R = ramanujan_axler(n, -4.7691, -6.2682); |
|
50
|
10
|
100
|
|
|
|
|
else if (n < 2290) R = ramanujan_axler(n, -0.9315, -0.5635); |
|
51
|
2
|
100
|
|
|
|
|
else if (n < 5225) R = ramanujan_axler(n, -0.5318, -0.0710); |
|
52
|
1
|
50
|
|
|
|
|
else if (n < 12581) R = ramanujan_axler(n, 0.1212, 0.7973); |
|
53
|
359
|
|
|
|
|
|
return nth_prime_upper(R); |
|
54
|
|
|
|
|
|
|
} |
|
55
|
22
|
50
|
|
|
|
|
if (n < 18175) D = 0.3548; |
|
56
|
22
|
100
|
|
|
|
|
else if (n < 82883) D = -0.2450; |
|
57
|
12
|
100
|
|
|
|
|
else if (n < 316314) D = -0.6384; |
|
58
|
10
|
50
|
|
|
|
|
else if (n < 1000001) D = -0.9353; |
|
59
|
10
|
100
|
|
|
|
|
else if (n < 4000001) D = -1.1271; |
|
60
|
8
|
50
|
|
|
|
|
else if (n < 16000001) D = -1.4152; |
|
61
|
0
|
0
|
|
|
|
|
else if (n < 64000001) D = -1.6671; |
|
62
|
0
|
0
|
|
|
|
|
else if (n < 128000001) D = -1.8855; |
|
63
|
0
|
0
|
|
|
|
|
else if (n < 256000001) D = -1.9325; |
|
64
|
0
|
0
|
|
|
|
|
else if (n < 384000001) D = -2.0190; |
|
65
|
0
|
0
|
|
|
|
|
else if (n < 512000001) D = -2.0310; |
|
66
|
|
|
|
|
|
|
else { |
|
67
|
0
|
|
|
|
|
|
D = -2.0884; |
|
68
|
0
|
0
|
|
|
|
|
if (n > UVCONST( 3999654659)) D = -2.235; |
|
69
|
|
|
|
|
|
|
#if BITS_PER_WORD == 64 |
|
70
|
0
|
0
|
|
|
|
|
if (n > UVCONST( 84086679236)) D = -2.435; |
|
71
|
0
|
0
|
|
|
|
|
if (n > UVCONST( 514808375201)) D = -2.535; |
|
72
|
0
|
0
|
|
|
|
|
if (n > UVCONST( 3594243587299)) D = -2.635; |
|
73
|
0
|
0
|
|
|
|
|
if (n > UVCONST( 28330126673435)) D = -2.735; |
|
74
|
0
|
0
|
|
|
|
|
if (n > UVCONST(117462814829787)) D = -2.8; |
|
75
|
|
|
|
|
|
|
#endif |
|
76
|
|
|
|
|
|
|
} |
|
77
|
|
|
|
|
|
|
|
|
78
|
22
|
|
|
|
|
|
return nth_prime_upper(ramanujan_axler(n, 0.0, D)); |
|
79
|
|
|
|
|
|
|
} |
|
80
|
|
|
|
|
|
|
|
|
81
|
462
|
|
|
|
|
|
UV nth_ramanujan_prime_lower(UV n) { |
|
82
|
462
|
|
|
|
|
|
double R = 0, D = 0; |
|
83
|
|
|
|
|
|
|
|
|
84
|
462
|
100
|
|
|
|
|
FAST_SMALL_NTH(n); |
|
|
|
50
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
|
|
86
|
407
|
100
|
|
|
|
|
if (n < 34816) { |
|
87
|
388
|
100
|
|
|
|
|
if (n < 189) R = ramanujan_axler(n, 4.2720, 0.340); |
|
88
|
13
|
100
|
|
|
|
|
else if (n < 1245) R = ramanujan_axler(n, -0.2179, -6.179); |
|
89
|
5
|
100
|
|
|
|
|
else if (n < 2984) R = ramanujan_axler(n, 0.1446, -4.8693); |
|
90
|
4
|
100
|
|
|
|
|
else if (n < 14303) R = ramanujan_axler(n, -0.3570, -5.1154); |
|
91
|
3
|
50
|
|
|
|
|
else if (n < 34816) R = ramanujan_axler(n, -1.5770, -7.5332); |
|
92
|
388
|
|
|
|
|
|
return nth_prime_lower(R); |
|
93
|
|
|
|
|
|
|
} |
|
94
|
|
|
|
|
|
|
|
|
95
|
19
|
100
|
|
|
|
|
if (n < 76400) D = 0.0126; |
|
96
|
12
|
100
|
|
|
|
|
else if (n < 280816) D = 0.5132; |
|
97
|
10
|
50
|
|
|
|
|
else if (n < 915887) D = 0.9967; |
|
98
|
10
|
100
|
|
|
|
|
else if (n < 4000001) D = 1.5004; |
|
99
|
8
|
50
|
|
|
|
|
else if (n < 16000001) D = 1.7184; |
|
100
|
0
|
0
|
|
|
|
|
else if (n < 64000001) D = 1.9860; |
|
101
|
0
|
0
|
|
|
|
|
else if (n < 128000001) D = 2.1352; |
|
102
|
0
|
0
|
|
|
|
|
else if (n < 256000001) D = 2.1658; |
|
103
|
0
|
0
|
|
|
|
|
else if (n < 384000001) D = 2.1999; |
|
104
|
0
|
0
|
|
|
|
|
else if (n < 512000001) D = 2.2047; |
|
105
|
0
|
0
|
|
|
|
|
else if (n < 640000001) D = 2.2324; |
|
106
|
|
|
|
|
|
|
else { |
|
107
|
0
|
|
|
|
|
|
D = 2.2385; |
|
108
|
|
|
|
|
|
|
#if BITS_PER_WORD == 64 |
|
109
|
0
|
0
|
|
|
|
|
if (n > UVCONST( 14888378285)) D = 2.29; |
|
110
|
0
|
0
|
|
|
|
|
if (n > UVCONST( 467037926604)) D = 2.31; |
|
111
|
0
|
0
|
|
|
|
|
if (n > UVCONST( 2778491401197)) D = 2.315; |
|
112
|
0
|
0
|
|
|
|
|
if (n > UVCONST( 10656144781918)) D = 2.317; |
|
113
|
0
|
0
|
|
|
|
|
if (n > UVCONST( 63698770351741)) D = 2.319; |
|
114
|
|
|
|
|
|
|
#endif |
|
115
|
|
|
|
|
|
|
} |
|
116
|
|
|
|
|
|
|
|
|
117
|
19
|
|
|
|
|
|
return nth_prime_lower(ramanujan_axler(n, 1.472, D)); |
|
118
|
|
|
|
|
|
|
} |
|
119
|
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
/* For Ramanujan prime count bounds, use binary searches on the inverses. */ |
|
121
|
|
|
|
|
|
|
|
|
122
|
89
|
|
|
|
|
|
UV ramanujan_prime_count_lower(UV n) { |
|
123
|
|
|
|
|
|
|
UV lo, hi; |
|
124
|
401
|
100
|
|
|
|
|
FAST_SMALL_COUNT(n); |
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
/* We know we're between p_2n and p_3n, probably close to the former. */ |
|
126
|
53
|
|
|
|
|
|
lo = prime_count_lower(n)/3; |
|
127
|
53
|
|
|
|
|
|
hi = prime_count_upper(n) >> 1; |
|
128
|
53
|
|
|
|
|
|
return inverse_interpolate(lo, hi, n, &nth_ramanujan_prime_upper, 0); |
|
129
|
|
|
|
|
|
|
} |
|
130
|
89
|
|
|
|
|
|
UV ramanujan_prime_count_upper(UV n) { |
|
131
|
|
|
|
|
|
|
UV lo, hi; |
|
132
|
411
|
100
|
|
|
|
|
FAST_SMALL_COUNT(n); |
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
/* We know we're between p_2n and p_3n, probably close to the former. */ |
|
134
|
54
|
|
|
|
|
|
lo = prime_count_lower(n)/3; |
|
135
|
54
|
|
|
|
|
|
hi = prime_count_upper(n) >> 1; |
|
136
|
54
|
|
|
|
|
|
return inverse_interpolate(lo, hi, n, &nth_ramanujan_prime_lower, 0); |
|
137
|
|
|
|
|
|
|
} |
|
138
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
/**************************** Approximate ****************************/ |
|
140
|
|
|
|
|
|
|
|
|
141
|
24
|
|
|
|
|
|
UV ramanujan_prime_count_approx(UV n) |
|
142
|
|
|
|
|
|
|
{ |
|
143
|
24
|
50
|
|
|
|
|
FAST_SMALL_COUNT(n); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
/* Extremely accurate but a bit slow */ |
|
145
|
24
|
|
|
|
|
|
return prime_count_approx(n) - prime_count_approx(n >> 1); |
|
146
|
|
|
|
|
|
|
} |
|
147
|
|
|
|
|
|
|
|
|
148
|
2
|
|
|
|
|
|
UV nth_ramanujan_prime_approx(UV n) |
|
149
|
|
|
|
|
|
|
{ |
|
150
|
|
|
|
|
|
|
UV lo, hi; |
|
151
|
2
|
50
|
|
|
|
|
FAST_SMALL_NTH(n); |
|
|
|
0
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
/* Interpolating using ramanujan prime count approximation */ |
|
153
|
2
|
|
|
|
|
|
lo = nth_ramanujan_prime_lower(n) - 1; |
|
154
|
2
|
|
|
|
|
|
hi = nth_ramanujan_prime_upper(n); |
|
155
|
2
|
|
|
|
|
|
return inverse_interpolate(lo, hi, n, &ramanujan_prime_count_approx, 0); |
|
156
|
|
|
|
|
|
|
} |
|
157
|
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
/******************************* Arrays *******************************/ |
|
159
|
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
/* Return array of first n ramanujan primes. Use Noe's algorithm. */ |
|
161
|
29
|
|
|
|
|
|
UV* n_ramanujan_primes(UV n) { |
|
162
|
|
|
|
|
|
|
UV max, k, s, *L; |
|
163
|
|
|
|
|
|
|
unsigned char* sieve; |
|
164
|
|
|
|
|
|
|
|
|
165
|
29
|
100
|
|
|
|
|
if (n <= NSMALL_RAM) { |
|
166
|
6
|
50
|
|
|
|
|
New(0, L, n, UV); |
|
167
|
39
|
100
|
|
|
|
|
for (k = 0; k < n; k++) |
|
168
|
33
|
|
|
|
|
|
L[k] = small_ram_primes[k]; |
|
169
|
6
|
|
|
|
|
|
return L; |
|
170
|
|
|
|
|
|
|
} |
|
171
|
|
|
|
|
|
|
|
|
172
|
23
|
|
|
|
|
|
max = nth_ramanujan_prime_upper(n); /* Rn <= max, so we can sieve to there */ |
|
173
|
23
|
50
|
|
|
|
|
MPUverbose(2, "sieving to %"UVuf" for first %"UVuf" Ramanujan primes\n", max, n); |
|
174
|
23
|
50
|
|
|
|
|
Newz(0, L, n, UV); |
|
175
|
23
|
|
|
|
|
|
L[0] = 2; |
|
176
|
23
|
|
|
|
|
|
sieve = sieve_erat30(max); |
|
177
|
5030
|
100
|
|
|
|
|
for (s = 0, k = 7; k <= max; k += 2) { |
|
178
|
5007
|
100
|
|
|
|
|
if (is_prime_in_sieve(sieve, k)) s++; |
|
179
|
5007
|
100
|
|
|
|
|
if (s < n) L[s] = k+1; |
|
180
|
5007
|
100
|
|
|
|
|
if ((k & 3) == 1 && is_prime_in_sieve(sieve, (k+1)>>1)) s--; |
|
|
|
100
|
|
|
|
|
|
|
181
|
5007
|
100
|
|
|
|
|
if (s < n) L[s] = k+2; |
|
182
|
|
|
|
|
|
|
} |
|
183
|
23
|
|
|
|
|
|
Safefree(sieve); |
|
184
|
23
|
|
|
|
|
|
return L; |
|
185
|
|
|
|
|
|
|
} |
|
186
|
|
|
|
|
|
|
|
|
187
|
155
|
|
|
|
|
|
UV* n_range_ramanujan_primes(UV nlo, UV nhi) { |
|
188
|
|
|
|
|
|
|
UV mink, maxk, k, s, *L; |
|
189
|
|
|
|
|
|
|
|
|
190
|
155
|
50
|
|
|
|
|
if (nlo == 0) nlo = 1; |
|
191
|
155
|
50
|
|
|
|
|
if (nhi == 0) nhi = 1; |
|
192
|
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
/* If we're starting from 1, just do single monolithic sieve */ |
|
194
|
155
|
100
|
|
|
|
|
if (nlo == 1) return n_ramanujan_primes(nhi); |
|
195
|
|
|
|
|
|
|
|
|
196
|
126
|
50
|
|
|
|
|
Newz(0, L, nhi-nlo+1, UV); |
|
197
|
126
|
50
|
|
|
|
|
if (nlo <= 1 && nhi >= 1) L[1-nlo] = 2; |
|
|
|
0
|
|
|
|
|
|
|
198
|
126
|
100
|
|
|
|
|
if (nlo <= 2 && nhi >= 2) L[2-nlo] = 11; |
|
|
|
50
|
|
|
|
|
|
|
199
|
126
|
100
|
|
|
|
|
if (nhi < 3) return L; |
|
200
|
|
|
|
|
|
|
|
|
201
|
125
|
|
|
|
|
|
mink = nth_ramanujan_prime_lower(nlo) - 1; |
|
202
|
125
|
|
|
|
|
|
maxk = nth_ramanujan_prime_upper(nhi) + 1; |
|
203
|
|
|
|
|
|
|
|
|
204
|
125
|
100
|
|
|
|
|
if (mink < 15) mink = 15; |
|
205
|
125
|
100
|
|
|
|
|
if (mink % 2 == 0) mink--; |
|
206
|
125
|
50
|
|
|
|
|
MPUverbose(2, "Rn[%"UVuf"] to Rn[%"UVuf"] Noe's: %"UVuf" to %"UVuf"\n", nlo, nhi, mink, maxk); |
|
207
|
|
|
|
|
|
|
|
|
208
|
125
|
|
|
|
|
|
s = 1 + prime_count(mink-2) - prime_count((mink-1)>>1); |
|
209
|
|
|
|
|
|
|
{ |
|
210
|
125
|
|
|
|
|
|
unsigned char *segment, *seg2 = 0; |
|
211
|
125
|
|
|
|
|
|
void* ctx = start_segment_primes(mink, maxk, &segment); |
|
212
|
125
|
|
|
|
|
|
UV seg_base, seg_low, seg_high, new_size, seg2beg, seg2end, seg2size = 0; |
|
213
|
250
|
100
|
|
|
|
|
while (next_segment_primes(ctx, &seg_base, &seg_low, &seg_high)) { |
|
214
|
125
|
|
|
|
|
|
seg2beg = 30 * (((seg_low+1)>>1)/30); |
|
215
|
125
|
|
|
|
|
|
seg2end = 30 * ((((seg_high+1)>>1)+29)/30); |
|
216
|
125
|
|
|
|
|
|
new_size = (seg2end - seg2beg)/30 + 1; |
|
217
|
125
|
50
|
|
|
|
|
if (new_size > seg2size) { |
|
218
|
125
|
50
|
|
|
|
|
if (seg2size > 0) Safefree(seg2); |
|
219
|
125
|
|
|
|
|
|
New(0, seg2, new_size, unsigned char); |
|
220
|
125
|
|
|
|
|
|
seg2size = new_size; |
|
221
|
|
|
|
|
|
|
} |
|
222
|
125
|
|
|
|
|
|
(void) sieve_segment(seg2, seg2beg/30, seg2end/30); |
|
223
|
87718
|
100
|
|
|
|
|
for (k = seg_low; k <= seg_high; k += 2) { |
|
224
|
87593
|
100
|
|
|
|
|
if (is_prime_in_sieve(segment, k-seg_base)) s++; |
|
225
|
87593
|
100
|
|
|
|
|
if (s >= nlo && s <= nhi) L[s-nlo] = k+1; |
|
|
|
100
|
|
|
|
|
|
|
226
|
87593
|
100
|
|
|
|
|
if ((k & 3) == 1 && is_prime_in_sieve(seg2, ((k+1)>>1)-seg2beg)) s--; |
|
|
|
100
|
|
|
|
|
|
|
227
|
87593
|
100
|
|
|
|
|
if (s >= nlo && s <= nhi) L[s-nlo] = k+2; |
|
|
|
100
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
} |
|
229
|
|
|
|
|
|
|
} |
|
230
|
125
|
|
|
|
|
|
end_segment_primes(ctx); |
|
231
|
125
|
|
|
|
|
|
Safefree(seg2); |
|
232
|
|
|
|
|
|
|
} |
|
233
|
125
|
50
|
|
|
|
|
MPUverbose(2, "Generated %"UVuf" Ramanujan primes from %"UVuf" to %"UVuf"\n", nhi-nlo+1, L[0], L[nhi-nlo]); |
|
234
|
125
|
|
|
|
|
|
return L; |
|
235
|
|
|
|
|
|
|
} |
|
236
|
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
/* Returns array of Ram primes between low and high, results from first->last */ |
|
238
|
15
|
|
|
|
|
|
UV* ramanujan_primes(UV* first, UV* last, UV low, UV high) |
|
239
|
|
|
|
|
|
|
{ |
|
240
|
|
|
|
|
|
|
UV nlo, nhi, *L, lo, hi, mid; |
|
241
|
|
|
|
|
|
|
|
|
242
|
15
|
50
|
|
|
|
|
if (high < 2 || high < low) return 0; |
|
|
|
50
|
|
|
|
|
|
|
243
|
15
|
50
|
|
|
|
|
if (low < 2) low = 2; |
|
244
|
|
|
|
|
|
|
|
|
245
|
15
|
|
|
|
|
|
nlo = ramanujan_prime_count_lower(low); |
|
246
|
15
|
|
|
|
|
|
nhi = ramanujan_prime_count_upper(high); |
|
247
|
15
|
|
|
|
|
|
L = n_range_ramanujan_primes(nlo, nhi); |
|
248
|
|
|
|
|
|
|
|
|
249
|
|
|
|
|
|
|
/* Search for first entry in range */ |
|
250
|
50
|
100
|
|
|
|
|
for (lo = 0, hi = nhi-nlo+1; lo < hi; ) { |
|
251
|
35
|
|
|
|
|
|
mid = lo + (hi-lo)/2; |
|
252
|
35
|
100
|
|
|
|
|
if (L[mid] < low) lo = mid+1; |
|
253
|
25
|
|
|
|
|
|
else hi = mid; |
|
254
|
|
|
|
|
|
|
} |
|
255
|
15
|
|
|
|
|
|
*first = lo; |
|
256
|
|
|
|
|
|
|
/* Search for last entry in range */ |
|
257
|
38
|
100
|
|
|
|
|
for (hi = nhi-nlo+1; lo < hi; ) { |
|
258
|
23
|
|
|
|
|
|
mid = lo + (hi-lo)/2; |
|
259
|
23
|
100
|
|
|
|
|
if (L[mid] <= high) lo = mid+1; |
|
260
|
4
|
|
|
|
|
|
else hi = mid; |
|
261
|
|
|
|
|
|
|
} |
|
262
|
15
|
|
|
|
|
|
*last = lo-1; |
|
263
|
15
|
|
|
|
|
|
return L; |
|
264
|
|
|
|
|
|
|
} |
|
265
|
|
|
|
|
|
|
|
|
266
|
15
|
|
|
|
|
|
UV range_ramanujan_prime_sieve(UV** list, UV lo, UV hi) |
|
267
|
|
|
|
|
|
|
{ |
|
268
|
|
|
|
|
|
|
UV first, last, *L; |
|
269
|
15
|
|
|
|
|
|
L = ramanujan_primes(&first, &last, lo, hi); |
|
270
|
15
|
50
|
|
|
|
|
if (L == 0 || first > last) { *list = 0; return 0; } |
|
|
|
100
|
|
|
|
|
|
|
271
|
14
|
100
|
|
|
|
|
if (first > 0) |
|
272
|
8
|
|
|
|
|
|
memmove( L + 0, L + first, (last-first+1) * sizeof(UV) ); |
|
273
|
14
|
|
|
|
|
|
*list = L; |
|
274
|
14
|
|
|
|
|
|
return last-first+1; |
|
275
|
|
|
|
|
|
|
} |
|
276
|
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
/* Generate a small window of Rp's around n */ |
|
278
|
88
|
|
|
|
|
|
static UV* _ramanujan_prime_window(UV n, UV* winsize, UV* npos) { |
|
279
|
88
|
|
|
|
|
|
UV i, v, *L, window, swin, ewin, wlen, winmult = 1; |
|
280
|
|
|
|
|
|
|
|
|
281
|
88
|
50
|
|
|
|
|
MPUverbose(1, "ramanujan_prime_count calculating Pi(%"UVuf")\n",n); |
|
282
|
88
|
|
|
|
|
|
v = prime_count(n) - prime_count(n >> 1); |
|
283
|
|
|
|
|
|
|
|
|
284
|
|
|
|
|
|
|
/* For large enough n make a slightly bigger window */ |
|
285
|
88
|
50
|
|
|
|
|
if (n > 1000000000U) winmult = 16; |
|
286
|
|
|
|
|
|
|
|
|
287
|
|
|
|
|
|
|
while (1) { |
|
288
|
88
|
|
|
|
|
|
window = 20 * winmult; |
|
289
|
88
|
100
|
|
|
|
|
swin = (v <= window) ? 1 : v-window; |
|
290
|
88
|
|
|
|
|
|
ewin = v+window; |
|
291
|
88
|
|
|
|
|
|
wlen = ewin-swin+1; |
|
292
|
88
|
|
|
|
|
|
L = n_range_ramanujan_primes(swin, ewin); |
|
293
|
88
|
50
|
|
|
|
|
if (L[0] < n && L[wlen-1] > n) { |
|
|
|
50
|
|
|
|
|
|
|
294
|
|
|
|
|
|
|
/* Naive linear search from the start. */ |
|
295
|
1645
|
50
|
|
|
|
|
for (i = 1; i < wlen; i++) |
|
296
|
1645
|
100
|
|
|
|
|
if (L[i] > n && L[i-1] <= n) |
|
|
|
50
|
|
|
|
|
|
|
297
|
88
|
|
|
|
|
|
break; |
|
298
|
88
|
50
|
|
|
|
|
if (i < wlen) break; |
|
299
|
|
|
|
|
|
|
} |
|
300
|
0
|
|
|
|
|
|
winmult *= 2; |
|
301
|
0
|
0
|
|
|
|
|
MPUverbose(1, " %s increasing window\n", "ramanujan_prime_count"); |
|
302
|
|
|
|
|
|
|
} |
|
303
|
88
|
|
|
|
|
|
*winsize = swin; |
|
304
|
88
|
|
|
|
|
|
*npos = i-1; |
|
305
|
88
|
|
|
|
|
|
return L; |
|
306
|
|
|
|
|
|
|
} |
|
307
|
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
/******************************* Exact *******************************/ |
|
309
|
|
|
|
|
|
|
|
|
310
|
75
|
|
|
|
|
|
UV nth_ramanujan_prime(UV n) { |
|
311
|
|
|
|
|
|
|
UV rn, *L; |
|
312
|
75
|
100
|
|
|
|
|
FAST_SMALL_NTH(n); |
|
|
|
50
|
|
|
|
|
|
|
313
|
52
|
|
|
|
|
|
L = n_range_ramanujan_primes(n, n); |
|
314
|
52
|
|
|
|
|
|
rn = L[0]; |
|
315
|
52
|
|
|
|
|
|
Safefree(L); |
|
316
|
52
|
|
|
|
|
|
return rn; |
|
317
|
|
|
|
|
|
|
} |
|
318
|
|
|
|
|
|
|
|
|
319
|
984
|
|
|
|
|
|
bool is_ramanujan_prime(UV n) { |
|
320
|
|
|
|
|
|
|
UV i, d, *L, swin, rn; |
|
321
|
|
|
|
|
|
|
bool res; |
|
322
|
|
|
|
|
|
|
|
|
323
|
984
|
100
|
|
|
|
|
if (!is_prime(n)) return 0; |
|
324
|
166
|
100
|
|
|
|
|
if (n < 17) return (n == 2 || n == 11); |
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
325
|
|
|
|
|
|
|
|
|
326
|
|
|
|
|
|
|
/* Pre-test: Check if Pi(n/2) increases before Pi(n) does. */ |
|
327
|
160
|
100
|
|
|
|
|
if (is_prime(n/2+1)) return 0; |
|
328
|
143
|
|
|
|
|
|
d = (next_prime(n) - n)/2; |
|
329
|
280
|
100
|
|
|
|
|
for (i = 2; i <= d; i++) |
|
330
|
201
|
100
|
|
|
|
|
if (is_prime(n/2+i)) return 0; |
|
331
|
|
|
|
|
|
|
|
|
332
|
|
|
|
|
|
|
/* Very straightforward, but not the fastest method: |
|
333
|
|
|
|
|
|
|
* return nth_ramanujan_prime(ramanujan_prime_count(n)) == n; |
|
334
|
|
|
|
|
|
|
* |
|
335
|
|
|
|
|
|
|
* Slower than below for most input sizes: |
|
336
|
|
|
|
|
|
|
* L = ramanujan_primes(&beg, &end, n, n); |
|
337
|
|
|
|
|
|
|
* Safefree(L); |
|
338
|
|
|
|
|
|
|
* return (beg <= end); |
|
339
|
|
|
|
|
|
|
*/ |
|
340
|
|
|
|
|
|
|
|
|
341
|
79
|
|
|
|
|
|
L = _ramanujan_prime_window(n, &swin, &rn); |
|
342
|
79
|
|
|
|
|
|
res = (L[rn] == n); |
|
343
|
79
|
|
|
|
|
|
Safefree(L); |
|
344
|
79
|
|
|
|
|
|
return res; |
|
345
|
|
|
|
|
|
|
} |
|
346
|
|
|
|
|
|
|
|
|
347
|
|
|
|
|
|
|
#if BITS_PER_WORD == 64 |
|
348
|
|
|
|
|
|
|
#define RAMPC2 56 |
|
349
|
|
|
|
|
|
|
static const UV ramanujan_counts_pow2[RAMPC2+1] = { |
|
350
|
|
|
|
|
|
|
0, 1, 1, 1, 2, 4, 7, 13, 23, 42, 75, 137, 255, 463, 872, 1612, |
|
351
|
|
|
|
|
|
|
3030, 5706, 10749, 20387, 38635, 73584, 140336, 268216, 513705, |
|
352
|
|
|
|
|
|
|
985818, 1894120, 3645744, 7027290, 13561906, 26207278, 50697533, |
|
353
|
|
|
|
|
|
|
98182656, 190335585, 369323301, 717267167, |
|
354
|
|
|
|
|
|
|
UVCONST( 1394192236), UVCONST( 2712103833), UVCONST( 5279763823), |
|
355
|
|
|
|
|
|
|
UVCONST( 10285641777), UVCONST( 20051180846), UVCONST( 39113482639), |
|
356
|
|
|
|
|
|
|
UVCONST( 76344462797), UVCONST( 149100679004), UVCONST( 291354668495), |
|
357
|
|
|
|
|
|
|
UVCONST( 569630404447), UVCONST( 1114251967767), UVCONST( 2180634225768), |
|
358
|
|
|
|
|
|
|
UVCONST( 4269555883751), UVCONST( 8363243713305), UVCONST( 16388947026629), |
|
359
|
|
|
|
|
|
|
UVCONST( 32129520311897), UVCONST( 63012603695171), UVCONST(123627200537929), |
|
360
|
|
|
|
|
|
|
UVCONST(242637500756376), UVCONST(476379740340417), UVCONST(935609435783647) }; |
|
361
|
|
|
|
|
|
|
#else |
|
362
|
|
|
|
|
|
|
#define RAMPC2 31 /* input limited */ |
|
363
|
|
|
|
|
|
|
static const UV ramanujan_counts_pow2[RAMPC2+1] = { |
|
364
|
|
|
|
|
|
|
0, 1, 1, 1, 2, 4, 7, 13, 23, 42, 75, 137, 255, 463, 872, 1612, |
|
365
|
|
|
|
|
|
|
3030, 5706, 10749, 20387, 38635, 73584, 140336, 268216, 513705, |
|
366
|
|
|
|
|
|
|
985818, 1894120, 3645744, 7027290, 13561906, 26207278, 50697533 }; |
|
367
|
|
|
|
|
|
|
#endif |
|
368
|
|
|
|
|
|
|
|
|
369
|
12
|
|
|
|
|
|
UV ramanujan_prime_count(UV n) { |
|
370
|
12
|
50
|
|
|
|
|
UV swin, rn, *L, log2 = log2floor(n); |
|
371
|
|
|
|
|
|
|
|
|
372
|
12
|
100
|
|
|
|
|
if ((n & (n-1)) == 0 && log2 <= RAMPC2) /* Powers of two from table */ |
|
|
|
50
|
|
|
|
|
|
|
373
|
1
|
|
|
|
|
|
return ramanujan_counts_pow2[log2]; |
|
374
|
17
|
100
|
|
|
|
|
FAST_SMALL_COUNT(n); |
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
375
|
|
|
|
|
|
|
|
|
376
|
9
|
|
|
|
|
|
L = _ramanujan_prime_window(n, &swin, &rn); |
|
377
|
9
|
|
|
|
|
|
Safefree(L); |
|
378
|
9
|
|
|
|
|
|
return swin+rn; |
|
379
|
|
|
|
|
|
|
} |
|
380
|
|
|
|
|
|
|
|
|
381
|
10
|
|
|
|
|
|
UV ramanujan_prime_count_range(UV lo, UV hi) |
|
382
|
|
|
|
|
|
|
{ |
|
383
|
10
|
50
|
|
|
|
|
if (hi < 2 || hi < lo) return 0; |
|
|
|
50
|
|
|
|
|
|
|
384
|
10
|
100
|
|
|
|
|
return ramanujan_prime_count(hi) - ((lo <= 2) ? 0 : ramanujan_prime_count(lo-1)); |
|
385
|
|
|
|
|
|
|
} |