| 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 "lucky_numbers.h" |
|
8
|
|
|
|
|
|
|
#include "inverse_interpolate.h" |
|
9
|
|
|
|
|
|
|
#include "ds_bitmask126.h" |
|
10
|
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
static const int _verbose = 0; |
|
12
|
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
/******************************************************************************/ |
|
14
|
|
|
|
|
|
|
/* LUCKY NUMBERS */ |
|
15
|
|
|
|
|
|
|
/******************************************************************************/ |
|
16
|
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
static const unsigned char _small_lucky[48] = {1,3,7,9,13,15,21,25,31,33,37,43,49,51,63,67,69,73,75,79,87,93,99,105,111,115,127,129,133,135,141,151,159,163,169,171,189,193,195,201,205,211,219,223,231,235,237,241}; |
|
18
|
|
|
|
|
|
|
static const unsigned char _small_lucky_count[48] = {0,1,1,2,2,2,2,3,3,4,4,4,4,5,5,6,6,6,6,6,6,7,7,7,7,8,8,8,8,8,8,9,9,10,10,10,10,11,11,11,11,11,11,12,12,12,12,12}; |
|
19
|
|
|
|
|
|
|
/* True for any position where (n % 7*9) could be a lucky number */ |
|
20
|
|
|
|
|
|
|
static const char _lmask63[63+2] = {1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,0,0,0,1,1,0,1,1,0,0,0,0,1,1,0,1,1,0,1,1,0,0,0,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,0,0,0,0,0,0,1,1}; |
|
21
|
|
|
|
|
|
|
/* mpufile '$n++; chomp; $v=$_; next unless $v > 10000; $m[ ($v>>1) % 4095 ]++; END { for (0..4094) { next unless $m[$_]; $b[$_ >> 5] |= (1 << ($_%32)); } say join ",",@b; }' ~/misc/ntheory/lucky_1e8.txt */ |
|
22
|
|
|
|
|
|
|
/* A large bitmask for ((n>>1) % 3*7*3*13) (819). Covers 2,3,7,9,13. */ |
|
23
|
|
|
|
|
|
|
static const uint32_t _lmask5[26] = {2334495963U,2261929142U,1169344621,2204739155U,2727961910U,1639207725,3513561243U,2430232978U,1754683725,3630970059U,3025873062U,1278646881,3658323539U,3055177010U,1830209833,3406669457U,3054200212U,1837519692,1531293898,650340770,757258597,2606838995U,2530306226U,1169218145,3408442969U,11572}; |
|
24
|
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
/* Lucky Number sieves. |
|
27
|
|
|
|
|
|
|
* |
|
28
|
|
|
|
|
|
|
* Mask presieving for the first 5 levels, followed by pre-sieving with a small |
|
29
|
|
|
|
|
|
|
* number of initial values. |
|
30
|
|
|
|
|
|
|
* |
|
31
|
|
|
|
|
|
|
* For fairly small sieves, less than 250k or so, we use a simplied pagelist. |
|
32
|
|
|
|
|
|
|
* Unlike the full pagelist method, this does not use an index tree. |
|
33
|
|
|
|
|
|
|
* |
|
34
|
|
|
|
|
|
|
* For sieving of non-small sizes, a bitmask (32 bits per 126 integers) is |
|
35
|
|
|
|
|
|
|
* used, with an index tree allowing log(n) time index lookups. This is much |
|
36
|
|
|
|
|
|
|
* faster and uses substantially less memory than the other methods. Memory |
|
37
|
|
|
|
|
|
|
* use grows linearly with the sieve size n. |
|
38
|
|
|
|
|
|
|
* |
|
39
|
|
|
|
|
|
|
* Generate first 10M lucky numbers (from 1 to 196502733) on 2020 M1 Mac: |
|
40
|
|
|
|
|
|
|
* 1.8s bitmask126 memory: n/25 ( 8MB) |
|
41
|
|
|
|
|
|
|
* 3.1s pagelist_sieve32 memory: 4 * count * ~2.5 (100MB) |
|
42
|
|
|
|
|
|
|
* 4.2s pagelist_sieve64 memory: 8 * count * ~2.3 (190MB) |
|
43
|
|
|
|
|
|
|
* 1356s lucky_cgen memory: 8 * count * 2 (160MB) |
|
44
|
|
|
|
|
|
|
* 8950s Wilson memory: 8 * count * 1 ( 80MB) |
|
45
|
|
|
|
|
|
|
* |
|
46
|
|
|
|
|
|
|
* pagelist: |
|
47
|
|
|
|
|
|
|
* nth_lucky(1<<31): 55291335127 47 sec using lucky_sieve32 930MB |
|
48
|
|
|
|
|
|
|
* nth_lucky(1<<32): 113924214621 140 sec using lucky_sieve64 3.2GB |
|
49
|
|
|
|
|
|
|
* nth_lucky(1<<33): 234516370291 312 sec using lucky_sieve64 6.3GB |
|
50
|
|
|
|
|
|
|
* nth_lucky(1<<34): 482339741617 733 sec using lucky_sieve64 12.1GB |
|
51
|
|
|
|
|
|
|
* |
|
52
|
|
|
|
|
|
|
* bitmask: |
|
53
|
|
|
|
|
|
|
* nth_lucky(1<<31): 55291335127 23 sec using lucky_sieve32 89MB |
|
54
|
|
|
|
|
|
|
* nth_lucky(1<<32): 113924214621 50 sec using lucky_sieve64 173MB |
|
55
|
|
|
|
|
|
|
* nth_lucky(1<<33): 234516370291 107 sec using lucky_sieve64 341MB |
|
56
|
|
|
|
|
|
|
* nth_lucky(1<<34): 482339741617 224 sec using lucky_sieve64 675MB |
|
57
|
|
|
|
|
|
|
* nth_lucky(1<<35): 991238156013 469 sec using lucky_sieve64 1.3GB |
|
58
|
|
|
|
|
|
|
* nth_lucky(1<<36): 2035487409679 987 sec using lucky_sieve64 2.6GB |
|
59
|
|
|
|
|
|
|
* nth_lucky(1<<37): 4176793875529 2063 sec using lucky_sieve64 5.3GB |
|
60
|
|
|
|
|
|
|
* |
|
61
|
|
|
|
|
|
|
* A Graviton3 r7g takes about 1.6x more CPU time. |
|
62
|
|
|
|
|
|
|
* nth_lucky(1<<39) 17551419620869 in 258min on Graviton3 r7g, 21GB. |
|
63
|
|
|
|
|
|
|
* nth_lucky(1<<40) 35944896074391 in 523min on Graviton3 r7g, 42GB. |
|
64
|
|
|
|
|
|
|
* nth_lucky(1<<41) 73571139180453 in 1112min on Graviton3 r7g, 84GB. |
|
65
|
|
|
|
|
|
|
* nth_lucky(1<<42) 150499648533909 in 2303min on Graviton3 r7g, 168GB. |
|
66
|
|
|
|
|
|
|
* nth_lucky(1<<43) 307703784778627 in 3691min on Graviton3 r7g, 334GB. |
|
67
|
|
|
|
|
|
|
*/ |
|
68
|
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
/* Simple 32-bit pagelist: fast for small (less than 10M or so) inputs. |
|
71
|
|
|
|
|
|
|
* Simple filtering, then sieve a big block using memmove. |
|
72
|
|
|
|
|
|
|
* This is memory intensive and has poor performance with large n. |
|
73
|
|
|
|
|
|
|
*/ |
|
74
|
1364
|
|
|
|
|
|
static uint32_t* _small_lucky_sieve32(UV *size, uint32_t n) { |
|
75
|
|
|
|
|
|
|
uint32_t i, m, c13, level, init_level, fsize, lsize, *lucky; |
|
76
|
|
|
|
|
|
|
|
|
77
|
1364
|
100
|
|
|
|
|
if (n < 259) { |
|
78
|
1309
|
50
|
|
|
|
|
if (n == 0) { *size = 0; return 0; } |
|
79
|
1309
|
|
|
|
|
|
New(0, lucky, 5+n/5, uint32_t); |
|
80
|
28196
|
50
|
|
|
|
|
for (lsize = 0; lsize < 48 && _small_lucky[lsize] <= n; lsize++) |
|
|
|
100
|
|
|
|
|
|
|
81
|
26887
|
|
|
|
|
|
lucky[lsize] = _small_lucky[lsize]; |
|
82
|
1309
|
|
|
|
|
|
*size = lsize; |
|
83
|
1309
|
|
|
|
|
|
return lucky; |
|
84
|
|
|
|
|
|
|
} |
|
85
|
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
/* @l=(2,3,7,9,13); $n=vecprod(@l); $n -= divint($n,$_) for @l; say $n */ |
|
87
|
55
|
|
|
|
|
|
fsize = 1152*(n+4913)/4914; |
|
88
|
55
|
|
|
|
|
|
New(0, lucky, 1 + fsize, uint32_t); |
|
89
|
55
|
|
|
|
|
|
lsize = c13 = 0; |
|
90
|
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
/* Create initial list, filtering out 3,7,9,13 */ |
|
92
|
215116
|
100
|
|
|
|
|
for (i = 1, m = 1; i <= n; i += 6) { |
|
93
|
215061
|
100
|
|
|
|
|
if (_lmask63[m ]) { |
|
94
|
163896
|
100
|
|
|
|
|
if (++c13 == 13) c13 = 0; else lucky[lsize++] = i; |
|
95
|
|
|
|
|
|
|
} |
|
96
|
215061
|
100
|
|
|
|
|
if (_lmask63[m+2] && (i+2) <= n) { |
|
|
|
100
|
|
|
|
|
|
|
97
|
163851
|
100
|
|
|
|
|
if (++c13 == 13) c13 = 0; else lucky[lsize++] = i+2; |
|
98
|
|
|
|
|
|
|
} |
|
99
|
215061
|
100
|
|
|
|
|
if ((m += 6) >= 63) m -= 63; |
|
100
|
|
|
|
|
|
|
} |
|
101
|
55
|
|
|
|
|
|
init_level = 5; |
|
102
|
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
/* After the fill-in, we'll start deleting at 15 */ |
|
104
|
8305
|
50
|
|
|
|
|
for (level = init_level; level < lsize && lucky[level]-1 < lsize; level++) { |
|
|
|
50
|
|
|
|
|
|
|
105
|
8305
|
|
|
|
|
|
uint32_t skip = lucky[level]-1, nlsize = skip; |
|
106
|
8305
|
100
|
|
|
|
|
if (2*(skip+1) > lsize) break; /* Only single skips left */ |
|
107
|
184789
|
100
|
|
|
|
|
for (i = skip+1; i < lsize; i += skip+1) { |
|
108
|
176539
|
|
|
|
|
|
uint32_t ncopy = (skip <= (lsize-i)) ? skip : (lsize-i); |
|
109
|
176539
|
|
|
|
|
|
memmove( lucky + nlsize, lucky + i, ncopy * sizeof(uint32_t) ); |
|
110
|
176539
|
|
|
|
|
|
nlsize += ncopy; |
|
111
|
|
|
|
|
|
|
} |
|
112
|
8250
|
|
|
|
|
|
lsize = nlsize; |
|
113
|
|
|
|
|
|
|
} |
|
114
|
|
|
|
|
|
|
/* Now we just have single skips. Process them all in one pass. */ |
|
115
|
55
|
50
|
|
|
|
|
if (level < lsize && lucky[level]-1 < lsize) { |
|
|
|
50
|
|
|
|
|
|
|
116
|
55
|
|
|
|
|
|
uint32_t skip = lucky[level], nlsize = skip-1; |
|
117
|
6302
|
100
|
|
|
|
|
while (skip < lsize) { |
|
118
|
6247
|
|
|
|
|
|
uint32_t ncopy = lucky[level+1] - lucky[level]; |
|
119
|
6247
|
100
|
|
|
|
|
if (ncopy > lsize-skip) ncopy = lsize - skip; |
|
120
|
6247
|
|
|
|
|
|
memmove(lucky + nlsize, lucky + skip, ncopy * sizeof(uint32_t)); |
|
121
|
6247
|
|
|
|
|
|
nlsize += ncopy; |
|
122
|
6247
|
|
|
|
|
|
skip += ncopy + 1; |
|
123
|
6247
|
|
|
|
|
|
level++; |
|
124
|
|
|
|
|
|
|
} |
|
125
|
55
|
|
|
|
|
|
lsize = nlsize; |
|
126
|
|
|
|
|
|
|
} |
|
127
|
55
|
|
|
|
|
|
*size = lsize; |
|
128
|
55
|
|
|
|
|
|
return lucky; |
|
129
|
|
|
|
|
|
|
} |
|
130
|
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
#if 0 /* No longer used */ |
|
132
|
|
|
|
|
|
|
#include "ds_pagelist32.h" |
|
133
|
|
|
|
|
|
|
uint32_t* _pagelist_lucky_sieve32(UV *size, uint32_t n) { |
|
134
|
|
|
|
|
|
|
uint32_t i, m, lsize, level, init_level, *lucky; |
|
135
|
|
|
|
|
|
|
pagelist32_t *pl; |
|
136
|
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
if (n > 4294967275U) n = 4294967275U; /* Max 32-bit lucky number */ |
|
138
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
if (n <= 280000) return _small_lucky_sieve32(size, n); |
|
140
|
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
pl = pagelist32_create(n); |
|
142
|
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
/* make initial list using filters for small lucky numbers. */ |
|
144
|
|
|
|
|
|
|
{ |
|
145
|
|
|
|
|
|
|
UV slsize; |
|
146
|
|
|
|
|
|
|
uint32_t sln, ln, lbeg, lend, *count, *slucky; |
|
147
|
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
/* Decide how much additional filtering we'll do. */ |
|
149
|
|
|
|
|
|
|
sln = (n <= 1000000U) ? 133 : (n <= 100000000) ? 241 : 925; |
|
150
|
|
|
|
|
|
|
slucky = _small_lucky_sieve32(&slsize, sln); |
|
151
|
|
|
|
|
|
|
Newz(0, count, slsize, uint32_t); |
|
152
|
|
|
|
|
|
|
lbeg = 5; |
|
153
|
|
|
|
|
|
|
lend = slsize-1; |
|
154
|
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
if (1) { |
|
156
|
|
|
|
|
|
|
uint32_t ntarget = (2.4 * (double)n/log(n)); |
|
157
|
|
|
|
|
|
|
uint32_t ninit = n/2; |
|
158
|
|
|
|
|
|
|
for (i = 1; i < slsize && ninit > ntarget; i++) |
|
159
|
|
|
|
|
|
|
ninit -= ninit/slucky[i]; |
|
160
|
|
|
|
|
|
|
if (i < slsize) lend = i; |
|
161
|
|
|
|
|
|
|
if (lend < lbeg) lend = lbeg; |
|
162
|
|
|
|
|
|
|
} |
|
163
|
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
if (_verbose) printf("lucky_sieve32 pre-sieve using %u lucky numbers up to %u\n", lend, slucky[lend]); |
|
165
|
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
/* Construct the initial list */ |
|
167
|
|
|
|
|
|
|
for (i = 1, m = 0; i <= n; i += 2, m += 1) { |
|
168
|
|
|
|
|
|
|
if (m >= 819) m -= 819; /* m = (i>>1) % 819 */ |
|
169
|
|
|
|
|
|
|
if (_lmask5[m >> 5] & (1U << (m & 0x1F))) { |
|
170
|
|
|
|
|
|
|
for (ln = lbeg; ln <= lend; ln++) { |
|
171
|
|
|
|
|
|
|
if (++count[ln] == slucky[ln]) { |
|
172
|
|
|
|
|
|
|
count[ln] = 0; |
|
173
|
|
|
|
|
|
|
break; |
|
174
|
|
|
|
|
|
|
} |
|
175
|
|
|
|
|
|
|
} |
|
176
|
|
|
|
|
|
|
if (ln > lend) |
|
177
|
|
|
|
|
|
|
pagelist32_append(pl,i); |
|
178
|
|
|
|
|
|
|
} |
|
179
|
|
|
|
|
|
|
} |
|
180
|
|
|
|
|
|
|
init_level = lend+1; |
|
181
|
|
|
|
|
|
|
Safefree(slucky); |
|
182
|
|
|
|
|
|
|
Safefree(count); |
|
183
|
|
|
|
|
|
|
} |
|
184
|
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
lsize = pl->nelems; |
|
186
|
|
|
|
|
|
|
if (_verbose) printf("lucky_sieve32 done inserting. values: %u pages: %u\n", lsize, pl->npages[0]); |
|
187
|
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
if (init_level < lsize) { |
|
189
|
|
|
|
|
|
|
/* Use an iterator rather than calling pagelist32_val(pl,level) */ |
|
190
|
|
|
|
|
|
|
pagelist32_iter_t iter = pagelist32_iterator_create(pl, init_level); |
|
191
|
|
|
|
|
|
|
for (level = init_level; level < lsize; level++) { |
|
192
|
|
|
|
|
|
|
uint32_t skip = pagelist32_iterator_next(&iter) - 1; |
|
193
|
|
|
|
|
|
|
if (skip >= lsize) break; |
|
194
|
|
|
|
|
|
|
for (i = skip; i < lsize; i += skip) { |
|
195
|
|
|
|
|
|
|
pagelist32_delete(pl, i); |
|
196
|
|
|
|
|
|
|
lsize--; |
|
197
|
|
|
|
|
|
|
} |
|
198
|
|
|
|
|
|
|
} |
|
199
|
|
|
|
|
|
|
if (_verbose) printf("lucky_sieve32 done sieving. values: %u pages: %u\n", lsize, pl->npages[0]); |
|
200
|
|
|
|
|
|
|
} |
|
201
|
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
lucky = pagelist32_to_array(size, pl); |
|
203
|
|
|
|
|
|
|
if (*size != lsize) croak("bad sizes in lucky sieve 32"); |
|
204
|
|
|
|
|
|
|
if (_verbose) printf("lucky_sieve32 done copying.\n"); |
|
205
|
|
|
|
|
|
|
pagelist32_destroy(pl); |
|
206
|
|
|
|
|
|
|
return lucky; |
|
207
|
|
|
|
|
|
|
} |
|
208
|
|
|
|
|
|
|
#endif |
|
209
|
|
|
|
|
|
|
|
|
210
|
3
|
|
|
|
|
|
static bitmask126_t* _bitmask126_sieve(UV* size, UV n) { |
|
211
|
|
|
|
|
|
|
UV i, lsize, level, init_level; |
|
212
|
|
|
|
|
|
|
bitmask126_t *pl; |
|
213
|
|
|
|
|
|
|
|
|
214
|
3
|
|
|
|
|
|
pl = bitmask126_create(n); |
|
215
|
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
{ |
|
217
|
3
|
|
|
|
|
|
uint8_t count[48] = {0}; |
|
218
|
|
|
|
|
|
|
uint32_t m, sln, ln, lbeg, lend; |
|
219
|
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
/* Decide how much additional filtering we'll do. */ |
|
221
|
3
|
50
|
|
|
|
|
sln = (n <= 200000000) ? 21 : |
|
|
|
0
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
(n <= 0xFFFFFFFF) ? 25 : 87; |
|
223
|
6
|
50
|
|
|
|
|
for (lbeg = lend = 5; lend < 48; lend++) |
|
224
|
6
|
100
|
|
|
|
|
if (_small_lucky[lend] >= sln) |
|
225
|
3
|
|
|
|
|
|
break; |
|
226
|
|
|
|
|
|
|
|
|
227
|
3
|
50
|
|
|
|
|
if (_verbose) printf("bitmask lucky pre-sieve using %u lucky numbers up to %u\n", lend, _small_lucky[lend]); |
|
228
|
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
/* Construct the initial list */ |
|
230
|
505296
|
100
|
|
|
|
|
for (i = 1, m = 0; i <= n; i += 2, m += 1) { |
|
231
|
505293
|
100
|
|
|
|
|
if (m >= 819) m -= 819; /* m = (i>>1) % 819 */ |
|
232
|
505293
|
100
|
|
|
|
|
if (_lmask5[m >> 5] & (1U << (m & 0x1F))) { |
|
233
|
668640
|
100
|
|
|
|
|
for (ln = lbeg; ln <= lend; ln++) { |
|
234
|
458043
|
100
|
|
|
|
|
if (++count[ln] == _small_lucky[ln]) { |
|
235
|
26321
|
|
|
|
|
|
count[ln] = 0; |
|
236
|
26321
|
|
|
|
|
|
break; |
|
237
|
|
|
|
|
|
|
} |
|
238
|
|
|
|
|
|
|
} |
|
239
|
236918
|
100
|
|
|
|
|
if (ln > lend) |
|
240
|
210597
|
|
|
|
|
|
bitmask126_append(pl,i); |
|
241
|
|
|
|
|
|
|
} |
|
242
|
|
|
|
|
|
|
} |
|
243
|
3
|
|
|
|
|
|
init_level = lend+1; |
|
244
|
|
|
|
|
|
|
} |
|
245
|
|
|
|
|
|
|
|
|
246
|
3
|
|
|
|
|
|
lsize = pl->nelems; |
|
247
|
3
|
50
|
|
|
|
|
if (_verbose) printf("bitmask lucky done inserting. values: %lu\n",lsize); |
|
248
|
|
|
|
|
|
|
|
|
249
|
3
|
50
|
|
|
|
|
if (init_level < lsize) { |
|
250
|
3
|
|
|
|
|
|
bitmask126_iter_t iter = bitmask126_iterator_create(pl, init_level); |
|
251
|
7625
|
50
|
|
|
|
|
for (level = init_level; level < lsize; level++) { |
|
252
|
7625
|
|
|
|
|
|
UV skip = bitmask126_iterator_next(&iter) - 1; |
|
253
|
7625
|
100
|
|
|
|
|
if (skip >= lsize) break; |
|
254
|
140415
|
100
|
|
|
|
|
for (i = skip; i < lsize; i += skip) { |
|
255
|
132793
|
|
|
|
|
|
bitmask126_delete(pl, i); |
|
256
|
132793
|
|
|
|
|
|
lsize--; |
|
257
|
|
|
|
|
|
|
} |
|
258
|
|
|
|
|
|
|
} |
|
259
|
3
|
50
|
|
|
|
|
if (_verbose) printf("bitmask lucky done sieving. values: %lu\n",lsize); |
|
260
|
|
|
|
|
|
|
} |
|
261
|
3
|
|
|
|
|
|
*size = lsize; |
|
262
|
3
|
|
|
|
|
|
return pl; |
|
263
|
|
|
|
|
|
|
} |
|
264
|
|
|
|
|
|
|
|
|
265
|
1367
|
|
|
|
|
|
uint32_t* lucky_sieve32(UV *size, uint32_t n) { |
|
266
|
|
|
|
|
|
|
uint32_t *lucky; |
|
267
|
|
|
|
|
|
|
bitmask126_t *pl; |
|
268
|
|
|
|
|
|
|
|
|
269
|
1367
|
100
|
|
|
|
|
if (n == 0) { *size = 0; return 0; } |
|
270
|
1366
|
50
|
|
|
|
|
if (n > 4294967275U) n = 4294967275U; /* Max 32-bit lucky number */ |
|
271
|
|
|
|
|
|
|
|
|
272
|
1366
|
100
|
|
|
|
|
if (n <= 240000U) return _small_lucky_sieve32(size, n); |
|
273
|
|
|
|
|
|
|
|
|
274
|
2
|
|
|
|
|
|
pl = _bitmask126_sieve(size, n); |
|
275
|
|
|
|
|
|
|
|
|
276
|
2
|
|
|
|
|
|
lucky = bitmask126_to_array32(size, pl); |
|
277
|
2
|
50
|
|
|
|
|
if (_verbose) printf("lucky_sieve32 done copying.\n"); |
|
278
|
2
|
|
|
|
|
|
bitmask126_destroy(pl); |
|
279
|
2
|
|
|
|
|
|
return lucky; |
|
280
|
|
|
|
|
|
|
} |
|
281
|
|
|
|
|
|
|
|
|
282
|
0
|
|
|
|
|
|
UV* lucky_sieve64(UV *size, UV n) { |
|
283
|
|
|
|
|
|
|
UV *lucky; |
|
284
|
|
|
|
|
|
|
bitmask126_t *pl; |
|
285
|
|
|
|
|
|
|
|
|
286
|
0
|
0
|
|
|
|
|
if (n == 0) { *size = 0; return 0; } |
|
287
|
|
|
|
|
|
|
|
|
288
|
0
|
|
|
|
|
|
pl = _bitmask126_sieve(size, n); |
|
289
|
|
|
|
|
|
|
|
|
290
|
0
|
|
|
|
|
|
lucky = bitmask126_to_array(size, pl); |
|
291
|
0
|
0
|
|
|
|
|
if (_verbose) printf("lucky_sieve64 done copying.\n"); |
|
292
|
0
|
|
|
|
|
|
bitmask126_destroy(pl); |
|
293
|
0
|
|
|
|
|
|
return lucky; |
|
294
|
|
|
|
|
|
|
} |
|
295
|
|
|
|
|
|
|
|
|
296
|
1
|
|
|
|
|
|
UV* lucky_sieve_range(UV *size, UV beg, UV end) { |
|
297
|
|
|
|
|
|
|
UV i, nlucky, startcount, *lucky; |
|
298
|
|
|
|
|
|
|
bitmask126_t *pl; |
|
299
|
|
|
|
|
|
|
bitmask126_iter_t iter; |
|
300
|
|
|
|
|
|
|
|
|
301
|
1
|
50
|
|
|
|
|
if (end == 0 || beg > end) { *size = 0; return 0; } |
|
|
|
50
|
|
|
|
|
|
|
302
|
|
|
|
|
|
|
|
|
303
|
1
|
50
|
|
|
|
|
if (beg <= 1) return lucky_sieve64(size, end); |
|
304
|
|
|
|
|
|
|
|
|
305
|
1
|
|
|
|
|
|
startcount = lucky_count_lower(beg) - 1; |
|
306
|
1
|
|
|
|
|
|
pl = _bitmask126_sieve(size, end); |
|
307
|
1
|
50
|
|
|
|
|
New(0, lucky, *size - startcount, UV); |
|
308
|
1
|
|
|
|
|
|
iter = bitmask126_iterator_create(pl, startcount); |
|
309
|
32
|
100
|
|
|
|
|
for (i = startcount, nlucky = 0; i < *size; i++) { |
|
310
|
31
|
|
|
|
|
|
UV l = bitmask126_iterator_next(&iter); |
|
311
|
31
|
100
|
|
|
|
|
if (l >= beg) |
|
312
|
6
|
|
|
|
|
|
lucky[nlucky++] = l; |
|
313
|
|
|
|
|
|
|
} |
|
314
|
1
|
|
|
|
|
|
bitmask126_destroy(pl); |
|
315
|
1
|
|
|
|
|
|
*size = nlucky; |
|
316
|
1
|
|
|
|
|
|
return lucky; |
|
317
|
|
|
|
|
|
|
} |
|
318
|
|
|
|
|
|
|
|
|
319
|
|
|
|
|
|
|
|
|
320
|
|
|
|
|
|
|
/* Lucky Number sieve for 64-bit inputs. |
|
321
|
|
|
|
|
|
|
* Uses running counters to skip entries while we add them. |
|
322
|
|
|
|
|
|
|
* Based substantially on Hugo van der Sanden's cgen_lucky.c. |
|
323
|
|
|
|
|
|
|
*/ |
|
324
|
0
|
|
|
|
|
|
UV* lucky_sieve_cgen(UV *size, UV n) { |
|
325
|
|
|
|
|
|
|
UV i, j, c3, lsize, lmax, lindex, *lucky, *count; |
|
326
|
|
|
|
|
|
|
|
|
327
|
0
|
0
|
|
|
|
|
if (n == 0) { *size = 0; return 0; } |
|
328
|
|
|
|
|
|
|
|
|
329
|
|
|
|
|
|
|
/* Init */ |
|
330
|
0
|
0
|
|
|
|
|
lmax = (n < 1000) ? 153 : 100 + n/log(n); |
|
331
|
0
|
0
|
|
|
|
|
New(0, lucky, lmax, UV); |
|
332
|
0
|
0
|
|
|
|
|
New(0, count, lmax, UV); |
|
333
|
0
|
|
|
|
|
|
lucky[0] = 1; |
|
334
|
0
|
|
|
|
|
|
lucky[1] = 3; |
|
335
|
0
|
|
|
|
|
|
lucky[2] = 7; |
|
336
|
0
|
|
|
|
|
|
lindex = 2; |
|
337
|
0
|
|
|
|
|
|
lsize = 1; |
|
338
|
0
|
|
|
|
|
|
c3 = 2; |
|
339
|
|
|
|
|
|
|
|
|
340
|
0
|
0
|
|
|
|
|
for (i = 3; i <= n; i += 2) { |
|
341
|
0
|
0
|
|
|
|
|
if (!--c3) { c3 = 3; continue; } /* Shortcut count[1] */ |
|
342
|
0
|
0
|
|
|
|
|
for (j = 2; j < lindex; j++) { |
|
343
|
0
|
0
|
|
|
|
|
if (--count[j] == 0) { |
|
344
|
0
|
|
|
|
|
|
count[j] = lucky[j]; |
|
345
|
0
|
|
|
|
|
|
break; |
|
346
|
|
|
|
|
|
|
} |
|
347
|
|
|
|
|
|
|
} |
|
348
|
0
|
0
|
|
|
|
|
if (j < lindex) continue; |
|
349
|
|
|
|
|
|
|
|
|
350
|
0
|
0
|
|
|
|
|
if (lsize >= lmax) { /* Given the estimate, we probably never do this. */ |
|
351
|
0
|
|
|
|
|
|
lmax = 1 + lsize * 1.2; |
|
352
|
0
|
0
|
|
|
|
|
Renew(lucky, lmax, UV); |
|
353
|
0
|
0
|
|
|
|
|
Renew(count, lmax, UV); |
|
354
|
|
|
|
|
|
|
} |
|
355
|
0
|
|
|
|
|
|
lucky[lsize] = count[lsize] = i; |
|
356
|
0
|
|
|
|
|
|
lsize++; |
|
357
|
|
|
|
|
|
|
|
|
358
|
0
|
0
|
|
|
|
|
if (lucky[lindex] == lsize) { |
|
359
|
0
|
|
|
|
|
|
lindex++; lsize--; /* Discard immediately */ |
|
360
|
|
|
|
|
|
|
} |
|
361
|
|
|
|
|
|
|
} |
|
362
|
0
|
|
|
|
|
|
Safefree(count); |
|
363
|
0
|
|
|
|
|
|
*size = lsize; |
|
364
|
0
|
|
|
|
|
|
return lucky; |
|
365
|
|
|
|
|
|
|
} |
|
366
|
|
|
|
|
|
|
|
|
367
|
|
|
|
|
|
|
/******************************************************************************/ |
|
368
|
|
|
|
|
|
|
|
|
369
|
|
|
|
|
|
|
/* static UV lucky_count_approx(UV n) { return 0.5 + 0.970 * n / log(n); } */ |
|
370
|
|
|
|
|
|
|
/* static UV lucky_count_upper(UV n) { return 200 + lucky_count_approx(n) * 1.025; } */ |
|
371
|
|
|
|
|
|
|
|
|
372
|
26
|
|
|
|
|
|
static UV _simple_lucky_count_approx(UV n) { |
|
373
|
26
|
|
|
|
|
|
double logn = log(n); |
|
374
|
0
|
|
|
|
|
|
return (n < 7) ? (n > 0) + (n > 2) |
|
375
|
52
|
50
|
|
|
|
|
: (n <= 10000) ? 1.03591 * n/logn |
|
|
|
50
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
376
|
21
|
|
|
|
|
|
: (n <= 1000000) ? 0.99575 * n/logn |
|
377
|
2
|
|
|
|
|
|
: (n <= 10000000) ? (1.03523 - logn/305) * n/logn |
|
378
|
0
|
|
|
|
|
|
: (n <= 100000000) ? (1.03432 - logn/304) * n/logn |
|
379
|
0
|
|
|
|
|
|
: (n <= 4000000000U) ? (1.03613 - logn/(100*log(logn))) * n/logn |
|
380
|
|
|
|
|
|
|
/* fit 1e9 to 1e10 */ |
|
381
|
3
|
|
|
|
|
|
: (1.03654 - logn/(100*log(logn))) * n/logn; |
|
382
|
|
|
|
|
|
|
} |
|
383
|
1164
|
|
|
|
|
|
static UV _simple_lucky_count_upper(UV n) { |
|
384
|
1164
|
|
|
|
|
|
double a, logn = log(n); |
|
385
|
1164
|
50
|
|
|
|
|
if (n <= 6) return (n > 0) + (n > 2); |
|
386
|
1164
|
100
|
|
|
|
|
if (n <= 7000) return 5 + 1.039 * n/logn; |
|
387
|
|
|
|
|
|
|
|
|
388
|
|
|
|
|
|
|
/* Don't make discontinities */ |
|
389
|
53
|
100
|
|
|
|
|
a = (n < 10017000) ? 0.58003 - 3.00e-9 * (n-7000) : 0.55; |
|
390
|
53
|
|
|
|
|
|
return n/(1.065*logn - a - 3.1/logn - 2.85/(logn*logn)); |
|
391
|
|
|
|
|
|
|
} |
|
392
|
134
|
|
|
|
|
|
static UV _simple_lucky_count_lower(UV n) { |
|
393
|
134
|
50
|
|
|
|
|
if (n <= 6) return (n > 0) + (n > 2); |
|
394
|
134
|
100
|
|
|
|
|
if (n <= 9000) return 1.028 * n/log(n) - 1; |
|
395
|
26
|
|
|
|
|
|
return 0.99 * _simple_lucky_count_approx(n); |
|
396
|
|
|
|
|
|
|
} |
|
397
|
|
|
|
|
|
|
|
|
398
|
114
|
|
|
|
|
|
UV lucky_count_approx(UV n) { |
|
399
|
|
|
|
|
|
|
UV lo, hi; |
|
400
|
114
|
100
|
|
|
|
|
if (n < 48) return _small_lucky_count[n]; |
|
401
|
|
|
|
|
|
|
/* return _simple_lucky_count_approx(n); */ |
|
402
|
66
|
|
|
|
|
|
lo = _simple_lucky_count_lower(n); |
|
403
|
66
|
|
|
|
|
|
hi = _simple_lucky_count_upper(n); |
|
404
|
66
|
|
|
|
|
|
return inverse_interpolate(lo, hi, n, &nth_lucky_approx, 0); |
|
405
|
|
|
|
|
|
|
} |
|
406
|
1133
|
|
|
|
|
|
UV lucky_count_upper(UV n) { /* Holds under 1e9 */ |
|
407
|
|
|
|
|
|
|
UV lo, hi; |
|
408
|
1133
|
100
|
|
|
|
|
if (n < 48) return _small_lucky_count[n]; |
|
409
|
|
|
|
|
|
|
/* The count estimator is better than nth lucky estimator for small values */ |
|
410
|
1085
|
100
|
|
|
|
|
if (n < 40000000) return _simple_lucky_count_upper(n); |
|
411
|
|
|
|
|
|
|
#if 1 && BITS_PER_WORD == 64 |
|
412
|
1
|
50
|
|
|
|
|
if (n > UVCONST(18428297000000000000)) |
|
413
|
0
|
|
|
|
|
|
return _simple_lucky_count_upper(n); |
|
414
|
|
|
|
|
|
|
#endif |
|
415
|
1
|
|
|
|
|
|
lo = _simple_lucky_count_lower(n); |
|
416
|
1
|
|
|
|
|
|
hi = 1 + (_simple_lucky_count_upper(n) * 1.001); |
|
417
|
1
|
|
|
|
|
|
return inverse_interpolate(lo, hi, n, &nth_lucky_lower, 0); |
|
418
|
|
|
|
|
|
|
} |
|
419
|
115
|
|
|
|
|
|
UV lucky_count_lower(UV n) { /* Holds under 1e9 */ |
|
420
|
|
|
|
|
|
|
UV lo, hi; |
|
421
|
115
|
100
|
|
|
|
|
if (n < 48) return _small_lucky_count[n]; |
|
422
|
67
|
100
|
|
|
|
|
if (n < 9000) return _simple_lucky_count_lower(n); |
|
423
|
13
|
|
|
|
|
|
lo = _simple_lucky_count_lower(n); |
|
424
|
13
|
|
|
|
|
|
hi = _simple_lucky_count_upper(n); |
|
425
|
13
|
|
|
|
|
|
return inverse_interpolate(lo, hi, n, &nth_lucky_upper, 0); |
|
426
|
|
|
|
|
|
|
} |
|
427
|
1960
|
|
|
|
|
|
UV lucky_count_range(UV lo, UV hi) { |
|
428
|
|
|
|
|
|
|
UV nlucky, lsize; |
|
429
|
|
|
|
|
|
|
|
|
430
|
1960
|
50
|
|
|
|
|
if (hi < lo) |
|
431
|
0
|
|
|
|
|
|
return 0; |
|
432
|
1960
|
100
|
|
|
|
|
if (hi < 48) |
|
433
|
957
|
100
|
|
|
|
|
return _small_lucky_count[hi] - (lo == 0 ? 0 : _small_lucky_count[lo-1]); |
|
434
|
|
|
|
|
|
|
|
|
435
|
|
|
|
|
|
|
/* |
|
436
|
|
|
|
|
|
|
* Analogous to how nth_lucky works, we sieve enough lucky numbers to |
|
437
|
|
|
|
|
|
|
* ensure we cover everything up to 'hi'. We can then get an exact |
|
438
|
|
|
|
|
|
|
* count by determining exactly how many values will be removed. |
|
439
|
|
|
|
|
|
|
*/ |
|
440
|
|
|
|
|
|
|
|
|
441
|
1003
|
50
|
|
|
|
|
if ((lo & 1)) lo--; /* Both lo and hi will be even */ |
|
442
|
1003
|
100
|
|
|
|
|
if ((hi & 1)) hi++; |
|
443
|
1003
|
|
|
|
|
|
lsize = 1+lucky_count_upper(hi); |
|
444
|
|
|
|
|
|
|
|
|
445
|
1003
|
50
|
|
|
|
|
if (hi <= UVCONST(2000000000)) { |
|
446
|
1003
|
|
|
|
|
|
uint32_t i, hicount = hi/2, locount = lo/2; |
|
447
|
1003
|
|
|
|
|
|
uint32_t *lucky32 = lucky_sieve32(&nlucky, lsize); |
|
448
|
1003
|
50
|
|
|
|
|
for (i = 1; i < nlucky && lucky32[i] <= lo; i++) { |
|
|
|
50
|
|
|
|
|
|
|
449
|
0
|
|
|
|
|
|
locount -= locount/lucky32[i]; |
|
450
|
0
|
|
|
|
|
|
hicount -= hicount/lucky32[i]; |
|
451
|
|
|
|
|
|
|
} |
|
452
|
19304
|
100
|
|
|
|
|
for ( ; i < nlucky && lucky32[i] <= hicount; i++) |
|
|
|
100
|
|
|
|
|
|
|
453
|
18301
|
|
|
|
|
|
hicount -= hicount/lucky32[i]; |
|
454
|
1003
|
|
|
|
|
|
Safefree(lucky32); |
|
455
|
1003
|
|
|
|
|
|
return hicount - locount; |
|
456
|
|
|
|
|
|
|
} else { |
|
457
|
|
|
|
|
|
|
/* We use the iterator here to cut down on memory use. */ |
|
458
|
0
|
|
|
|
|
|
UV i, hicount = hi/2, locount = lo/2; |
|
459
|
0
|
|
|
|
|
|
bitmask126_t* pl = _bitmask126_sieve(&nlucky, lsize); |
|
460
|
0
|
|
|
|
|
|
bitmask126_iter_t iter = bitmask126_iterator_create(pl, 1); |
|
461
|
0
|
0
|
|
|
|
|
for (i = 1; i < nlucky; i++) { |
|
462
|
0
|
|
|
|
|
|
UV l = bitmask126_iterator_next(&iter); |
|
463
|
0
|
0
|
|
|
|
|
if (l <= lo) locount -= locount/l; |
|
464
|
0
|
0
|
|
|
|
|
if (l > hicount) break; |
|
465
|
0
|
|
|
|
|
|
hicount -= hicount/l; |
|
466
|
|
|
|
|
|
|
} |
|
467
|
0
|
|
|
|
|
|
bitmask126_destroy(pl); |
|
468
|
0
|
|
|
|
|
|
return hicount - locount; |
|
469
|
|
|
|
|
|
|
} |
|
470
|
|
|
|
|
|
|
} |
|
471
|
0
|
|
|
|
|
|
UV lucky_count(UV n) { |
|
472
|
0
|
|
|
|
|
|
return lucky_count_range(0,n); |
|
473
|
|
|
|
|
|
|
} |
|
474
|
|
|
|
|
|
|
|
|
475
|
628
|
|
|
|
|
|
UV nth_lucky_approx(UV n) { |
|
476
|
|
|
|
|
|
|
double est, corr, fn, logn, loglogn, loglogn2; |
|
477
|
628
|
100
|
|
|
|
|
if (n <= 48) return (n == 0) ? 0 : _small_lucky[n-1]; |
|
|
|
50
|
|
|
|
|
|
|
478
|
396
|
|
|
|
|
|
fn = n; logn = log(fn); loglogn = log(logn); loglogn2 = loglogn * loglogn; |
|
479
|
|
|
|
|
|
|
|
|
480
|
|
|
|
|
|
|
/* Use interpolation so we have monotonic growth, as well as good results. |
|
481
|
|
|
|
|
|
|
* We use one formula for small values, and another for larger. */ |
|
482
|
|
|
|
|
|
|
|
|
483
|
|
|
|
|
|
|
/* p1=1<<14; e1=199123; p2=1<<16; e2=904225; |
|
484
|
|
|
|
|
|
|
* x1=log(log(p1))^2; x2=log(log(p2))^2; y1=(e1/p1-log(p1)-0.5*log(log(p1)))/x1; y2=(e2/p2-log(p2)-0.5*log(log(p2)))/x2; m=(y2-y1)/(x2-x1); printf(" corr = %13.11f + %.11f * (loglogn2 - %.11f);\n", y1, m, x1); |
|
485
|
|
|
|
|
|
|
*/ |
|
486
|
396
|
100
|
|
|
|
|
if (n <= 65536) { |
|
487
|
294
|
100
|
|
|
|
|
if (n >= 16384) /* 16384 -- 65536 */ |
|
488
|
38
|
|
|
|
|
|
corr = 0.25427076035 + 0.00883698771 * (loglogn2 - 5.16445809103); |
|
489
|
256
|
100
|
|
|
|
|
else if (n >= 2048) /* 2048 -- 16384 */ |
|
490
|
28
|
|
|
|
|
|
corr = 0.24513311782 + 0.00880360023 * (loglogn2 - 4.12651426090); |
|
491
|
228
|
100
|
|
|
|
|
else if (n >= 256) /* 256 -- 2048 */ |
|
492
|
12
|
|
|
|
|
|
corr = 0.25585213066 - 0.00898952075 * (loglogn2 - 2.93412446098); |
|
493
|
|
|
|
|
|
|
else /* 49 -- 256 */ |
|
494
|
216
|
|
|
|
|
|
corr = 0.38691439589 - 0.12050840608 * (loglogn2 - 1.84654667704); |
|
495
|
294
|
|
|
|
|
|
est = fn * (logn + 0.5*loglogn + corr*loglogn2) + 0.5; |
|
496
|
|
|
|
|
|
|
} else { |
|
497
|
|
|
|
|
|
|
/* p1=1<<32; e1=113924214621; p2=1<<37; e2=4176793875529; |
|
498
|
|
|
|
|
|
|
* x1=log(log(p1))^2; x2=log(log(p2))^2; y1=(e1/p1-log(p1)-0.5*x1)/x1; y2=(e2/p2-log(p2)-0.5*x2)/x2; m=(y2-y1)/(x2-x1); printf(" corr = %13.11f + %.11f * (loglogn2 - %.11f);\n", y1, m, x1); |
|
499
|
|
|
|
|
|
|
*/ |
|
500
|
102
|
100
|
|
|
|
|
if (fn >= 1099511627776.0) /* 2^40 -- 2^43 */ |
|
501
|
28
|
|
|
|
|
|
corr = -0.05012215934 - 0.00139445216 * (loglogn2 - 11.03811938314); |
|
502
|
74
|
50
|
|
|
|
|
else if (fn >= 68719476736.0) /* 2^36 -- 2^40 */ |
|
503
|
0
|
|
|
|
|
|
corr = -0.04904974983 - 0.00155649126 * (loglogn2 - 10.34912771904); |
|
504
|
74
|
50
|
|
|
|
|
else if (fn >= 4294967296.0) /* 2^32 -- 2^36 */ |
|
505
|
0
|
|
|
|
|
|
corr = -0.04770894029 - 0.00180229750 * (loglogn2 - 9.60518309351); |
|
506
|
74
|
100
|
|
|
|
|
else if (fn >= 67108864) /* 2^26 -- 2^32 */ |
|
507
|
4
|
|
|
|
|
|
corr = -0.04484819198 - 0.00229977135 * (loglogn2 - 8.36125581665); |
|
508
|
70
|
100
|
|
|
|
|
else if (fn >= 1048576) /* 2^20 -- 2^26 */ |
|
509
|
8
|
|
|
|
|
|
corr = -0.03971615189 - 0.00354309756 * (loglogn2 - 6.91279440604); |
|
510
|
62
|
50
|
|
|
|
|
else if (n >= 65536) /* 2^16 -- 2^20 */ |
|
511
|
62
|
|
|
|
|
|
corr = -0.03240114452 - 0.00651036735 * (loglogn2 - 5.78920076332); |
|
512
|
0
|
0
|
|
|
|
|
else if (n >= 512) /* 2^9 -- 2^16 */ |
|
513
|
0
|
|
|
|
|
|
corr = 0.00990254026 - 0.01735396532 * (loglogn2 - 3.35150517018); |
|
514
|
|
|
|
|
|
|
else /* 2^6 -- 2^9 */ |
|
515
|
0
|
|
|
|
|
|
corr = 0.13714087150 - 0.09637971899 * (loglogn2 - 2.03132772443); |
|
516
|
|
|
|
|
|
|
/* Hawkins and Briggs (1958), attributed to S. Chowla. */ |
|
517
|
102
|
|
|
|
|
|
est = fn * (logn + (0.5+corr)*loglogn2) + 0.5; |
|
518
|
|
|
|
|
|
|
} |
|
519
|
396
|
50
|
|
|
|
|
if (est >= MPU_MAX_LUCKY) return MPU_MAX_LUCKY; |
|
520
|
396
|
|
|
|
|
|
return (UV)est; |
|
521
|
|
|
|
|
|
|
} |
|
522
|
171
|
|
|
|
|
|
UV nth_lucky_upper(UV n) { |
|
523
|
|
|
|
|
|
|
double est, corr; |
|
524
|
171
|
100
|
|
|
|
|
if (n <= 48) return (n == 0) ? 0 : _small_lucky[n-1]; |
|
|
|
50
|
|
|
|
|
|
|
525
|
193
|
100
|
|
|
|
|
corr = (n <= 1000) ? 1.01 : |
|
526
|
70
|
100
|
|
|
|
|
(n <= 8200) ? 1.005 : |
|
527
|
|
|
|
|
|
|
1.001; /* verified to n=3e9 / v=1e11 */ |
|
528
|
123
|
|
|
|
|
|
est = corr * nth_lucky_approx(n) + 0.5; |
|
529
|
123
|
50
|
|
|
|
|
if (est >= MPU_MAX_LUCKY) return MPU_MAX_LUCKY; |
|
530
|
123
|
|
|
|
|
|
return (UV)est; |
|
531
|
|
|
|
|
|
|
} |
|
532
|
122
|
|
|
|
|
|
UV nth_lucky_lower(UV n) { |
|
533
|
|
|
|
|
|
|
double est, corr; |
|
534
|
122
|
100
|
|
|
|
|
if (n <= 48) return (n == 0) ? 0 : _small_lucky[n-1]; |
|
|
|
50
|
|
|
|
|
|
|
535
|
74
|
|
|
|
|
|
est = nth_lucky_approx(n); |
|
536
|
95
|
100
|
|
|
|
|
corr = (n <= 122) ? 0.95 : |
|
537
|
40
|
100
|
|
|
|
|
(n <= 4096) ? 0.97 : |
|
538
|
19
|
100
|
|
|
|
|
(n <= 115000) ? 0.998 : |
|
539
|
|
|
|
|
|
|
0.999 ; /* verified to n=3e9 / v=1e11 */ |
|
540
|
74
|
|
|
|
|
|
est = corr * nth_lucky_approx(n); |
|
541
|
74
|
|
|
|
|
|
return (UV)est; |
|
542
|
|
|
|
|
|
|
} |
|
543
|
|
|
|
|
|
|
|
|
544
|
164
|
|
|
|
|
|
UV nth_lucky(UV n) { |
|
545
|
|
|
|
|
|
|
UV i, k, nlucky; |
|
546
|
|
|
|
|
|
|
|
|
547
|
164
|
100
|
|
|
|
|
if (n <= 48) return (n == 0) ? 0 : _small_lucky[n-1]; |
|
|
|
50
|
|
|
|
|
|
|
548
|
|
|
|
|
|
|
|
|
549
|
|
|
|
|
|
|
/* Apply the backward sieve, ala Wilson, for entry n */ |
|
550
|
116
|
50
|
|
|
|
|
if (n <= UVCONST(100000000)) { |
|
551
|
116
|
|
|
|
|
|
uint32_t *lucky32 = lucky_sieve32(&nlucky, n); |
|
552
|
38635
|
100
|
|
|
|
|
for (i = nlucky-1, k = n-1; i >= 1; i--) |
|
553
|
38519
|
|
|
|
|
|
k += k/(lucky32[i]-1); |
|
554
|
116
|
|
|
|
|
|
Safefree(lucky32); |
|
555
|
|
|
|
|
|
|
} else { /* Iterate backwards through the sieve directly to save memory. */ |
|
556
|
0
|
|
|
|
|
|
bitmask126_t* pl = _bitmask126_sieve(&nlucky, n); |
|
557
|
0
|
|
|
|
|
|
bitmask126_iter_t iter = bitmask126_iterator_create(pl, nlucky-1); |
|
558
|
0
|
0
|
|
|
|
|
for (i = nlucky-1, k = n-1; i >= 1; i--) |
|
559
|
0
|
|
|
|
|
|
k += k / (bitmask126_iterator_prev(&iter) - 1); |
|
560
|
0
|
|
|
|
|
|
bitmask126_destroy(pl); |
|
561
|
|
|
|
|
|
|
} |
|
562
|
116
|
|
|
|
|
|
return (2 * k + 1); |
|
563
|
|
|
|
|
|
|
} |
|
564
|
|
|
|
|
|
|
|
|
565
|
|
|
|
|
|
|
|
|
566
|
42
|
|
|
|
|
|
static int _test_lucky_to(UV lsize, UV *beg, UV *end) { |
|
567
|
42
|
|
|
|
|
|
UV i = *beg, pos = *end, l, quo, nlucky; |
|
568
|
42
|
|
|
|
|
|
int ret = -1; |
|
569
|
|
|
|
|
|
|
|
|
570
|
42
|
50
|
|
|
|
|
if (lsize <= 700000000U) { |
|
571
|
42
|
|
|
|
|
|
uint32_t *lucky32 = lucky_sieve32(&nlucky, lsize); |
|
572
|
89563
|
100
|
|
|
|
|
while (i < nlucky) { |
|
573
|
89536
|
|
|
|
|
|
l = lucky32[i++]; |
|
574
|
89536
|
100
|
|
|
|
|
if (pos < l) { ret = 1; break; } |
|
575
|
89523
|
|
|
|
|
|
quo = pos / l; |
|
576
|
89523
|
100
|
|
|
|
|
if (pos == quo*l) { ret = 0; break; } |
|
577
|
89521
|
|
|
|
|
|
pos -= quo; |
|
578
|
|
|
|
|
|
|
} |
|
579
|
42
|
|
|
|
|
|
Safefree(lucky32); |
|
580
|
|
|
|
|
|
|
} else { |
|
581
|
|
|
|
|
|
|
/* For 64-bit, iterate directly through the bit-mask to save memory. */ |
|
582
|
0
|
|
|
|
|
|
bitmask126_t* pl = _bitmask126_sieve(&nlucky, lsize); |
|
583
|
0
|
0
|
|
|
|
|
if (i < nlucky) { |
|
584
|
0
|
|
|
|
|
|
bitmask126_iter_t iter = bitmask126_iterator_create(pl, i); |
|
585
|
0
|
0
|
|
|
|
|
while (i < nlucky) { |
|
586
|
0
|
|
|
|
|
|
l = bitmask126_iterator_next(&iter); |
|
587
|
0
|
|
|
|
|
|
i++; |
|
588
|
0
|
0
|
|
|
|
|
if (pos < l) { ret = 1; break; } |
|
589
|
0
|
|
|
|
|
|
quo = pos / l; |
|
590
|
0
|
0
|
|
|
|
|
if (pos == quo*l) { ret = 0; break; } |
|
591
|
0
|
|
|
|
|
|
pos -= quo; |
|
592
|
|
|
|
|
|
|
} |
|
593
|
|
|
|
|
|
|
} |
|
594
|
0
|
|
|
|
|
|
bitmask126_destroy(pl); |
|
595
|
|
|
|
|
|
|
} |
|
596
|
|
|
|
|
|
|
/* printf("tested lsize = %lu from %lu to %lu\n", lsize, *beg, i-1); */ |
|
597
|
42
|
|
|
|
|
|
*beg = i; |
|
598
|
42
|
|
|
|
|
|
*end = pos; |
|
599
|
42
|
|
|
|
|
|
return ret; |
|
600
|
|
|
|
|
|
|
} |
|
601
|
|
|
|
|
|
|
|
|
602
|
218
|
|
|
|
|
|
bool is_lucky(UV n) { |
|
603
|
|
|
|
|
|
|
UV i, l, quo, pos, lsize; |
|
604
|
|
|
|
|
|
|
int res; |
|
605
|
|
|
|
|
|
|
|
|
606
|
|
|
|
|
|
|
/* Simple pre-tests */ |
|
607
|
218
|
100
|
|
|
|
|
if ( !(n & 1) || (n%6) == 5 || !_lmask63[n % 63]) return 0; |
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
608
|
69
|
100
|
|
|
|
|
if (n < 45) return 1; |
|
609
|
57
|
50
|
|
|
|
|
if (n > MPU_MAX_LUCKY) return 0; |
|
610
|
|
|
|
|
|
|
|
|
611
|
|
|
|
|
|
|
/* Check valid position using the static list */ |
|
612
|
57
|
|
|
|
|
|
pos = (n+1) >> 1; /* Initial position in odds */ |
|
613
|
|
|
|
|
|
|
|
|
614
|
1078
|
100
|
|
|
|
|
for (i = 1; i < 48; i++) { |
|
615
|
1062
|
|
|
|
|
|
l = _small_lucky[i]; |
|
616
|
1062
|
100
|
|
|
|
|
if (pos < l) return 1; |
|
617
|
1035
|
|
|
|
|
|
quo = pos / l; |
|
618
|
1035
|
100
|
|
|
|
|
if (pos == quo*l) return 0; |
|
619
|
1021
|
|
|
|
|
|
pos -= quo; |
|
620
|
|
|
|
|
|
|
} |
|
621
|
|
|
|
|
|
|
|
|
622
|
16
|
|
|
|
|
|
lsize = 1+lucky_count_upper(n); |
|
623
|
|
|
|
|
|
|
|
|
624
|
|
|
|
|
|
|
{ /* Check more small values */ |
|
625
|
16
|
|
|
|
|
|
UV psize = 600, gfac = 6; |
|
626
|
42
|
100
|
|
|
|
|
while (psize < lsize/3) { |
|
627
|
27
|
|
|
|
|
|
res = _test_lucky_to(psize, &i, &pos); |
|
628
|
27
|
100
|
|
|
|
|
if (res != -1) return res; |
|
629
|
26
|
|
|
|
|
|
psize *= gfac; |
|
630
|
26
|
|
|
|
|
|
gfac += 1; |
|
631
|
|
|
|
|
|
|
} |
|
632
|
|
|
|
|
|
|
} |
|
633
|
15
|
|
|
|
|
|
res = _test_lucky_to(lsize, &i, &pos); |
|
634
|
15
|
|
|
|
|
|
return (res == 0) ? 0 : 1; |
|
635
|
|
|
|
|
|
|
} |