line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
#include |
2
|
|
|
|
|
|
|
#include |
3
|
|
|
|
|
|
|
#include |
4
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
#include "ptypes.h" |
6
|
|
|
|
|
|
|
#define FUNC_log2floor 1 |
7
|
|
|
|
|
|
|
#include "util.h" |
8
|
|
|
|
|
|
|
#define FUNC_is_prime_in_sieve 1 |
9
|
|
|
|
|
|
|
#include "prime_nth_count.h" |
10
|
|
|
|
|
|
|
#include "sieve.h" |
11
|
|
|
|
|
|
|
#include "ramanujan_primes.h" |
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
/******************************************************************************/ |
14
|
|
|
|
|
|
|
/* RAMANUJAN PRIMES */ |
15
|
|
|
|
|
|
|
/******************************************************************************/ |
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
/* For Ramanujan prime estimates: |
18
|
|
|
|
|
|
|
* - counts are done via inverse nth, so only one thing to tune. |
19
|
|
|
|
|
|
|
* - For nth tables, upper values ok if too high, lower values ok if too low. |
20
|
|
|
|
|
|
|
* - both upper & lower empirically tested to 175e9 (175 thousand million), |
21
|
|
|
|
|
|
|
* with a return value of over 10^13. |
22
|
|
|
|
|
|
|
*/ |
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
/* These are playing loose with Sondow/Nicholson/Noe 2011 theorem 4. |
25
|
|
|
|
|
|
|
* The last value should be rigorously checked using actual R_n values. */ |
26
|
|
|
|
|
|
|
static const uint32_t small_ram_upper_idx[] = { |
27
|
|
|
|
|
|
|
3970,3980,5218,5221,5224,5226,5262,5270,5272,5278,5281,5553,5556,7432, |
28
|
|
|
|
|
|
|
7449,7453,8580,8584,8607,12589,12603,12620,12729,18119,18134,18174,18289, |
29
|
|
|
|
|
|
|
18300,18401,18419,25799,27247,27267,28663,39635,40061,40366,45338,51320, |
30
|
|
|
|
|
|
|
64439,65566,65829,84761,89055,104959,107852,146968,151755,186499,217258, |
31
|
|
|
|
|
|
|
223956,270700,332195,347223,440804,508096,565039,768276,828377,1090285, |
32
|
|
|
|
|
|
|
1277320,1568165,1896508,2375799,3300765,4162908,5124977,6522443,9298256, |
33
|
|
|
|
|
|
|
11406250, 15873245, 21307556, 29899174, 40666215, |
34
|
|
|
|
|
|
|
57180770, 81543888, 119596564, 177392936, 266391665, |
35
|
|
|
|
|
|
|
411512446, 646331578, 1043239835, 1723380058, UVCONST(2919198776), |
36
|
|
|
|
|
|
|
UVCONST(4294967295) |
37
|
|
|
|
|
|
|
}; |
38
|
|
|
|
|
|
|
#define SMALL_NRAM_UPPER_MULT 2852 |
39
|
|
|
|
|
|
|
#define SMALL_NRAM_UPPER (sizeof(small_ram_upper_idx)/sizeof(small_ram_upper_idx[0])) |
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
#if BITS_PER_WORD == 64 |
42
|
|
|
|
|
|
|
static const UV large_ram_upper_idx[] = { |
43
|
|
|
|
|
|
|
UVCONST( 2256197513), UVCONST( 2556868249), UVCONST( 2919198776), |
44
|
|
|
|
|
|
|
/* 11071, 11070, 11069, 11068, 11067, 11066, 11065, 11064, 11063 */ |
45
|
|
|
|
|
|
|
UVCONST( 3371836636), UVCONST( 3874119737), UVCONST( 4467380631), |
46
|
|
|
|
|
|
|
UVCONST( 5163817509), UVCONST( 5950413657), UVCONST( 6901033442), |
47
|
|
|
|
|
|
|
UVCONST( 8015893438), UVCONST( 9322299866), UVCONST( 10845166831), |
48
|
|
|
|
|
|
|
/* 11062, 11061, 11060, 11059, 11058, 11057, 11056, 11055, 11054 */ |
49
|
|
|
|
|
|
|
UVCONST( 12727569836), UVCONST( 14852585181), UVCONST( 17463419944), |
50
|
|
|
|
|
|
|
UVCONST( 20585027534), UVCONST( 24252210453), UVCONST( 28704897522), |
51
|
|
|
|
|
|
|
UVCONST( 34003499133), UVCONST( 40436019651), UVCONST( 48229247660), |
52
|
|
|
|
|
|
|
/* 11053, 11052, 11051, 11050, 11049, 11048, 11047, 11046, 11045 */ |
53
|
|
|
|
|
|
|
UVCONST( 57558675911), UVCONST( 69028965312), UVCONST( 83015434548), |
54
|
|
|
|
|
|
|
UVCONST( 100138535684), UVCONST( 121051505524), UVCONST( 146783829698), |
55
|
|
|
|
|
|
|
UVCONST( 178727808587), UVCONST( 218113299173), UVCONST( 267104085772), |
56
|
|
|
|
|
|
|
/* 11044, 11043, 11042, 11041, 11040, 11039, 11038, 11037, 11036 */ |
57
|
|
|
|
|
|
|
UVCONST( 328057281739), UVCONST( 404608665617), UVCONST( 500552556306), |
58
|
|
|
|
|
|
|
UVCONST( 621794385742), UVCONST( 774739900202), UVCONST( 969943548548), |
59
|
|
|
|
|
|
|
UVCONST( 1218276754392), UVCONST( 1536655221634), UVCONST( 1946308957195), |
60
|
|
|
|
|
|
|
/* 11035, 11034, 11033, 11032, 11031, 11030, 11029, 11028, 11027 */ |
61
|
|
|
|
|
|
|
UVCONST( 2475456777850), UVCONST( 3162491651655), UVCONST( 4058282334559), |
62
|
|
|
|
|
|
|
UVCONST( 5233096936468), UVCONST( 6776539822896), UVCONST( 8821085181511), |
63
|
|
|
|
|
|
|
UVCONST( 11539712635284), UVCONST( 15171808426849), UVCONST( 20056581407599), |
64
|
|
|
|
|
|
|
/* 11026, 11025, 11024, 11023, 11022, 11021, 11020, 11019, 11018 */ |
65
|
|
|
|
|
|
|
UVCONST( 26656864542121), UVCONST( 35627338984775), UVCONST( 47899755943330), |
66
|
|
|
|
|
|
|
UVCONST( 64773009691258), UVCONST( 88134778026475), UVCONST(120680838280663), |
67
|
|
|
|
|
|
|
UVCONST(166331208358410), UVCONST(230783974844445), UVCONST(322443487572932), |
68
|
|
|
|
|
|
|
/* 11017, 11016, 11015, 11014, 11013, 11012, 11011, 11010, 11009 */ |
69
|
|
|
|
|
|
|
UVCONST(453738479744216), UVCONST(643248344602940), UVCONST(918867804392140), |
70
|
|
|
|
|
|
|
UVCONST(1322953724888193),UVCONST(1920282116080684), |
71
|
|
|
|
|
|
|
1.47*UVCONST(1920282116080684), /* Estimates for larger */ |
72
|
|
|
|
|
|
|
2.3*UVCONST(1920282116080684), |
73
|
|
|
|
|
|
|
3.4*UVCONST(1920282116080684), |
74
|
|
|
|
|
|
|
5.1*UVCONST(1920282116080684), |
75
|
|
|
|
|
|
|
7.9*UVCONST(1920282116080684), |
76
|
|
|
|
|
|
|
12.2*UVCONST(1920282116080684), |
77
|
|
|
|
|
|
|
}; |
78
|
|
|
|
|
|
|
#define LARGE_NRAM_UPPER_MULT 11075 |
79
|
|
|
|
|
|
|
#define LARGE_NRAM_UPPER (sizeof(large_ram_upper_idx)/sizeof(large_ram_upper_idx[0])) |
80
|
|
|
|
|
|
|
#endif |
81
|
|
|
|
|
|
|
|
82
|
1280
|
|
|
|
|
|
UV nth_ramanujan_prime_upper(UV n) { |
83
|
|
|
|
|
|
|
UV i, mult, res; |
84
|
|
|
|
|
|
|
|
85
|
1280
|
100
|
|
|
|
|
if (n <= 2) return (n==0) ? 0 : (n==1) ? 2 : 11; |
|
|
50
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
86
|
1273
|
|
|
|
|
|
res = nth_prime_upper(3*n); |
87
|
|
|
|
|
|
|
|
88
|
1273
|
50
|
|
|
|
|
if (n < UVCONST(2256197512) || BITS_PER_WORD < 64) { |
89
|
|
|
|
|
|
|
/* While p_3n is a complete upper bound, Rp_n tends to p_2n, and |
90
|
|
|
|
|
|
|
* SNN(2011) theorem 4 shows how we can find (m,c) values where m < 1, |
91
|
|
|
|
|
|
|
* Rn < m*p_3n for all n > c. Here we use various quantized m values |
92
|
|
|
|
|
|
|
* and the table gives us c values where it applies. */ |
93
|
1273
|
100
|
|
|
|
|
if (n < 20) mult = 3580; |
94
|
1047
|
100
|
|
|
|
|
else if (n < 98) mult = 3340; |
95
|
116
|
100
|
|
|
|
|
else if (n < 1580) mult = 3040; |
96
|
104
|
100
|
|
|
|
|
else if (n < 3242) mult = 2885; |
97
|
|
|
|
|
|
|
else { |
98
|
5729
|
50
|
|
|
|
|
for (i = 0; i < SMALL_NRAM_UPPER; i++) |
99
|
5729
|
100
|
|
|
|
|
if (small_ram_upper_idx[i] > n) |
100
|
103
|
|
|
|
|
|
break; |
101
|
103
|
|
|
|
|
|
mult = SMALL_NRAM_UPPER_MULT-i; |
102
|
|
|
|
|
|
|
} |
103
|
1273
|
50
|
|
|
|
|
if (res > (UV_MAX/mult)) res = (UV) (((long double) mult / 4096.0L) * res); |
104
|
1273
|
|
|
|
|
|
else res = (res * mult) >> 12; |
105
|
|
|
|
|
|
|
#if BITS_PER_WORD == 64 |
106
|
|
|
|
|
|
|
} else { |
107
|
0
|
0
|
|
|
|
|
for (i = 0; i < LARGE_NRAM_UPPER; i++) |
108
|
0
|
0
|
|
|
|
|
if (large_ram_upper_idx[i] > n) |
109
|
0
|
|
|
|
|
|
break; |
110
|
0
|
|
|
|
|
|
mult = (LARGE_NRAM_UPPER_MULT-i); |
111
|
0
|
0
|
|
|
|
|
if (res > (UV_MAX/mult)) res = (UV) (((long double) mult / 16384.0L) * res); |
112
|
0
|
|
|
|
|
|
else res = (res * mult) >> 14; |
113
|
|
|
|
|
|
|
#endif |
114
|
|
|
|
|
|
|
} |
115
|
1273
|
100
|
|
|
|
|
if (n > 43 && n < 10000) { |
|
|
100
|
|
|
|
|
|
116
|
|
|
|
|
|
|
/* Calculate upper bound using Srinivasan and Arés 2017 */ |
117
|
|
|
|
|
|
|
/* TODO We should construct a tighter bound like this. */ |
118
|
526
|
|
|
|
|
|
double s = (2 * (double)n) * (1.0L + 1.0L/ramanujan_sa_gn(n)); |
119
|
526
|
|
|
|
|
|
UV ps = nth_prime_upper( (UV) s ); |
120
|
526
|
100
|
|
|
|
|
if (ps < res) |
121
|
24
|
|
|
|
|
|
res = ps; |
122
|
|
|
|
|
|
|
} |
123
|
1273
|
|
|
|
|
|
return res; |
124
|
|
|
|
|
|
|
} |
125
|
|
|
|
|
|
|
static const uint32_t small_ram_lower_idx[] = { |
126
|
|
|
|
|
|
|
2785, 2800, 4275, 5935, 6107, 8797, 9556, 13314, 13641, 20457, 23745, |
127
|
|
|
|
|
|
|
34432, 50564, 69194, 97434, 149399, 224590, 337116, 514260, 804041, |
128
|
|
|
|
|
|
|
1317612, 2340461, 4332796, 8393680, 17227225, 38996663, 94437897, |
129
|
|
|
|
|
|
|
253560792, 763315838, UVCONST(2663598260), UVCONST(4294967295) |
130
|
|
|
|
|
|
|
}; |
131
|
|
|
|
|
|
|
#define SMALL_NRAM_LOWER_MULT 557 |
132
|
|
|
|
|
|
|
#define SMALL_NRAM_LOWER (sizeof(small_ram_lower_idx)/sizeof(small_ram_lower_idx[0])) |
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
#if BITS_PER_WORD == 64 |
135
|
|
|
|
|
|
|
static const UV large_ram_lower_idx[] = { |
136
|
|
|
|
|
|
|
UVCONST( 2267483962), UVCONST( 2663598260), UVCONST( 3152476871), |
137
|
|
|
|
|
|
|
UVCONST( 3742932857), UVCONST( 4446913643), UVCONST( 5298293978), |
138
|
|
|
|
|
|
|
UVCONST( 6318053149), UVCONST( 7608807497), UVCONST( 9140758346), |
139
|
|
|
|
|
|
|
UVCONST( 11015956390), UVCONST( 13351265915), UVCONST( 16199147294), |
140
|
|
|
|
|
|
|
/* 4213, 4212, 4211, 4210, 4209, 4208, 4207, 4206, 4205 */ |
141
|
|
|
|
|
|
|
UVCONST( 19739499402), UVCONST( 24137542585), UVCONST( 29629560254), |
142
|
|
|
|
|
|
|
UVCONST( 36435870727), UVCONST( 45085624406), UVCONST( 55940244390), |
143
|
|
|
|
|
|
|
UVCONST( 69713814138), UVCONST( 87221199999), UVCONST( 109606558728), |
144
|
|
|
|
|
|
|
/* 4204, 4203, 4202, 4201, 4200, 4199, 4198, 4197, 4196 */ |
145
|
|
|
|
|
|
|
UVCONST( 138227790751), UVCONST( 175290761423), UVCONST( 223132516788), |
146
|
|
|
|
|
|
|
UVCONST( 285315117360), UVCONST( 366761235749), UVCONST( 473606049986), |
147
|
|
|
|
|
|
|
UVCONST( 614858505562), UVCONST( 802552362351), UVCONST( 1052957884730), |
148
|
|
|
|
|
|
|
/* 4195, 4194, 4193, 4192, 4191, 4190, 4189, 4188, 4187 */ |
149
|
|
|
|
|
|
|
UVCONST( 1389550174208), UVCONST( 1843854433659), UVCONST( 2461728402552), |
150
|
|
|
|
|
|
|
UVCONST( 3306766457564), UVCONST( 4469341663210), UVCONST( 6080948095909), |
151
|
|
|
|
|
|
|
UVCONST( 8329279118918), UVCONST( 11488848759561), UVCONST( 15959135388235), |
152
|
|
|
|
|
|
|
/* 4186, 4185, 4184, 4183, 4182, 4181, 4180, 4179, 4178 */ |
153
|
|
|
|
|
|
|
UVCONST( 22336622435614), UVCONST( 31501671598985), UVCONST( 44779902229212), |
154
|
|
|
|
|
|
|
UVCONST( 64180867011184), UVCONST( 92772523880955), UVCONST(135282253437392), |
155
|
|
|
|
|
|
|
UVCONST(199079826917291), UVCONST(295746797998912), UVCONST(443667118326600), |
156
|
|
|
|
|
|
|
/* 4177, 4176, 4175, 4174, 4173, 4172, 4171, 4170, 4169 */ |
157
|
|
|
|
|
|
|
UVCONST(672350086039900),UVCONST(1029719394152693),UVCONST(1594365662292999), |
158
|
|
|
|
|
|
|
1.55*UVCONST(1594365662292999), /* estimates here and further */ |
159
|
|
|
|
|
|
|
2.45*UVCONST(1594365662292999), |
160
|
|
|
|
|
|
|
3.90*UVCONST(1594365662292999), |
161
|
|
|
|
|
|
|
6.30*UVCONST(1594365662292999), |
162
|
|
|
|
|
|
|
10.4*UVCONST(1594365662292999), |
163
|
|
|
|
|
|
|
17.2*UVCONST(1594365662292999), |
164
|
|
|
|
|
|
|
}; |
165
|
|
|
|
|
|
|
#define LARGE_NRAM_LOWER_MULT 4225 |
166
|
|
|
|
|
|
|
#define LARGE_NRAM_LOWER (sizeof(large_ram_lower_idx)/sizeof(large_ram_lower_idx[0])) |
167
|
|
|
|
|
|
|
#endif |
168
|
|
|
|
|
|
|
|
169
|
1295
|
|
|
|
|
|
UV nth_ramanujan_prime_lower(UV n) { |
170
|
|
|
|
|
|
|
UV res, i, mult; |
171
|
1295
|
100
|
|
|
|
|
if (n <= 2) return (n==0) ? 0 : (n==1) ? 2 : 11; |
|
|
50
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
172
|
|
|
|
|
|
|
|
173
|
1288
|
|
|
|
|
|
res = nth_prime_lower(2*n); |
174
|
|
|
|
|
|
|
|
175
|
1288
|
50
|
|
|
|
|
if (n < UVCONST(2267483962) || BITS_PER_WORD < 64) { |
176
|
3201
|
50
|
|
|
|
|
for (i = 0; i < SMALL_NRAM_LOWER; i++) |
177
|
3201
|
100
|
|
|
|
|
if (small_ram_lower_idx[i] > n) |
178
|
1288
|
|
|
|
|
|
break; |
179
|
1288
|
|
|
|
|
|
mult = (SMALL_NRAM_LOWER_MULT-i); |
180
|
1288
|
50
|
|
|
|
|
if (res > (UV_MAX/mult)) res = (UV) (((long double) mult / 512.0L) * res); |
181
|
1288
|
|
|
|
|
|
else res = (res * mult) >> 9; |
182
|
|
|
|
|
|
|
#if BITS_PER_WORD == 64 |
183
|
|
|
|
|
|
|
} else { |
184
|
0
|
0
|
|
|
|
|
if (n < large_ram_lower_idx[LARGE_NRAM_LOWER-1]) { |
185
|
0
|
0
|
|
|
|
|
for (i = 0; i < LARGE_NRAM_LOWER; i++) |
186
|
0
|
0
|
|
|
|
|
if (large_ram_lower_idx[i] > n) |
187
|
0
|
|
|
|
|
|
break; |
188
|
0
|
|
|
|
|
|
mult = (LARGE_NRAM_LOWER_MULT-i); |
189
|
0
|
0
|
|
|
|
|
if (res > (UV_MAX/mult)) res = (UV) (((long double) mult / 4096.0L) * res); |
190
|
0
|
|
|
|
|
|
else res = (res * mult) >> 12; |
191
|
|
|
|
|
|
|
} |
192
|
|
|
|
|
|
|
#endif |
193
|
|
|
|
|
|
|
} |
194
|
1288
|
|
|
|
|
|
return res; |
195
|
|
|
|
|
|
|
} |
196
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
/* An advantage of making these binary searches on the inverse is that we |
198
|
|
|
|
|
|
|
* don't have to tune them separately, and nothing changes if the prime |
199
|
|
|
|
|
|
|
* count bounds are modified. We do need to keep up to date with any |
200
|
|
|
|
|
|
|
* changes to nth_prime_{lower,upper} however. */ |
201
|
|
|
|
|
|
|
|
202
|
251
|
|
|
|
|
|
UV ramanujan_prime_count_lower(UV n) { |
203
|
|
|
|
|
|
|
UV lo, hi; |
204
|
251
|
100
|
|
|
|
|
if (n < 29) return (n < 2) ? 0 : (n < 11) ? 1 : (n < 17) ? 2 : 3; |
|
|
50
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
205
|
|
|
|
|
|
|
/* Binary search on nth_ramanujan_prime_upper */ |
206
|
|
|
|
|
|
|
/* We know we're between p_2n and p_3n, probably close to the former. */ |
207
|
233
|
|
|
|
|
|
lo = prime_count_lower(n)/3; |
208
|
233
|
|
|
|
|
|
hi = prime_count_upper(n) >> 1; |
209
|
1158
|
100
|
|
|
|
|
while (lo < hi) { |
210
|
925
|
|
|
|
|
|
UV mid = lo + (hi-lo)/2; |
211
|
925
|
100
|
|
|
|
|
if (nth_ramanujan_prime_upper(mid) < n) lo = mid+1; |
212
|
476
|
|
|
|
|
|
else hi = mid; |
213
|
|
|
|
|
|
|
} |
214
|
233
|
|
|
|
|
|
return lo-1; |
215
|
|
|
|
|
|
|
} |
216
|
251
|
|
|
|
|
|
UV ramanujan_prime_count_upper(UV n) { |
217
|
|
|
|
|
|
|
/* return prime_count_upper(n) >> 1; */ /* Simple bound */ |
218
|
|
|
|
|
|
|
UV lo, hi; |
219
|
251
|
100
|
|
|
|
|
if (n < 29) return (n < 2) ? 0 : (n < 11) ? 1 : (n < 17) ? 2 : 3; |
|
|
50
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
220
|
|
|
|
|
|
|
/* Binary search on nth_ramanujan_prime_upper */ |
221
|
|
|
|
|
|
|
/* We know we're between p_2n and p_3n, probably close to the former. */ |
222
|
235
|
|
|
|
|
|
lo = prime_count_lower(n)/3; |
223
|
235
|
|
|
|
|
|
hi = prime_count_upper(n) >> 1; |
224
|
1183
|
100
|
|
|
|
|
while (lo < hi) { |
225
|
948
|
|
|
|
|
|
UV mid = lo + (hi-lo)/2; |
226
|
948
|
100
|
|
|
|
|
if (nth_ramanujan_prime_lower(mid) < n) lo = mid+1; |
227
|
361
|
|
|
|
|
|
else hi = mid; |
228
|
|
|
|
|
|
|
} |
229
|
235
|
|
|
|
|
|
return lo-1; |
230
|
|
|
|
|
|
|
} |
231
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
/* Return array of first n ramanujan primes. Use Noe's algorithm. */ |
233
|
8
|
|
|
|
|
|
UV* n_ramanujan_primes(UV n) { |
234
|
|
|
|
|
|
|
UV max, k, s, *L; |
235
|
|
|
|
|
|
|
unsigned char* sieve; |
236
|
8
|
|
|
|
|
|
max = nth_ramanujan_prime_upper(n); /* Rn <= max, so we can sieve to there */ |
237
|
8
|
50
|
|
|
|
|
MPUverbose(2, "sieving to %"UVuf" for first %"UVuf" Ramanujan primes\n", max, n); |
238
|
8
|
50
|
|
|
|
|
Newz(0, L, n, UV); |
239
|
8
|
|
|
|
|
|
L[0] = 2; |
240
|
8
|
|
|
|
|
|
sieve = sieve_erat30(max); |
241
|
884
|
100
|
|
|
|
|
for (s = 0, k = 7; k <= max; k += 2) { |
242
|
876
|
100
|
|
|
|
|
if (is_prime_in_sieve(sieve, k)) s++; |
243
|
876
|
100
|
|
|
|
|
if (s < n) L[s] = k+1; |
244
|
876
|
100
|
|
|
|
|
if ((k & 3) == 1 && is_prime_in_sieve(sieve, (k+1)>>1)) s--; |
|
|
100
|
|
|
|
|
|
245
|
876
|
100
|
|
|
|
|
if (s < n) L[s] = k+2; |
246
|
|
|
|
|
|
|
} |
247
|
8
|
|
|
|
|
|
Safefree(sieve); |
248
|
8
|
|
|
|
|
|
return L; |
249
|
|
|
|
|
|
|
} |
250
|
|
|
|
|
|
|
|
251
|
259
|
|
|
|
|
|
UV* n_range_ramanujan_primes(UV nlo, UV nhi) { |
252
|
|
|
|
|
|
|
UV mink, maxk, k, s, *L; |
253
|
|
|
|
|
|
|
|
254
|
259
|
50
|
|
|
|
|
if (nlo == 0) nlo = 1; |
255
|
259
|
50
|
|
|
|
|
if (nhi == 0) nhi = 1; |
256
|
|
|
|
|
|
|
|
257
|
|
|
|
|
|
|
/* If we're starting from 1, just do single monolithic sieve */ |
258
|
259
|
100
|
|
|
|
|
if (nlo == 1) return n_ramanujan_primes(nhi); |
259
|
|
|
|
|
|
|
|
260
|
251
|
50
|
|
|
|
|
Newz(0, L, nhi-nlo+1, UV); |
261
|
251
|
50
|
|
|
|
|
if (nlo <= 1 && nhi >= 1) L[1-nlo] = 2; |
|
|
0
|
|
|
|
|
|
262
|
251
|
100
|
|
|
|
|
if (nlo <= 2 && nhi >= 2) L[2-nlo] = 11; |
|
|
50
|
|
|
|
|
|
263
|
251
|
100
|
|
|
|
|
if (nhi < 3) return L; |
264
|
|
|
|
|
|
|
|
265
|
250
|
|
|
|
|
|
mink = nth_ramanujan_prime_lower(nlo) - 1; |
266
|
250
|
|
|
|
|
|
maxk = nth_ramanujan_prime_upper(nhi) + 1; |
267
|
|
|
|
|
|
|
|
268
|
250
|
100
|
|
|
|
|
if (mink < 15) mink = 15; |
269
|
250
|
100
|
|
|
|
|
if (mink % 2 == 0) mink--; |
270
|
250
|
50
|
|
|
|
|
MPUverbose(2, "Rn[%"UVuf"] to Rn[%"UVuf"] Noe's: %"UVuf" to %"UVuf"\n", nlo, nhi, mink, maxk); |
271
|
|
|
|
|
|
|
|
272
|
250
|
|
|
|
|
|
s = 1 + prime_count(2,mink-2) - prime_count(2,(mink-1)>>1); |
273
|
|
|
|
|
|
|
{ |
274
|
250
|
|
|
|
|
|
unsigned char *segment, *seg2 = 0; |
275
|
250
|
|
|
|
|
|
void* ctx = start_segment_primes(mink, maxk, &segment); |
276
|
250
|
|
|
|
|
|
UV seg_base, seg_low, seg_high, new_size, seg2beg, seg2end, seg2size = 0; |
277
|
500
|
100
|
|
|
|
|
while (next_segment_primes(ctx, &seg_base, &seg_low, &seg_high)) { |
278
|
250
|
|
|
|
|
|
seg2beg = 30 * (((seg_low+1)>>1)/30); |
279
|
250
|
|
|
|
|
|
seg2end = 30 * ((((seg_high+1)>>1)+29)/30); |
280
|
250
|
|
|
|
|
|
new_size = (seg2end - seg2beg)/30 + 1; |
281
|
250
|
50
|
|
|
|
|
if (new_size > seg2size) { |
282
|
250
|
50
|
|
|
|
|
if (seg2size > 0) Safefree(seg2); |
283
|
250
|
|
|
|
|
|
New(0, seg2, new_size, unsigned char); |
284
|
250
|
|
|
|
|
|
seg2size = new_size; |
285
|
|
|
|
|
|
|
} |
286
|
250
|
|
|
|
|
|
(void) sieve_segment(seg2, seg2beg/30, seg2end/30); |
287
|
197451
|
100
|
|
|
|
|
for (k = seg_low; k <= seg_high; k += 2) { |
288
|
197201
|
100
|
|
|
|
|
if (is_prime_in_sieve(segment, k-seg_base)) s++; |
289
|
197201
|
100
|
|
|
|
|
if (s >= nlo && s <= nhi) L[s-nlo] = k+1; |
|
|
100
|
|
|
|
|
|
290
|
197201
|
100
|
|
|
|
|
if ((k & 3) == 1 && is_prime_in_sieve(seg2, ((k+1)>>1)-seg2beg)) s--; |
|
|
100
|
|
|
|
|
|
291
|
197201
|
100
|
|
|
|
|
if (s >= nlo && s <= nhi) L[s-nlo] = k+2; |
|
|
100
|
|
|
|
|
|
292
|
|
|
|
|
|
|
} |
293
|
|
|
|
|
|
|
} |
294
|
250
|
|
|
|
|
|
end_segment_primes(ctx); |
295
|
250
|
|
|
|
|
|
Safefree(seg2); |
296
|
|
|
|
|
|
|
} |
297
|
250
|
50
|
|
|
|
|
MPUverbose(2, "Generated %"UVuf" Ramanujan primes from %"UVuf" to %"UVuf"\n", nhi-nlo+1, L[0], L[nhi-nlo]); |
298
|
250
|
|
|
|
|
|
return L; |
299
|
|
|
|
|
|
|
} |
300
|
|
|
|
|
|
|
|
301
|
75
|
|
|
|
|
|
UV nth_ramanujan_prime(UV n) { |
302
|
|
|
|
|
|
|
UV rn, *L; |
303
|
75
|
100
|
|
|
|
|
if (n <= 2) return (n == 0) ? 0 : (n == 1) ? 2 : 11; |
|
|
50
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
304
|
73
|
|
|
|
|
|
L = n_range_ramanujan_primes(n, n); |
305
|
73
|
|
|
|
|
|
rn = L[0]; |
306
|
73
|
|
|
|
|
|
Safefree(L); |
307
|
73
|
|
|
|
|
|
return rn; |
308
|
|
|
|
|
|
|
} |
309
|
|
|
|
|
|
|
|
310
|
|
|
|
|
|
|
/* Returns array of Ram primes between low and high, results from first->last */ |
311
|
175
|
|
|
|
|
|
UV* ramanujan_primes(UV* first, UV* last, UV low, UV high) |
312
|
|
|
|
|
|
|
{ |
313
|
|
|
|
|
|
|
UV nlo, nhi, *L, lo, hi, mid; |
314
|
|
|
|
|
|
|
|
315
|
175
|
50
|
|
|
|
|
if (high < 2 || high < low) return 0; |
|
|
50
|
|
|
|
|
|
316
|
175
|
50
|
|
|
|
|
if (low < 2) low = 2; |
317
|
|
|
|
|
|
|
|
318
|
175
|
|
|
|
|
|
nlo = ramanujan_prime_count_lower(low); |
319
|
175
|
|
|
|
|
|
nhi = ramanujan_prime_count_upper(high); |
320
|
175
|
|
|
|
|
|
L = n_range_ramanujan_primes(nlo, nhi); |
321
|
|
|
|
|
|
|
|
322
|
|
|
|
|
|
|
/* Search for first entry in range */ |
323
|
689
|
100
|
|
|
|
|
for (lo = 0, hi = nhi-nlo+1; lo < hi; ) { |
324
|
514
|
|
|
|
|
|
mid = lo + (hi-lo)/2; |
325
|
514
|
100
|
|
|
|
|
if (L[mid] < low) lo = mid+1; |
326
|
274
|
|
|
|
|
|
else hi = mid; |
327
|
|
|
|
|
|
|
} |
328
|
175
|
|
|
|
|
|
*first = lo; |
329
|
|
|
|
|
|
|
/* Search for last entry in range */ |
330
|
548
|
100
|
|
|
|
|
for (hi = nhi-nlo+1; lo < hi; ) { |
331
|
373
|
|
|
|
|
|
mid = lo + (hi-lo)/2; |
332
|
373
|
100
|
|
|
|
|
if (L[mid] <= high) lo = mid+1; |
333
|
285
|
|
|
|
|
|
else hi = mid; |
334
|
|
|
|
|
|
|
} |
335
|
175
|
|
|
|
|
|
*last = lo-1; |
336
|
175
|
|
|
|
|
|
return L; |
337
|
|
|
|
|
|
|
} |
338
|
|
|
|
|
|
|
|
339
|
984
|
|
|
|
|
|
int is_ramanujan_prime(UV n) { |
340
|
|
|
|
|
|
|
UV beg, end, *L; |
341
|
|
|
|
|
|
|
|
342
|
984
|
100
|
|
|
|
|
if (!is_prime(n)) return 0; |
343
|
166
|
100
|
|
|
|
|
if (n < 17) return (n == 2 || n == 11); |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
344
|
|
|
|
|
|
|
|
345
|
|
|
|
|
|
|
/* Generate Ramanujan primes and see if we're in the list. Slow. */ |
346
|
160
|
|
|
|
|
|
L = ramanujan_primes(&beg, &end, n, n); |
347
|
160
|
|
|
|
|
|
Safefree(L); |
348
|
984
|
|
|
|
|
|
return (beg <= end); |
349
|
|
|
|
|
|
|
} |
350
|
|
|
|
|
|
|
|
351
|
2
|
|
|
|
|
|
UV ramanujan_prime_count_approx(UV n) |
352
|
|
|
|
|
|
|
{ |
353
|
|
|
|
|
|
|
/* Binary search on nth_ramanujan_prime_approx */ |
354
|
|
|
|
|
|
|
UV lo, hi; |
355
|
2
|
50
|
|
|
|
|
if (n < 29) return (n < 2) ? 0 : (n < 11) ? 1 : (n < 17) ? 2 : 3; |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
356
|
2
|
|
|
|
|
|
lo = ramanujan_prime_count_lower(n); |
357
|
2
|
|
|
|
|
|
hi = ramanujan_prime_count_upper(n); |
358
|
23
|
100
|
|
|
|
|
while (lo < hi) { |
359
|
21
|
|
|
|
|
|
UV mid = lo + (hi-lo)/2; |
360
|
21
|
100
|
|
|
|
|
if (nth_ramanujan_prime_approx(mid) < n) lo = mid+1; |
361
|
14
|
|
|
|
|
|
else hi = mid; |
362
|
|
|
|
|
|
|
} |
363
|
2
|
|
|
|
|
|
return lo-1; |
364
|
|
|
|
|
|
|
} |
365
|
|
|
|
|
|
|
|
366
|
23
|
|
|
|
|
|
UV nth_ramanujan_prime_approx(UV n) |
367
|
|
|
|
|
|
|
{ |
368
|
23
|
|
|
|
|
|
UV lo = nth_ramanujan_prime_lower(n), hi = nth_ramanujan_prime_upper(n); |
369
|
|
|
|
|
|
|
/* Our upper bounds come out much closer, so weight toward them. */ |
370
|
23
|
50
|
|
|
|
|
double weight = (n <= UVCONST(4294967295)) ? 1.62 : 1.51; |
371
|
23
|
|
|
|
|
|
return lo + weight * ((hi-lo) >> 1); |
372
|
|
|
|
|
|
|
} |
373
|
|
|
|
|
|
|
|
374
|
|
|
|
|
|
|
#if BITS_PER_WORD == 64 |
375
|
|
|
|
|
|
|
#define RAMPC2 56 |
376
|
|
|
|
|
|
|
static const UV ramanujan_counts_pow2[RAMPC2+1] = { |
377
|
|
|
|
|
|
|
0, 1, 1, 1, 2, 4, 7, 13, 23, 42, 75, 137, 255, 463, 872, 1612, |
378
|
|
|
|
|
|
|
3030, 5706, 10749, 20387, 38635, 73584, 140336, 268216, 513705, |
379
|
|
|
|
|
|
|
985818, 1894120, 3645744, 7027290, 13561906, 26207278, 50697533, |
380
|
|
|
|
|
|
|
98182656, 190335585, 369323301, 717267167, |
381
|
|
|
|
|
|
|
UVCONST( 1394192236), UVCONST( 2712103833), UVCONST( 5279763823), |
382
|
|
|
|
|
|
|
UVCONST( 10285641777), UVCONST( 20051180846), UVCONST( 39113482639), |
383
|
|
|
|
|
|
|
UVCONST( 76344462797), UVCONST( 149100679004), UVCONST( 291354668495), |
384
|
|
|
|
|
|
|
UVCONST( 569630404447), UVCONST( 1114251967767), UVCONST( 2180634225768), |
385
|
|
|
|
|
|
|
UVCONST( 4269555883751), UVCONST( 8363243713305), UVCONST( 16388947026629), |
386
|
|
|
|
|
|
|
UVCONST( 32129520311897), UVCONST( 63012603695171), UVCONST(123627200537929), |
387
|
|
|
|
|
|
|
UVCONST(242637500756376), UVCONST(476379740340417), UVCONST(935609435783647) }; |
388
|
|
|
|
|
|
|
#else |
389
|
|
|
|
|
|
|
#define RAMPC2 31 /* input limited */ |
390
|
|
|
|
|
|
|
static const UV ramanujan_counts_pow2[RAMPC2+1] = { |
391
|
|
|
|
|
|
|
0, 1, 1, 1, 2, 4, 7, 13, 23, 42, 75, 137, 255, 463, 872, 1612, |
392
|
|
|
|
|
|
|
3030, 5706, 10749, 20387, 38635, 73584, 140336, 268216, 513705, |
393
|
|
|
|
|
|
|
985818, 1894120, 3645744, 7027290, 13561906, 26207278, 50697533 }; |
394
|
|
|
|
|
|
|
#endif |
395
|
|
|
|
|
|
|
|
396
|
12
|
|
|
|
|
|
static UV _ramanujan_prime_count(UV n) { |
397
|
12
|
50
|
|
|
|
|
UV i, v, rn, *L, window, swin, ewin, wlen, log2 = log2floor(n), winmult = 1; |
398
|
|
|
|
|
|
|
|
399
|
12
|
50
|
|
|
|
|
if (n <= 10) return (n < 2) ? 0 : 1; |
400
|
|
|
|
|
|
|
|
401
|
|
|
|
|
|
|
/* We have some perfect powers of 2 in our table */ |
402
|
12
|
100
|
|
|
|
|
if ((n & (n-1)) == 0 && log2 <= RAMPC2) |
|
|
50
|
|
|
|
|
|
403
|
1
|
|
|
|
|
|
return ramanujan_counts_pow2[log2]; |
404
|
|
|
|
|
|
|
|
405
|
11
|
50
|
|
|
|
|
MPUverbose(1, "ramanujan_prime_count calculating Pi(%"UVuf")\n",n); |
406
|
11
|
|
|
|
|
|
v = prime_count(2,n) - prime_count(2,n >> 1); |
407
|
|
|
|
|
|
|
|
408
|
|
|
|
|
|
|
/* For large enough n make a slightly bigger window */ |
409
|
11
|
50
|
|
|
|
|
if (n > 1000000000U) winmult = 16; |
410
|
|
|
|
|
|
|
|
411
|
|
|
|
|
|
|
while (1) { |
412
|
11
|
|
|
|
|
|
window = 20 * winmult; |
413
|
11
|
100
|
|
|
|
|
swin = (v <= window) ? 1 : v-window; |
414
|
11
|
|
|
|
|
|
ewin = v+window; |
415
|
11
|
|
|
|
|
|
wlen = ewin-swin+1; |
416
|
11
|
|
|
|
|
|
L = n_range_ramanujan_primes(swin, ewin); |
417
|
11
|
50
|
|
|
|
|
if (L[0] < n && L[wlen-1] > n) { |
|
|
50
|
|
|
|
|
|
418
|
|
|
|
|
|
|
/* Naive linear search from the start. */ |
419
|
191
|
50
|
|
|
|
|
for (i = 1; i < wlen; i++) |
420
|
191
|
100
|
|
|
|
|
if (L[i] > n && L[i-1] <= n) |
|
|
50
|
|
|
|
|
|
421
|
11
|
|
|
|
|
|
break; |
422
|
11
|
50
|
|
|
|
|
if (i < wlen) break; |
423
|
|
|
|
|
|
|
} |
424
|
0
|
|
|
|
|
|
winmult *= 2; |
425
|
0
|
0
|
|
|
|
|
MPUverbose(1, " ramanujan_prime_count increasing window\n"); |
426
|
0
|
|
|
|
|
|
} |
427
|
11
|
|
|
|
|
|
rn = swin + i - 1; |
428
|
11
|
|
|
|
|
|
Safefree(L); |
429
|
11
|
|
|
|
|
|
return rn; |
430
|
|
|
|
|
|
|
} |
431
|
|
|
|
|
|
|
|
432
|
10
|
|
|
|
|
|
UV ramanujan_prime_count(UV lo, UV hi) |
433
|
|
|
|
|
|
|
{ |
434
|
|
|
|
|
|
|
UV count; |
435
|
|
|
|
|
|
|
|
436
|
10
|
50
|
|
|
|
|
if (hi < 2 || hi < lo) return 0; |
|
|
50
|
|
|
|
|
|
437
|
|
|
|
|
|
|
|
438
|
|
|
|
|
|
|
#if 1 |
439
|
10
|
|
|
|
|
|
count = _ramanujan_prime_count(hi); |
440
|
10
|
100
|
|
|
|
|
if (lo > 2) |
441
|
2
|
|
|
|
|
|
count -= _ramanujan_prime_count(lo-1); |
442
|
|
|
|
|
|
|
#else |
443
|
|
|
|
|
|
|
{ |
444
|
|
|
|
|
|
|
UV beg, end, *L; |
445
|
|
|
|
|
|
|
/* Generate all Rp from lo to hi */ |
446
|
|
|
|
|
|
|
L = ramanujan_primes(&beg, &end, lo, hi); |
447
|
|
|
|
|
|
|
count = (L && end >= beg) ? end-beg+1 : 0; |
448
|
|
|
|
|
|
|
Safefree(L); |
449
|
|
|
|
|
|
|
} |
450
|
|
|
|
|
|
|
#endif |
451
|
10
|
|
|
|
|
|
return count; |
452
|
|
|
|
|
|
|
} |