File Coverage

ramanujan_primes.c
Criterion Covered Total %
statement 166 182 91.2
branch 157 220 71.3
condition n/a
subroutine n/a
pod n/a
total 323 402 80.3


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             }