| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
/******************************************************************************/ |
|
2
|
|
|
|
|
|
|
/* ALMOST PRIMES */ |
|
3
|
|
|
|
|
|
|
/******************************************************************************/ |
|
4
|
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
#include |
|
6
|
|
|
|
|
|
|
#include |
|
7
|
|
|
|
|
|
|
#include |
|
8
|
|
|
|
|
|
|
#include |
|
9
|
|
|
|
|
|
|
#include "ptypes.h" |
|
10
|
|
|
|
|
|
|
#include "constants.h" |
|
11
|
|
|
|
|
|
|
#define FUNC_isqrt 1 |
|
12
|
|
|
|
|
|
|
#define FUNC_ctz 1 |
|
13
|
|
|
|
|
|
|
#include "sort.h" |
|
14
|
|
|
|
|
|
|
#include "cache.h" |
|
15
|
|
|
|
|
|
|
#include "sieve.h" |
|
16
|
|
|
|
|
|
|
#include "util.h" |
|
17
|
|
|
|
|
|
|
#include "prime_counts.h" |
|
18
|
|
|
|
|
|
|
#include "prime_count_cache.h" |
|
19
|
|
|
|
|
|
|
#include "semi_primes.h" |
|
20
|
|
|
|
|
|
|
#include "inverse_interpolate.h" |
|
21
|
|
|
|
|
|
|
#include "almost_primes.h" |
|
22
|
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
/******************************************************************************/ |
|
24
|
|
|
|
|
|
|
/* KAP UTILITY */ |
|
25
|
|
|
|
|
|
|
/******************************************************************************/ |
|
26
|
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
#if BITS_PER_WORD == 32 |
|
28
|
|
|
|
|
|
|
static uint32_t const _pow3[21] = {1,3,9,27,81,243,729,2187,6561,19683,59049,177147,531441,1594323,4782969,14348907,43046721,129140163,387420489,1162261467,3486784401U}; |
|
29
|
|
|
|
|
|
|
#else |
|
30
|
|
|
|
|
|
|
static UV const _pow3[41] = {1,3,9,27,81,243,729,2187,6561,19683,59049,177147,531441,1594323,4782969,14348907,43046721,129140163,387420489,1162261467,3486784401U,UVCONST(10460353203),UVCONST(31381059609),UVCONST(94143178827),UVCONST(282429536481),UVCONST(847288609443),UVCONST(2541865828329),UVCONST(7625597484987),UVCONST(22876792454961),UVCONST(68630377364883),UVCONST(205891132094649),UVCONST(617673396283947),UVCONST(1853020188851841),UVCONST(5559060566555523),UVCONST(16677181699666569),UVCONST(50031545098999707),UVCONST(150094635296999121),UVCONST(450283905890997363),UVCONST(1350851717672992089),UVCONST(4052555153018976267),UVCONST(12157665459056928801)}; |
|
31
|
|
|
|
|
|
|
#endif |
|
32
|
|
|
|
|
|
|
#define A078843_MAX_K 49 |
|
33
|
|
|
|
|
|
|
static const uint32_t _first_3[A078843_MAX_K+1] = {1, 2, 3, 5, 8, 14, 23, 39, 64, 103, 169, 269, 427, 676, 1065, 1669, 2628, 4104, 6414, 10023, 15608, 24281, 37733, 58503, 90616, 140187, 216625, 334527, 516126, 795632, 1225641, 1886570, 2901796, 4460359, 6851532, 10518476, 16138642, 24748319, 37932129, 58110457, 88981343, 136192537, 208364721, 318653143, 487128905, 744398307, 1137129971, 1736461477, 2650785552U, 4045250962U}; |
|
34
|
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
/* For all n <= hi, we can get the same results using 2*result with lower k */ |
|
36
|
3
|
|
|
|
|
|
static uint32_t reduce_k_for_n(uint32_t k, UV n) { |
|
37
|
3
|
|
|
|
|
|
uint32_t r = 0; |
|
38
|
3
|
50
|
|
|
|
|
if (k <= 1 || k >= BITS_PER_WORD) return 0; |
|
|
|
50
|
|
|
|
|
|
|
39
|
3
|
50
|
|
|
|
|
if (k > MPU_MAX_POW3) /* Larger n would not fit in a UV type */ |
|
40
|
0
|
|
|
|
|
|
r = k-MPU_MAX_POW3; |
|
41
|
3
|
50
|
|
|
|
|
while ((k-r) > 1 && (n>>r) < _pow3[k-r]) |
|
|
|
50
|
|
|
|
|
|
|
42
|
0
|
|
|
|
|
|
r++; |
|
43
|
3
|
|
|
|
|
|
return r; |
|
44
|
|
|
|
|
|
|
} |
|
45
|
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
/* Least r s.t. almost_prime_count(k, n) = almost_prime_count(k-r, n >> r) */ |
|
47
|
555
|
|
|
|
|
|
static void reduce_prime_count_factor(uint32_t *pk, UV *n) { |
|
48
|
555
|
|
|
|
|
|
uint32_t k = *pk, r = 0; |
|
49
|
555
|
50
|
|
|
|
|
if (k > MPU_MAX_POW3) /* Larger n would not fit in a UV type */ |
|
50
|
0
|
|
|
|
|
|
r = k-MPU_MAX_POW3; |
|
51
|
1903
|
50
|
|
|
|
|
while (k >= r && ((*n)>>r) < _pow3[k-r]) |
|
|
|
100
|
|
|
|
|
|
|
52
|
1348
|
|
|
|
|
|
r++; |
|
53
|
|
|
|
|
|
|
/* Reduce */ |
|
54
|
555
|
100
|
|
|
|
|
if (r > 0) { |
|
55
|
84
|
|
|
|
|
|
*pk -= r; |
|
56
|
84
|
|
|
|
|
|
*n >>= r; |
|
57
|
|
|
|
|
|
|
} |
|
58
|
555
|
|
|
|
|
|
} |
|
59
|
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
/* Least r s.t. nth_almost_prime(k,n) = nth_almost_prime(k-r,n) << r */ |
|
61
|
24
|
|
|
|
|
|
static uint32_t reduce_nth_factor(uint32_t k, UV n) { |
|
62
|
24
|
|
|
|
|
|
uint32_t r = 0; |
|
63
|
24
|
50
|
|
|
|
|
if (k <= 1 || k >= BITS_PER_WORD) return 0; |
|
|
|
50
|
|
|
|
|
|
|
64
|
24
|
50
|
|
|
|
|
if (k > A078843_MAX_K) { |
|
65
|
0
|
0
|
|
|
|
|
if (n >= _first_3[A078843_MAX_K]) |
|
66
|
0
|
|
|
|
|
|
return 0; |
|
67
|
0
|
|
|
|
|
|
r = k-A078843_MAX_K+1; |
|
68
|
|
|
|
|
|
|
} |
|
69
|
115
|
100
|
|
|
|
|
while (n < _first_3[k-r]) |
|
70
|
91
|
|
|
|
|
|
r++; |
|
71
|
24
|
|
|
|
|
|
return r; |
|
72
|
|
|
|
|
|
|
} |
|
73
|
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
/* This could be easily extended to 16 or 32 */ |
|
76
|
2
|
|
|
|
|
|
static UV _fast_small_nth_almost_prime(uint32_t k, UV n) { |
|
77
|
|
|
|
|
|
|
static const uint8_t semi[8] = {0, 4, 6, 9, 10, 14, 15, 21}; |
|
78
|
|
|
|
|
|
|
static const uint8_t mult[8] = {0, 8, 12, 18, 20, 27, 28, 30}; |
|
79
|
2
|
50
|
|
|
|
|
MPUassert(n < 8 && k >= 2, "Fast small nth almost prime out of range"); |
|
|
|
50
|
|
|
|
|
|
|
80
|
2
|
50
|
|
|
|
|
if (k == 2) return semi[n]; |
|
81
|
2
|
|
|
|
|
|
return mult[n] * (UVCONST(1) << (k-3)); |
|
82
|
|
|
|
|
|
|
} |
|
83
|
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
static void _almost_prime_count_bounds(UV *lower, UV *upper, uint32_t k, UV n); |
|
85
|
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
#if 0 /* Not currently used */ |
|
87
|
|
|
|
|
|
|
/* Somewhere around k=20 it is faster to do: |
|
88
|
|
|
|
|
|
|
* return nth_almost_prime(h, 1+almost_prime_count(k,n)); |
|
89
|
|
|
|
|
|
|
*/ |
|
90
|
|
|
|
|
|
|
static UV _next_almost_prime(uint32_t k, UV n) { |
|
91
|
|
|
|
|
|
|
while (!is_almost_prime(k, ++n)) |
|
92
|
|
|
|
|
|
|
; |
|
93
|
|
|
|
|
|
|
return n; |
|
94
|
|
|
|
|
|
|
} |
|
95
|
|
|
|
|
|
|
static UV _prev_almost_semiprime(uint32_t k, UV n) { |
|
96
|
|
|
|
|
|
|
while (!is_almost_prime(k, --n)) |
|
97
|
|
|
|
|
|
|
; |
|
98
|
|
|
|
|
|
|
return n; |
|
99
|
|
|
|
|
|
|
} |
|
100
|
|
|
|
|
|
|
#endif |
|
101
|
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
/******************************************************************************/ |
|
104
|
|
|
|
|
|
|
/* KAP COUNT */ |
|
105
|
|
|
|
|
|
|
/******************************************************************************/ |
|
106
|
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
#define CACHED_PC(cache,n) prime_count_cache_lookup(cache,n) |
|
108
|
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
/* Debatably useful. Slightly faster for small n, the same for larger. */ |
|
110
|
4
|
|
|
|
|
|
static UV almost3prime_count(UV n) { |
|
111
|
4
|
|
|
|
|
|
UV sum = 0, cbrtn = prev_prime(rootint(n,3)+1); |
|
112
|
4
|
|
|
|
|
|
void *cache = prime_count_cache_create( (UV)pow(n,0.72) ); |
|
113
|
|
|
|
|
|
|
|
|
114
|
43
|
50
|
|
|
|
|
SIMPLE_FOR_EACH_PRIME(2, cbrtn) { |
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
115
|
35
|
|
|
|
|
|
UV pdiv = p, lo = p, hi = isqrt(n/pdiv); |
|
116
|
35
|
|
|
|
|
|
UV j = CACHED_PC(cache, lo) - 1; /* IDX(Pi) */ |
|
117
|
35
|
100
|
|
|
|
|
if ((lo <= 2) && (hi >= 2)) sum += CACHED_PC(cache,n/(pdiv*2)) - j++; |
|
|
|
50
|
|
|
|
|
|
|
118
|
35
|
100
|
|
|
|
|
if ((lo <= 3) && (hi >= 3)) sum += CACHED_PC(cache,n/(pdiv*3)) - j++; |
|
|
|
50
|
|
|
|
|
|
|
119
|
35
|
100
|
|
|
|
|
if ((lo <= 5) && (hi >= 5)) sum += CACHED_PC(cache,n/(pdiv*5)) - j++; |
|
|
|
100
|
|
|
|
|
|
|
120
|
35
|
100
|
|
|
|
|
if (lo < 7) lo = 7; |
|
121
|
35
|
100
|
|
|
|
|
if (lo <= hi) { |
|
122
|
|
|
|
|
|
|
unsigned char* segment; |
|
123
|
|
|
|
|
|
|
UV seg_base, seg_low, seg_high; |
|
124
|
32
|
|
|
|
|
|
void* ctx = start_segment_primes(lo, hi, &segment); |
|
125
|
64
|
100
|
|
|
|
|
while (next_segment_primes(ctx, &seg_base, &seg_low, &seg_high)) { |
|
126
|
1040
|
50
|
|
|
|
|
START_DO_FOR_EACH_SIEVE_PRIME( segment, seg_base, seg_low, seg_high ) |
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
127
|
903
|
|
|
|
|
|
sum += CACHED_PC(cache,n/(pdiv*p)) - j++; |
|
128
|
41
|
|
|
|
|
|
END_DO_FOR_EACH_SIEVE_PRIME |
|
129
|
|
|
|
|
|
|
} |
|
130
|
32
|
|
|
|
|
|
end_segment_primes(ctx); |
|
131
|
|
|
|
|
|
|
} |
|
132
|
|
|
|
|
|
|
} END_SIMPLE_FOR_EACH_PRIME |
|
133
|
4
|
|
|
|
|
|
prime_count_cache_destroy(cache); |
|
134
|
4
|
|
|
|
|
|
return sum; |
|
135
|
|
|
|
|
|
|
} |
|
136
|
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
/* almost_prime_count(k,n) is the main interface, it will call the recursive |
|
138
|
|
|
|
|
|
|
* function _cs(), with the terminal function _final_sum(). */ |
|
139
|
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
/* for Pi from Pi to isqrt(N/Pi) [pc[n/Pi]-idx(Pi)+1] */ |
|
141
|
|
|
|
|
|
|
/* semiprime count = _final_sum(n, 1, 2, cache); */ |
|
142
|
|
|
|
|
|
|
/* 3-almost prime count = sum(Pj < icbrt(n) of _final_sum(n, Pj, Pj, cache); */ |
|
143
|
3081
|
|
|
|
|
|
static UV _final_sum(UV n, UV pdiv, UV lo, void *cache) { |
|
144
|
3081
|
|
|
|
|
|
UV s = 0, hi = isqrt(n/pdiv); |
|
145
|
3081
|
|
|
|
|
|
UV j = CACHED_PC(cache, lo) - 1; /* IDX(Pi) */ |
|
146
|
|
|
|
|
|
|
|
|
147
|
3081
|
50
|
|
|
|
|
if (hi-lo < 500) { |
|
148
|
26472
|
50
|
|
|
|
|
SIMPLE_FOR_EACH_PRIME(lo, hi) { |
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
149
|
20310
|
|
|
|
|
|
s += CACHED_PC(cache,n/(pdiv*p)) - j++; |
|
150
|
|
|
|
|
|
|
} END_SIMPLE_FOR_EACH_PRIME |
|
151
|
3081
|
|
|
|
|
|
return s; |
|
152
|
|
|
|
|
|
|
} |
|
153
|
|
|
|
|
|
|
|
|
154
|
0
|
0
|
|
|
|
|
if ((lo <= 2) && (hi >= 2)) s += CACHED_PC(cache,n/(pdiv*2)) - j++; |
|
|
|
0
|
|
|
|
|
|
|
155
|
0
|
0
|
|
|
|
|
if ((lo <= 3) && (hi >= 3)) s += CACHED_PC(cache,n/(pdiv*3)) - j++; |
|
|
|
0
|
|
|
|
|
|
|
156
|
0
|
0
|
|
|
|
|
if ((lo <= 5) && (hi >= 5)) s += CACHED_PC(cache,n/(pdiv*5)) - j++; |
|
|
|
0
|
|
|
|
|
|
|
157
|
0
|
0
|
|
|
|
|
if (lo < 7) lo = 7; |
|
158
|
0
|
0
|
|
|
|
|
if (lo <= hi) { |
|
159
|
|
|
|
|
|
|
unsigned char* segment; |
|
160
|
|
|
|
|
|
|
UV seg_base, seg_low, seg_high; |
|
161
|
0
|
|
|
|
|
|
void* ctx = start_segment_primes(lo, hi, &segment); |
|
162
|
0
|
0
|
|
|
|
|
while (next_segment_primes(ctx, &seg_base, &seg_low, &seg_high)) { |
|
163
|
0
|
0
|
|
|
|
|
START_DO_FOR_EACH_SIEVE_PRIME( segment, seg_base, seg_low, seg_high ) |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
164
|
0
|
|
|
|
|
|
s += CACHED_PC(cache,n/(pdiv*p)) - j++; |
|
165
|
0
|
|
|
|
|
|
END_DO_FOR_EACH_SIEVE_PRIME |
|
166
|
|
|
|
|
|
|
} |
|
167
|
0
|
|
|
|
|
|
end_segment_primes(ctx); |
|
168
|
|
|
|
|
|
|
} |
|
169
|
0
|
|
|
|
|
|
return s; |
|
170
|
|
|
|
|
|
|
} |
|
171
|
|
|
|
|
|
|
|
|
172
|
2286
|
|
|
|
|
|
static UV _cs(UV n, UV pdiv, UV lo, uint32_t k, void *cache) { |
|
173
|
2286
|
|
|
|
|
|
UV count = 0; |
|
174
|
|
|
|
|
|
|
|
|
175
|
2286
|
50
|
|
|
|
|
if (k == 2) |
|
176
|
0
|
|
|
|
|
|
return _final_sum(n, pdiv, lo, cache); |
|
177
|
|
|
|
|
|
|
|
|
178
|
9909
|
50
|
|
|
|
|
SIMPLE_FOR_EACH_PRIME(lo, rootint(n/pdiv,k)) { |
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
179
|
5337
|
100
|
|
|
|
|
if (k == 3) count += _final_sum(n, pdiv*p, p, cache); |
|
180
|
2256
|
|
|
|
|
|
else count += _cs(n, pdiv*p, p, k-1, cache); |
|
181
|
|
|
|
|
|
|
} END_SIMPLE_FOR_EACH_PRIME |
|
182
|
|
|
|
|
|
|
|
|
183
|
2286
|
|
|
|
|
|
return count; |
|
184
|
|
|
|
|
|
|
} |
|
185
|
|
|
|
|
|
|
|
|
186
|
47
|
|
|
|
|
|
UV almost_prime_count(uint32_t k, UV n) |
|
187
|
|
|
|
|
|
|
{ |
|
188
|
|
|
|
|
|
|
void* cache; |
|
189
|
|
|
|
|
|
|
UV count, csize; |
|
190
|
|
|
|
|
|
|
|
|
191
|
47
|
100
|
|
|
|
|
if (k == 0) return (n >= 1); |
|
192
|
46
|
50
|
|
|
|
|
if (k >= BITS_PER_WORD || (n >> k) == 0) return 0; |
|
|
|
100
|
|
|
|
|
|
|
193
|
42
|
|
|
|
|
|
reduce_prime_count_factor(&k, &n); /* Reduce to lower k,n if possible */ |
|
194
|
|
|
|
|
|
|
|
|
195
|
42
|
100
|
|
|
|
|
if (n >= max_nth_almost_prime(k)) |
|
196
|
1
|
|
|
|
|
|
return max_almost_prime_count(k); |
|
197
|
|
|
|
|
|
|
|
|
198
|
41
|
50
|
|
|
|
|
if (k == 0) return n; |
|
199
|
41
|
100
|
|
|
|
|
if (k == 1) return prime_count(n); |
|
200
|
37
|
100
|
|
|
|
|
if (k == 2) return semiprime_count(n); |
|
201
|
34
|
100
|
|
|
|
|
if (k == 3) return almost3prime_count(n); |
|
202
|
30
|
50
|
|
|
|
|
if (n < 3*(UVCONST(1) << (k-1))) return 1; |
|
203
|
30
|
50
|
|
|
|
|
if (n < 9*(UVCONST(1) << (k-2))) return 2; |
|
204
|
30
|
50
|
|
|
|
|
if (n < 10*(UVCONST(1) << (k-2))) return 3; |
|
205
|
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
/* Decide how much we will cache prime counts. |
|
207
|
|
|
|
|
|
|
* |
|
208
|
|
|
|
|
|
|
* n/(1UL << (k+M)) has 0,1,2,7,15,37,84,187,... lookups for M=-2,-1,0,... |
|
209
|
|
|
|
|
|
|
* The number of non-cached counts performed follows OEIS A052130. */ |
|
210
|
|
|
|
|
|
|
|
|
211
|
30
|
|
|
|
|
|
csize = n / (1UL << (k-2)); |
|
212
|
30
|
100
|
|
|
|
|
if (csize < 32) csize = 32; |
|
213
|
30
|
100
|
|
|
|
|
if (csize > 16UL*1024) csize = n / (1UL << (k+2)); /* 15 */ |
|
214
|
30
|
50
|
|
|
|
|
if (csize > 128UL*1024) csize = n / (1UL << (k+4)); /* 84 */ |
|
215
|
30
|
50
|
|
|
|
|
if (csize > 1UL*1024*1024) csize = n / (1UL << (k+6)); /* 421 */ |
|
216
|
30
|
50
|
|
|
|
|
if (((csize >> 16) >> 16) >= 3) csize >>= 1; |
|
217
|
|
|
|
|
|
|
|
|
218
|
30
|
|
|
|
|
|
cache = prime_count_cache_create( csize ); |
|
219
|
30
|
|
|
|
|
|
count = _cs(n, 1, 2, k, cache); |
|
220
|
30
|
|
|
|
|
|
prime_count_cache_destroy(cache); |
|
221
|
30
|
|
|
|
|
|
return count; |
|
222
|
|
|
|
|
|
|
} |
|
223
|
|
|
|
|
|
|
|
|
224
|
0
|
|
|
|
|
|
UV almost_prime_count_range(uint32_t k, UV lo, UV hi) { |
|
225
|
0
|
0
|
|
|
|
|
if (k == 0) return (lo <= 1 && hi >= 1); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
226
|
0
|
0
|
|
|
|
|
if (k == 1) return prime_count_range(lo, hi); |
|
227
|
0
|
0
|
|
|
|
|
if (k == 2) return semiprime_count_range(lo, hi); |
|
228
|
|
|
|
|
|
|
/* See semiprime_count. Possibly clever solutions for small ranges. */ |
|
229
|
0
|
0
|
|
|
|
|
if (k >= BITS_PER_WORD || (hi >> k) == 0 || hi < lo) return 0; |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
230
|
0
|
|
|
|
|
|
return almost_prime_count(k, hi) |
|
231
|
0
|
0
|
|
|
|
|
- (((lo >> k) == 0) ? 0 : almost_prime_count(k,lo-1)); |
|
232
|
|
|
|
|
|
|
} |
|
233
|
|
|
|
|
|
|
|
|
234
|
159
|
|
|
|
|
|
UV almost_prime_count_approx(uint32_t k, UV n) { |
|
235
|
|
|
|
|
|
|
UV lo, hi; |
|
236
|
|
|
|
|
|
|
|
|
237
|
159
|
50
|
|
|
|
|
if (k == 0) return (n >= 1); |
|
238
|
159
|
50
|
|
|
|
|
if (k >= BITS_PER_WORD || (n >> k) == 0) return 0; |
|
|
|
100
|
|
|
|
|
|
|
239
|
150
|
|
|
|
|
|
reduce_prime_count_factor(&k, &n); /* Reduce to lower k,n if possible */ |
|
240
|
|
|
|
|
|
|
|
|
241
|
150
|
100
|
|
|
|
|
if (k == 1) return prime_count_approx(n); |
|
242
|
149
|
100
|
|
|
|
|
if (k == 2) return semiprime_count_approx(n); |
|
243
|
148
|
50
|
|
|
|
|
if (n < 3*(UVCONST(1) << (k-1))) return 1; |
|
244
|
148
|
50
|
|
|
|
|
if (n < 9*(UVCONST(1) << (k-2))) return 2; |
|
245
|
148
|
50
|
|
|
|
|
if (n < 10*(UVCONST(1) << (k-2))) return 3; |
|
246
|
|
|
|
|
|
|
|
|
247
|
148
|
100
|
|
|
|
|
if (k == 3 && n < 102) { |
|
|
|
100
|
|
|
|
|
|
|
248
|
3
|
|
|
|
|
|
unsigned char const sm3[19] = {27,28,30,42,44,45,50,52,63,66,68,70,75,76,78,92,98,99}; |
|
249
|
12
|
50
|
|
|
|
|
for (lo=0; lo < 19; lo++) |
|
250
|
12
|
100
|
|
|
|
|
if (n < sm3[lo]) |
|
251
|
3
|
|
|
|
|
|
break; |
|
252
|
3
|
|
|
|
|
|
return 4+lo; |
|
253
|
|
|
|
|
|
|
} |
|
254
|
|
|
|
|
|
|
|
|
255
|
145
|
|
|
|
|
|
_almost_prime_count_bounds(&lo, &hi, k, n); |
|
256
|
|
|
|
|
|
|
|
|
257
|
145
|
100
|
|
|
|
|
if (k == 3) { /* Much better fit for k=3. */ |
|
258
|
37
|
|
|
|
|
|
double x = n, logx = log(x), loglogx = log(logx); |
|
259
|
37
|
|
|
|
|
|
double a = 1.0, s = 2.0; |
|
260
|
|
|
|
|
|
|
UV est; |
|
261
|
37
|
100
|
|
|
|
|
if (x <= 638) { s = 1.554688; a = 0.865814; } |
|
262
|
25
|
100
|
|
|
|
|
else if (x <= 1544) { s = 1.050000; a = 0.822256; } |
|
263
|
23
|
100
|
|
|
|
|
else if (x <= 1927) { s = 0.625000; a = 0.791747; } |
|
264
|
15
|
100
|
|
|
|
|
else if (x <= 486586) { s = 2.865611; a = 1.004090; } |
|
265
|
4
|
50
|
|
|
|
|
else if (x <= 1913680) { s = 2.790963; a = 0.999618; } |
|
266
|
4
|
50
|
|
|
|
|
else if (x <= 22347532) { s = 2.719238; a = 0.995635; } |
|
267
|
4
|
100
|
|
|
|
|
else if (x <= 2.95e8) { s = 2.584473; a = 0.988802; } |
|
268
|
2
|
50
|
|
|
|
|
else if (x <= 4.20e9) { s = 2.457108; a = 0.983098; } |
|
269
|
2
|
50
|
|
|
|
|
else if (x <= 7.07e10) { s = 2.352818; a = 0.978931; } |
|
270
|
2
|
50
|
|
|
|
|
else if (x <= 1.36e12) { s = 2.269745; a = 0.975953; } |
|
271
|
2
|
50
|
|
|
|
|
else if (x <= 4.1e13) { s = 2.203002; a = 0.973796; } |
|
272
|
0
|
0
|
|
|
|
|
else if (x <= 9.2e14) { s = 2.148463; a = 0.972213; } |
|
273
|
0
|
|
|
|
|
|
else { s = 2.119279; a = 0.971438; } |
|
274
|
37
|
|
|
|
|
|
est = 0.5 * a * x * ((loglogx+0.26153)*(loglogx+0.26153)) / (logx+s)+0.5; |
|
275
|
37
|
50
|
|
|
|
|
if (est < lo) est = lo; |
|
276
|
37
|
50
|
|
|
|
|
else if (est > hi) est = hi; |
|
277
|
37
|
|
|
|
|
|
return est; |
|
278
|
|
|
|
|
|
|
} |
|
279
|
|
|
|
|
|
|
|
|
280
|
|
|
|
|
|
|
#if 0 /* Equation 6 from https://arxiv.org/pdf/2103.09866v3.pdf */ |
|
281
|
|
|
|
|
|
|
{ |
|
282
|
|
|
|
|
|
|
const double nu[21] = { |
|
283
|
|
|
|
|
|
|
1.0, 2.61497e-1, -5.62153e-1, 3.05978e-1, 2.62973e-2, -6.44501e-2, |
|
284
|
|
|
|
|
|
|
3.64064e-2, -4.70865e-3, -4.33984e-4, 1.50850e-3, -1.83548e-4, |
|
285
|
|
|
|
|
|
|
1.49365e-4, 4.99174e-5, 1.82657e-5, 1.30241e-5, 5.52779e-6, |
|
286
|
|
|
|
|
|
|
2.90194e-6, 1.45075e-6, 7.19861e-7, 3.61606e-7, 1.80517e-7 }; |
|
287
|
|
|
|
|
|
|
double sum = 0, x = n, logx = log(x), loglogx = log(logx); |
|
288
|
|
|
|
|
|
|
uint32_t i, j; |
|
289
|
|
|
|
|
|
|
for (j = 0; j < k; j++) { |
|
290
|
|
|
|
|
|
|
uint32_t idx = k-1-j; |
|
291
|
|
|
|
|
|
|
double v = (idx <= 20) ? nu[idx] : 0.1893475 * powl(2.0, -(double)k); |
|
292
|
|
|
|
|
|
|
for (i = 1; i <= j; i++) |
|
293
|
|
|
|
|
|
|
v = v * loglogx / i; |
|
294
|
|
|
|
|
|
|
sum += v; |
|
295
|
|
|
|
|
|
|
} |
|
296
|
|
|
|
|
|
|
sum = (x / logx) * sum; |
|
297
|
|
|
|
|
|
|
return (UV) (sum+0.5); |
|
298
|
|
|
|
|
|
|
} |
|
299
|
|
|
|
|
|
|
#endif |
|
300
|
|
|
|
|
|
|
|
|
301
|
|
|
|
|
|
|
/* We should look at (1) better bounds, (2) better weighting here */ |
|
302
|
|
|
|
|
|
|
/* return lo + (hi-lo)/2; */ |
|
303
|
|
|
|
|
|
|
/* Consider two variables to control our weight: k and n */ |
|
304
|
108
|
100
|
|
|
|
|
if (k > 11) return lo + (hi-lo) * 0.20; |
|
305
|
67
|
|
|
|
|
|
return lo + (hi-lo) * 0.76; |
|
306
|
|
|
|
|
|
|
} |
|
307
|
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
|
|
309
|
|
|
|
|
|
|
/******************************************************************************/ |
|
310
|
|
|
|
|
|
|
/* NTH KAP */ |
|
311
|
|
|
|
|
|
|
/******************************************************************************/ |
|
312
|
|
|
|
|
|
|
|
|
313
|
|
|
|
|
|
|
#if 0 |
|
314
|
|
|
|
|
|
|
/* Asymptotic estimate for the nth k-almost prime */ |
|
315
|
|
|
|
|
|
|
static double _asymptotic_nth(uint32_t k, UV n) { |
|
316
|
|
|
|
|
|
|
uint32_t i; double x, logn, loglogn; |
|
317
|
|
|
|
|
|
|
if (k == 0 || n == 0) return 0; |
|
318
|
|
|
|
|
|
|
if (n == 1) return UVCONST(1) << k; |
|
319
|
|
|
|
|
|
|
logn = log(n); |
|
320
|
|
|
|
|
|
|
loglogn = log(logn); |
|
321
|
|
|
|
|
|
|
x = n * logn; |
|
322
|
|
|
|
|
|
|
for (i = 1; i < k; i++) |
|
323
|
|
|
|
|
|
|
x *= (double)i / loglogn; |
|
324
|
|
|
|
|
|
|
return x; |
|
325
|
|
|
|
|
|
|
} |
|
326
|
|
|
|
|
|
|
#endif |
|
327
|
|
|
|
|
|
|
|
|
328
|
161
|
|
|
|
|
|
static UV apcu(UV mid, UV k) { return almost_prime_count_upper(k, mid); } |
|
329
|
53
|
|
|
|
|
|
static UV apcl(UV mid, UV k) { return almost_prime_count_lower(k, mid); } |
|
330
|
123
|
|
|
|
|
|
static UV apca(UV mid, UV k) { return almost_prime_count_approx(k, mid); } |
|
331
|
12
|
|
|
|
|
|
static UV apce(UV mid, UV k) { return almost_prime_count(k, mid); } |
|
332
|
|
|
|
|
|
|
|
|
333
|
5
|
|
|
|
|
|
UV nth_almost_prime_upper(uint32_t k, UV n) { |
|
334
|
|
|
|
|
|
|
UV r, maxc, maxn, lo, up; |
|
335
|
|
|
|
|
|
|
|
|
336
|
5
|
50
|
|
|
|
|
if (n == 0) return 0; |
|
337
|
5
|
50
|
|
|
|
|
if (k == 0) return (n == 1) ? 1 : 0; |
|
338
|
5
|
50
|
|
|
|
|
if (k == 1) return nth_prime_upper(n); |
|
339
|
5
|
50
|
|
|
|
|
if (n < 8) return _fast_small_nth_almost_prime(k, n); |
|
340
|
|
|
|
|
|
|
|
|
341
|
5
|
|
|
|
|
|
maxn = max_nth_almost_prime(k); |
|
342
|
5
|
|
|
|
|
|
maxc = max_almost_prime_count(k); |
|
343
|
5
|
50
|
|
|
|
|
if (n >= maxc) return n == maxc ? maxn : 0; |
|
|
|
0
|
|
|
|
|
|
|
344
|
|
|
|
|
|
|
|
|
345
|
5
|
|
|
|
|
|
r = reduce_nth_factor(k,n); |
|
346
|
5
|
100
|
|
|
|
|
if (r > 0) { |
|
347
|
1
|
|
|
|
|
|
UV redup = nth_almost_prime_upper(k-r, n); |
|
348
|
1
|
50
|
|
|
|
|
if (redup > maxn || ((redup<>r) != redup) |
|
|
|
50
|
|
|
|
|
|
|
349
|
0
|
|
|
|
|
|
return maxn; |
|
350
|
1
|
|
|
|
|
|
return redup << r; |
|
351
|
|
|
|
|
|
|
} |
|
352
|
|
|
|
|
|
|
|
|
353
|
|
|
|
|
|
|
/* We start out with the literal min and max because we have NO idea. */ |
|
354
|
4
|
|
|
|
|
|
lo = UVCONST(5) << k; /* For k >= 1 and n >= 8 */ |
|
355
|
|
|
|
|
|
|
|
|
356
|
4
|
|
|
|
|
|
up = inverse_interpolate_k(lo, 0, n, k, &apcl, 0); |
|
357
|
4
|
|
|
|
|
|
return up > maxn ? maxn : up; |
|
358
|
|
|
|
|
|
|
} |
|
359
|
|
|
|
|
|
|
|
|
360
|
14
|
|
|
|
|
|
UV nth_almost_prime_lower(uint32_t k, UV n) { |
|
361
|
|
|
|
|
|
|
UV r, maxc, lo; |
|
362
|
|
|
|
|
|
|
|
|
363
|
14
|
50
|
|
|
|
|
if (n == 0) return 0; |
|
364
|
14
|
50
|
|
|
|
|
if (k == 0) return (n == 1) ? 1 : 0; |
|
365
|
14
|
50
|
|
|
|
|
if (k == 1) return nth_prime_lower(n); |
|
366
|
14
|
50
|
|
|
|
|
if (n < 8) return _fast_small_nth_almost_prime(k, n); |
|
367
|
|
|
|
|
|
|
|
|
368
|
14
|
|
|
|
|
|
maxc = max_almost_prime_count(k); |
|
369
|
14
|
50
|
|
|
|
|
if (n >= maxc) return n == maxc ? max_nth_almost_prime(k) : 0; |
|
|
|
0
|
|
|
|
|
|
|
370
|
|
|
|
|
|
|
|
|
371
|
14
|
|
|
|
|
|
r = reduce_nth_factor(k,n); |
|
372
|
14
|
100
|
|
|
|
|
if (r > 0) return nth_almost_prime_lower(k-r, n) << r; |
|
373
|
|
|
|
|
|
|
|
|
374
|
|
|
|
|
|
|
/* We start out with the literal min and max because we have NO idea. */ |
|
375
|
|
|
|
|
|
|
/* \_/ note 3 instead of 5! TODO: apcu is not tight enough, so reduce */ |
|
376
|
12
|
|
|
|
|
|
lo = UVCONST(3) << k; /* For k >= 1 and n >= 8 */ |
|
377
|
|
|
|
|
|
|
|
|
378
|
12
|
|
|
|
|
|
return inverse_interpolate_k(lo, 0, n, k, &apcu, 0); |
|
379
|
|
|
|
|
|
|
} |
|
380
|
|
|
|
|
|
|
|
|
381
|
10
|
|
|
|
|
|
UV nth_almost_prime_approx(uint32_t k, UV n) { |
|
382
|
|
|
|
|
|
|
UV maxc, lo; |
|
383
|
|
|
|
|
|
|
|
|
384
|
10
|
50
|
|
|
|
|
if (n == 0) return 0; |
|
385
|
10
|
50
|
|
|
|
|
if (k == 0) return (n == 1) ? 1 : 0; |
|
386
|
10
|
100
|
|
|
|
|
if (k == 1) return nth_prime_approx(n); |
|
387
|
9
|
100
|
|
|
|
|
if (k == 2) return nth_semiprime_approx(n); |
|
388
|
|
|
|
|
|
|
|
|
389
|
8
|
|
|
|
|
|
maxc = max_almost_prime_count(k); |
|
390
|
8
|
50
|
|
|
|
|
if (n >= maxc) return n == maxc ? max_nth_almost_prime(k) : 0; |
|
|
|
0
|
|
|
|
|
|
|
391
|
|
|
|
|
|
|
|
|
392
|
|
|
|
|
|
|
/* We could reduce but really no reason to do it */ |
|
393
|
|
|
|
|
|
|
|
|
394
|
8
|
50
|
|
|
|
|
if (n < 8) return _fast_small_nth_almost_prime(k,n); |
|
395
|
8
|
|
|
|
|
|
lo = nth_almost_prime_lower(k,n); |
|
396
|
|
|
|
|
|
|
|
|
397
|
8
|
|
|
|
|
|
return inverse_interpolate_k(lo, 0, n, k, &apca, 0); |
|
398
|
|
|
|
|
|
|
} |
|
399
|
|
|
|
|
|
|
|
|
400
|
1
|
|
|
|
|
|
static UV _cb_nth3(UV n) { return nth_almost_prime_approx(3,n); } |
|
401
|
1
|
|
|
|
|
|
static UV _cb_cnt3(UV n) { return almost_prime_count(3,n); } |
|
402
|
4
|
|
|
|
|
|
static bool _cb_is3(UV n) { return is_almost_prime(3,n); } |
|
403
|
|
|
|
|
|
|
|
|
404
|
1
|
|
|
|
|
|
static UV _cb_nth4(UV n) { return nth_almost_prime_approx(4,n); } |
|
405
|
1
|
|
|
|
|
|
static UV _cb_cnt4(UV n) { return almost_prime_count(4,n); } |
|
406
|
221
|
|
|
|
|
|
static bool _cb_is4(UV n) { return is_almost_prime(4,n); } |
|
407
|
|
|
|
|
|
|
|
|
408
|
10
|
|
|
|
|
|
UV nth_almost_prime(uint32_t k, UV n) { |
|
409
|
|
|
|
|
|
|
UV r, lo, hi, maxc; |
|
410
|
|
|
|
|
|
|
|
|
411
|
10
|
50
|
|
|
|
|
if (n == 0) return 0; |
|
412
|
10
|
50
|
|
|
|
|
if (k == 0) return (n == 1) ? 1 : 0; |
|
413
|
10
|
100
|
|
|
|
|
if (k == 1) return nth_prime(n); |
|
414
|
9
|
100
|
|
|
|
|
if (k == 2) return nth_semiprime(n); |
|
415
|
|
|
|
|
|
|
|
|
416
|
7
|
|
|
|
|
|
maxc = max_almost_prime_count(k); |
|
417
|
7
|
50
|
|
|
|
|
if (n >= maxc) return n == maxc ? max_nth_almost_prime(k) : 0; |
|
|
|
0
|
|
|
|
|
|
|
418
|
|
|
|
|
|
|
|
|
419
|
|
|
|
|
|
|
/* For k >= 3 and small n we can answer this quickly. */ |
|
420
|
7
|
100
|
|
|
|
|
if (n < 8) return _fast_small_nth_almost_prime(k,n); |
|
421
|
5
|
|
|
|
|
|
r = reduce_nth_factor(k,n); |
|
422
|
5
|
100
|
|
|
|
|
if (r > 0) return nth_almost_prime(k-r,n) << r; |
|
423
|
|
|
|
|
|
|
/* NOTE: given n a 64-bit integer, k always <= 40 after reduction */ |
|
424
|
|
|
|
|
|
|
|
|
425
|
|
|
|
|
|
|
/* Using the approximation to narrow in is *much* more efficient. But |
|
426
|
|
|
|
|
|
|
* there is no good way to make it generic without closures (GCC extension) |
|
427
|
|
|
|
|
|
|
* or statics (not thread-safe). */ |
|
428
|
4
|
100
|
|
|
|
|
if (k == 3) |
|
429
|
1
|
|
|
|
|
|
return interpolate_with_approx(n, 0, 20000, &_cb_nth3, &_cb_cnt3, &_cb_is3); |
|
430
|
3
|
100
|
|
|
|
|
if (k == 4) |
|
431
|
1
|
|
|
|
|
|
return interpolate_with_approx(n, 0, 20000, &_cb_nth4, &_cb_cnt4, &_cb_is4); |
|
432
|
|
|
|
|
|
|
|
|
433
|
2
|
|
|
|
|
|
lo = nth_almost_prime_lower(k,n); |
|
434
|
2
|
|
|
|
|
|
hi = nth_almost_prime_upper(k,n); |
|
435
|
2
|
|
|
|
|
|
hi = inverse_interpolate_k(lo, hi, n, k, &apce, 60000); |
|
436
|
6234
|
100
|
|
|
|
|
while (!is_almost_prime(k,hi)) |
|
437
|
6232
|
|
|
|
|
|
hi--; |
|
438
|
2
|
|
|
|
|
|
return hi; |
|
439
|
|
|
|
|
|
|
} |
|
440
|
|
|
|
|
|
|
|
|
441
|
|
|
|
|
|
|
|
|
442
|
|
|
|
|
|
|
/******************************************************************************/ |
|
443
|
|
|
|
|
|
|
/* Bounds */ |
|
444
|
|
|
|
|
|
|
/******************************************************************************/ |
|
445
|
|
|
|
|
|
|
|
|
446
|
|
|
|
|
|
|
/* Bayless et al. (2018) and Kinlaw (2019) are main references. |
|
447
|
|
|
|
|
|
|
* |
|
448
|
|
|
|
|
|
|
* https://www.researchgate.net/publication/329788487_Sums_over_primitive_sets_with_a_fixed_number_of_prime_factors |
|
449
|
|
|
|
|
|
|
* http://math.colgate.edu/~integers/t22/t22.pdf |
|
450
|
|
|
|
|
|
|
* https://arxiv.org/pdf/2103.09866v3.pdf |
|
451
|
|
|
|
|
|
|
* |
|
452
|
|
|
|
|
|
|
* Note that they use Pi_k(x) to mean square-free numbers, and |
|
453
|
|
|
|
|
|
|
* Tau_k(x) to mean the general count like we use. |
|
454
|
|
|
|
|
|
|
* They also have results for k = 2,3,4 only. |
|
455
|
|
|
|
|
|
|
* Also see https://archimede.mat.ulaval.ca/MAINE-QUEBEC/19/Kinlaw19.pdf. |
|
456
|
|
|
|
|
|
|
* |
|
457
|
|
|
|
|
|
|
* We split into three ranges: |
|
458
|
|
|
|
|
|
|
* 1 - 2^20 complete computations |
|
459
|
|
|
|
|
|
|
* 2^20 - 2^32 complete computations |
|
460
|
|
|
|
|
|
|
* 2^32 - 2^64 correct upper for k=2,3,4. correct lower for k=2. |
|
461
|
|
|
|
|
|
|
* empirical for other k. |
|
462
|
|
|
|
|
|
|
* |
|
463
|
|
|
|
|
|
|
*/ |
|
464
|
|
|
|
|
|
|
|
|
465
|
|
|
|
|
|
|
static const double _upper_20[13] = {0,0, 1.006,0.7385,0.6830,0.5940,0.3596,0.2227,0.1439, 0.09785,0.07016,0.05303,0.04202}; |
|
466
|
|
|
|
|
|
|
static const double _upper_32[21] = {0,0, 1.013,0.8094,0.7485, |
|
467
|
|
|
|
|
|
|
/* 5-12 */ 0.6467,0.3984,0.2464,0.1572,0.1049,0.07364,0.05452,0.04266, |
|
468
|
|
|
|
|
|
|
/* 13-20 */ 0.03542,0.03082,0.02798,0.02642,0.02585,0.02615,0.02808,0.03054}; |
|
469
|
|
|
|
|
|
|
static const double _upper_64[41] = {0,0, 1.028, 1.028, 1.3043,/* <--corrrect */ |
|
470
|
|
|
|
|
|
|
/* 5-12 */ |
|
471
|
|
|
|
|
|
|
0.72208, 0.46609, 0.29340,0.18571,0.12063,0.0815,0.0575,0.0427, |
|
472
|
|
|
|
|
|
|
/* 13-20 */ |
|
473
|
|
|
|
|
|
|
0.03490, 0.03007, 0.02710, 0.02554, 0.02504, 0.02554, 0.02699, 0.02954, |
|
474
|
|
|
|
|
|
|
/* 21-28 */ |
|
475
|
|
|
|
|
|
|
0.03294, 0.03779, 0.04453, 0.05393, 0.06703, 0.08543, 0.1117, 0.1494, |
|
476
|
|
|
|
|
|
|
/* 29-31 */ |
|
477
|
|
|
|
|
|
|
0.205,0.287,0.410, |
|
478
|
|
|
|
|
|
|
/* 32-40 */ |
|
479
|
|
|
|
|
|
|
0.60,0.90,1.36,2.12,3.35,5.38,8.83,14.75,25.07, |
|
480
|
|
|
|
|
|
|
}; |
|
481
|
|
|
|
|
|
|
|
|
482
|
|
|
|
|
|
|
static const double _lower_20[13] = {0,0, 0.8197, 0.8418, 0.5242, |
|
483
|
|
|
|
|
|
|
/* 5-12 */ 0.5154,0.3053,0.1901,0.1253,0.0892,0.06551,0.05082,0.04101}; |
|
484
|
|
|
|
|
|
|
static const double _lower_32[21] = {0,0, 1.004, 0.7383, 0.6828, |
|
485
|
|
|
|
|
|
|
/* 5-12 */ 0.5939,0.3594,0.2222,0.1438,0.09754,0.06981,0.05245,0.04151, |
|
486
|
|
|
|
|
|
|
/* 13-20 */ 0.03461,0.03006,0.02709,0.02553,0.02502,0.02552,0.02697,0.02945 }; |
|
487
|
|
|
|
|
|
|
static const double _lower_64[41] = {0,0, 1.011, 0.8093, 0.7484, |
|
488
|
|
|
|
|
|
|
/* 5-12 */ |
|
489
|
|
|
|
|
|
|
0.6465,0.3982,0.2463,0.1571,0.1048,0.07363,0.0545,0.0422, |
|
490
|
|
|
|
|
|
|
/* 13-20 */ |
|
491
|
|
|
|
|
|
|
0.0331,0.0270,0.0232,0.0208,0.0194,0.0190,0.0193,0.0203, |
|
492
|
|
|
|
|
|
|
/* 21-28 */ |
|
493
|
|
|
|
|
|
|
0.0222,0.0252,0.0295,0.0356,0.0444,0.0570,0.0753,0.102, |
|
494
|
|
|
|
|
|
|
/* 29-31 */ |
|
495
|
|
|
|
|
|
|
0.14,0.20,0.297, |
|
496
|
|
|
|
|
|
|
/* 32-40 */ |
|
497
|
|
|
|
|
|
|
0.44,0.68,1.07,1.71,2.8,4.7,8.0,13.89,23.98, |
|
498
|
|
|
|
|
|
|
}; |
|
499
|
|
|
|
|
|
|
|
|
500
|
|
|
|
|
|
|
/* |
|
501
|
|
|
|
|
|
|
k,count n <= 2^64-1 |
|
502
|
|
|
|
|
|
|
1,425656284035217743 |
|
503
|
|
|
|
|
|
|
2,1701748900850019777 10 hours |
|
504
|
|
|
|
|
|
|
3,3167597434038354478 320 hours |
|
505
|
|
|
|
|
|
|
4,3787884015050788482 322 hours |
|
506
|
|
|
|
|
|
|
5,3378907169603895030 294 hours |
|
507
|
|
|
|
|
|
|
6,2466706950238087748 209 hours |
|
508
|
|
|
|
|
|
|
7,1571012171387856192 123 hours |
|
509
|
|
|
|
|
|
|
8,913164427599983727 82 hours |
|
510
|
|
|
|
|
|
|
9,499840874923678341 42 hours |
|
511
|
|
|
|
|
|
|
10,263157990621533964 20 hours |
|
512
|
|
|
|
|
|
|
11,135128109904869290 12 hours |
|
513
|
|
|
|
|
|
|
12,68283616225825256 7 hours |
|
514
|
|
|
|
|
|
|
13,34151861008771016 4 hours |
|
515
|
|
|
|
|
|
|
14,16967424859951587 2 hours |
|
516
|
|
|
|
|
|
|
15,8393048221327186 |
|
517
|
|
|
|
|
|
|
16,4139595949113890 |
|
518
|
|
|
|
|
|
|
17,2037655246635364 |
|
519
|
|
|
|
|
|
|
18,1001591348315641 |
|
520
|
|
|
|
|
|
|
19,491808604962296 |
|
521
|
|
|
|
|
|
|
20,241293656953012 |
|
522
|
|
|
|
|
|
|
21,118304122014405 |
|
523
|
|
|
|
|
|
|
22,57968649799947 |
|
524
|
|
|
|
|
|
|
23,28388662714236 |
|
525
|
|
|
|
|
|
|
24,13895161400556 |
|
526
|
|
|
|
|
|
|
25,6797526392535 |
|
527
|
|
|
|
|
|
|
26,3323560145881 |
|
528
|
|
|
|
|
|
|
27,1624109166018 |
|
529
|
|
|
|
|
|
|
28,793189260998 |
|
530
|
|
|
|
|
|
|
29,387148515886 |
|
531
|
|
|
|
|
|
|
30,188844769357 |
|
532
|
|
|
|
|
|
|
31,92054377509 |
|
533
|
|
|
|
|
|
|
32,44841620426 |
|
534
|
|
|
|
|
|
|
33,21827124353 |
|
535
|
|
|
|
|
|
|
34,10616326552 |
|
536
|
|
|
|
|
|
|
35,5159281045 |
|
537
|
|
|
|
|
|
|
36,2505087309 |
|
538
|
|
|
|
|
|
|
37,1215204383 |
|
539
|
|
|
|
|
|
|
38,588891145 |
|
540
|
|
|
|
|
|
|
39,285076316 |
|
541
|
|
|
|
|
|
|
40,137840686 |
|
542
|
|
|
|
|
|
|
*/ |
|
543
|
|
|
|
|
|
|
|
|
544
|
363
|
|
|
|
|
|
static void _almost_prime_count_bounds(UV *lower, UV *upper, uint32_t k, UV n) { |
|
545
|
|
|
|
|
|
|
double x, logx, loglogx, logplus, multl, multu, boundl, boundu; |
|
546
|
|
|
|
|
|
|
UV max; |
|
547
|
|
|
|
|
|
|
uint32_t i; |
|
548
|
|
|
|
|
|
|
|
|
549
|
363
|
50
|
|
|
|
|
if (k >= BITS_PER_WORD || (n >> k) == 0) { *lower = *upper = 0; return; } |
|
|
|
50
|
|
|
|
|
|
|
550
|
363
|
|
|
|
|
|
reduce_prime_count_factor(&k, &n); /* Reduce to lower k,n if possible */ |
|
551
|
363
|
50
|
|
|
|
|
if (k == 0) { *lower = *upper = (n >= 1); return; } |
|
552
|
363
|
50
|
|
|
|
|
if (k == 1) { *lower = prime_count_lower(n); *upper = prime_count_upper(n); return; } |
|
553
|
363
|
50
|
|
|
|
|
if (n < 3*(UVCONST(1) << (k-1))) { *lower = *upper = 1; return; } |
|
554
|
363
|
50
|
|
|
|
|
if (n < 9*(UVCONST(1) << (k-2))) { *lower = *upper = 2; return; } |
|
555
|
363
|
50
|
|
|
|
|
if (n < 10*(UVCONST(1) << (k-2))) { *lower = *upper = 3; return; } |
|
556
|
|
|
|
|
|
|
|
|
557
|
363
|
|
|
|
|
|
max = max_almost_prime_count(k); |
|
558
|
363
|
50
|
|
|
|
|
if (n >= max_nth_almost_prime(k)) |
|
559
|
0
|
|
|
|
|
|
{ *lower = *upper = max; return; } |
|
560
|
|
|
|
|
|
|
|
|
561
|
363
|
|
|
|
|
|
x = (double) n; |
|
562
|
363
|
|
|
|
|
|
logx = log(x); |
|
563
|
363
|
|
|
|
|
|
loglogx = log(logx); |
|
564
|
363
|
|
|
|
|
|
logplus = loglogx + 0.26153; |
|
565
|
|
|
|
|
|
|
|
|
566
|
|
|
|
|
|
|
/* Select the appropriate table for n's range. |
|
567
|
|
|
|
|
|
|
* 20/32/64-bit n will always reduce k to these limits. */ |
|
568
|
363
|
100
|
|
|
|
|
if (n <= 1048575U) { |
|
569
|
234
|
50
|
|
|
|
|
MPUassert(k <= 12, "almost prime count: 20-bit n doesn't exceed k 12"); |
|
570
|
234
|
|
|
|
|
|
multu = _upper_20[k]; multl = _lower_20[k]; |
|
571
|
129
|
100
|
|
|
|
|
} else if (n <= 4294967295U) { |
|
572
|
123
|
50
|
|
|
|
|
MPUassert(k <= 20, "almost prime count: 32-bit n doesn't exceed k 20"); |
|
573
|
123
|
|
|
|
|
|
multu = _upper_32[k]; multl = _lower_32[k]; |
|
574
|
|
|
|
|
|
|
} else { |
|
575
|
6
|
50
|
|
|
|
|
MPUassert(k <= 40, "almost prime count: after reduction, k <= 40"); |
|
576
|
6
|
|
|
|
|
|
multu = _upper_64[k]; multl = _lower_64[k]; |
|
577
|
|
|
|
|
|
|
} |
|
578
|
|
|
|
|
|
|
|
|
579
|
363
|
100
|
|
|
|
|
if (k == 2) { |
|
580
|
12
|
|
|
|
|
|
boundl = boundu = x * (loglogx + 0.261536) / logx; |
|
581
|
12
|
50
|
|
|
|
|
if (x >= 1e12) { |
|
582
|
0
|
|
|
|
|
|
boundl = x*(loglogx+0.1769)/logx * (1+0.4232/logx); |
|
583
|
0
|
|
|
|
|
|
multl = 1; |
|
584
|
|
|
|
|
|
|
} |
|
585
|
351
|
100
|
|
|
|
|
} else if (k == 3) { |
|
586
|
107
|
|
|
|
|
|
boundu = x * (logplus*logplus + 1.055852) / (2*logx); |
|
587
|
|
|
|
|
|
|
/* Kinlaw (2019) Theorem 1 (with 1.000) */ |
|
588
|
107
|
|
|
|
|
|
boundl = x * loglogx * loglogx / (2*logx); |
|
589
|
107
|
100
|
|
|
|
|
if (n < 638) { |
|
590
|
37
|
|
|
|
|
|
multl = 0.8418; |
|
591
|
70
|
100
|
|
|
|
|
} else if (n <= 1926) { |
|
592
|
19
|
|
|
|
|
|
double weight = (x - 638L) / (double)(1926 - 638); |
|
593
|
19
|
|
|
|
|
|
multl = (1L-weight) * 0.8939 + weight * 0.9233; |
|
594
|
51
|
100
|
|
|
|
|
} else if (n <= 500194) { |
|
595
|
47
|
|
|
|
|
|
double weight = (x - 1927L) / (double)(500194 - 1927); |
|
596
|
47
|
|
|
|
|
|
multl = (1L-weight) * 0.9233 + weight * 1.000; |
|
597
|
4
|
100
|
|
|
|
|
} else if (n <= 3184393786U) { |
|
598
|
2
|
|
|
|
|
|
double weight = (x - 500194L) / (double)(3184393786U - 500194U); |
|
599
|
2
|
|
|
|
|
|
multl = (1L-weight) * 1.0000 + weight * 1.039; |
|
600
|
|
|
|
|
|
|
} else { /* TODO blend down to this */ |
|
601
|
2
|
|
|
|
|
|
multl = 1.0004; |
|
602
|
|
|
|
|
|
|
} |
|
603
|
|
|
|
|
|
|
/* Bayless (2018) Theorem 5.3 proves that multu=1.028 is a correct bound |
|
604
|
|
|
|
|
|
|
* for all x >= 10^12. However it is not a tight bound for the range |
|
605
|
|
|
|
|
|
|
* 2^32 to 2^64. We tighten it a lot for the reduced range. |
|
606
|
|
|
|
|
|
|
*/ |
|
607
|
107
|
100
|
|
|
|
|
if (n > 4294967295U) multu = 0.8711; |
|
608
|
244
|
100
|
|
|
|
|
} else if (k == 4) { |
|
609
|
|
|
|
|
|
|
/* Bayless doesn't discuss a lower bound for k=4. */ |
|
610
|
|
|
|
|
|
|
/* Bayless Theorem 5.4 part 1 (with multu = 1.3043) */ |
|
611
|
89
|
|
|
|
|
|
boundl = boundu = x * logplus*logplus*logplus / (6*logx); |
|
612
|
|
|
|
|
|
|
/* Bayless Theorem 5.4 part 2 */ |
|
613
|
89
|
100
|
|
|
|
|
if (x > 1e12) { |
|
614
|
2
|
|
|
|
|
|
boundu += 0.511977 * x * (log(log(x/4)) + 0.261536) / logx; |
|
615
|
2
|
|
|
|
|
|
multu = 1.028; |
|
616
|
|
|
|
|
|
|
} |
|
617
|
|
|
|
|
|
|
/* As with k=3, adjust to tighten in the finite range. */ |
|
618
|
89
|
100
|
|
|
|
|
if (n > 4294967295U) multu = 0.780; |
|
619
|
89
|
100
|
|
|
|
|
if (x > 1e12) multu = 0.6921; |
|
620
|
|
|
|
|
|
|
} else { |
|
621
|
|
|
|
|
|
|
/* Completely empirical and by no means optimal. |
|
622
|
|
|
|
|
|
|
* It is easy and seems fairly reasonable through k=20 or so. |
|
623
|
|
|
|
|
|
|
* |
|
624
|
|
|
|
|
|
|
* For high k, this follows the lower bound well but upper grows too fast. |
|
625
|
|
|
|
|
|
|
*/ |
|
626
|
155
|
|
|
|
|
|
boundl = x / logx; |
|
627
|
155
|
|
|
|
|
|
logplus = loglogx + (log(k)*log(log(k))-0.504377); /* k=5 => 0.26153 */ |
|
628
|
2134
|
100
|
|
|
|
|
for (i = 1; i < k; i++) |
|
629
|
1979
|
|
|
|
|
|
boundl *= logplus / (double)i; |
|
630
|
155
|
|
|
|
|
|
boundu = boundl; |
|
631
|
|
|
|
|
|
|
} |
|
632
|
|
|
|
|
|
|
|
|
633
|
|
|
|
|
|
|
#if 0 |
|
634
|
|
|
|
|
|
|
printf(" lower: %lf * %lf = %lf\n", boundl, multl, boundl*multl); |
|
635
|
|
|
|
|
|
|
printf(" upper: %lf * %lf = %lf\n", boundu, multu, boundu*multu); |
|
636
|
|
|
|
|
|
|
printf(" max: %lu\n", max); |
|
637
|
|
|
|
|
|
|
#endif |
|
638
|
363
|
|
|
|
|
|
boundl *= multl; |
|
639
|
363
|
|
|
|
|
|
boundu *= multu; |
|
640
|
|
|
|
|
|
|
|
|
641
|
363
|
50
|
|
|
|
|
*lower = (boundl >= UV_MAX || (max > 0 && boundl > max)) ? max : (UV)boundl; |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
642
|
363
|
50
|
|
|
|
|
*upper = (boundu >= UV_MAX || (max > 0 && boundu > max)) ? max : (UV)(boundu+1.0); |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
643
|
|
|
|
|
|
|
} |
|
644
|
|
|
|
|
|
|
|
|
645
|
163
|
|
|
|
|
|
UV almost_prime_count_upper(uint32_t k, UV n) { |
|
646
|
|
|
|
|
|
|
UV l, u; |
|
647
|
163
|
50
|
|
|
|
|
if (k == 2 && n < 256) return semiprime_count(n); |
|
|
|
0
|
|
|
|
|
|
|
648
|
163
|
|
|
|
|
|
_almost_prime_count_bounds(&l, &u, k, n); |
|
649
|
163
|
|
|
|
|
|
return u; |
|
650
|
|
|
|
|
|
|
} |
|
651
|
|
|
|
|
|
|
|
|
652
|
55
|
|
|
|
|
|
UV almost_prime_count_lower(uint32_t k, UV n) { |
|
653
|
|
|
|
|
|
|
UV l, u; |
|
654
|
55
|
50
|
|
|
|
|
if (k == 2 && n < 256) return semiprime_count(n); |
|
|
|
0
|
|
|
|
|
|
|
655
|
55
|
|
|
|
|
|
_almost_prime_count_bounds(&l, &u, k, n); |
|
656
|
55
|
|
|
|
|
|
return l; |
|
657
|
|
|
|
|
|
|
} |
|
658
|
|
|
|
|
|
|
|
|
659
|
448
|
|
|
|
|
|
UV max_nth_almost_prime(uint32_t k) { |
|
660
|
|
|
|
|
|
|
#if BITS_PER_WORD == 32 |
|
661
|
|
|
|
|
|
|
static const UV offset[32] = {UV_MAX-1,4,1,9,5,0,7,47,31,3,15,511,1263,5119,1023,255,23295,2559,4095,126975,16383,262143,2359295,2097151,5767167,1048575,33554431,16777215,100663295,67108863,268435455,1073741823}; |
|
662
|
|
|
|
|
|
|
#else |
|
663
|
|
|
|
|
|
|
static const UV offset[64] = {UV_MAX-1,58,14,2,4, |
|
664
|
|
|
|
|
|
|
/* 5-12 */ 3,17,0,1,195,51,127,63, |
|
665
|
|
|
|
|
|
|
/* 13-22 */ 767,1535,511,255,15,8191,1023,83967,16383,111615, |
|
666
|
|
|
|
|
|
|
/* 23-32 */ 557055,2097151,524287,65535,1048575,6553599,33554431,4194303,671088639,16777215, |
|
667
|
|
|
|
|
|
|
/* 33-63 */ UVCONST(536870911),UVCONST(2684354559),UVCONST(2147483647), |
|
668
|
|
|
|
|
|
|
UVCONST(25769803775),UVCONST(4294967295),UVCONST(268435455), |
|
669
|
|
|
|
|
|
|
UVCONST(206158430207),UVCONST(137438953471),UVCONST(17179869183), |
|
670
|
|
|
|
|
|
|
UVCONST(68719476735),UVCONST(2199023255551),UVCONST(5428838662143), |
|
671
|
|
|
|
|
|
|
UVCONST(21990232555519),UVCONST(4398046511103),UVCONST(1099511627775), |
|
672
|
|
|
|
|
|
|
UVCONST(100055558127615),UVCONST(10995116277759),UVCONST(17592186044415), |
|
673
|
|
|
|
|
|
|
UVCONST(545357767376895),UVCONST(70368744177663),UVCONST(1125899906842623), |
|
674
|
|
|
|
|
|
|
UVCONST(10133099161583615),UVCONST(9007199254740991), |
|
675
|
|
|
|
|
|
|
UVCONST(24769797950537727),UVCONST(4503599627370495), |
|
676
|
|
|
|
|
|
|
UVCONST(144115188075855871),UVCONST(72057594037927935), |
|
677
|
|
|
|
|
|
|
UVCONST(432345564227567615),UVCONST(288230376151711743), |
|
678
|
|
|
|
|
|
|
UVCONST(1152921504606846975),UVCONST(4611686018427387903) |
|
679
|
|
|
|
|
|
|
}; |
|
680
|
|
|
|
|
|
|
#endif |
|
681
|
448
|
50
|
|
|
|
|
if (k >= BITS_PER_WORD) return 0; |
|
682
|
448
|
|
|
|
|
|
return UV_MAX - offset[k]; |
|
683
|
|
|
|
|
|
|
} |
|
684
|
|
|
|
|
|
|
|
|
685
|
420
|
|
|
|
|
|
UV max_almost_prime_count(uint32_t k) { |
|
686
|
|
|
|
|
|
|
#if BITS_PER_WORD == 32 |
|
687
|
|
|
|
|
|
|
static const UV max[32] = {1,203280221,658662065,967785236,916899721,665533848,410630859,229679168,121092503,61600699,30653019,15043269,7315315,3535071,1700690,814699,389357,185245,87964,41599,19611,9184,4283,2001,914,421,187,84,37,15,7,2}; |
|
688
|
|
|
|
|
|
|
#else |
|
689
|
|
|
|
|
|
|
static const UV max[64] = {1, |
|
690
|
|
|
|
|
|
|
UVCONST( 425656284035217743), /* max prime count */ |
|
691
|
|
|
|
|
|
|
UVCONST(1701748900850019777), /* max semiprime count */ |
|
692
|
|
|
|
|
|
|
UVCONST(3167597434038354478), /* max 3-almost-prime count */ |
|
693
|
|
|
|
|
|
|
UVCONST(3787884015050788482), /* max 4-almost-prime count */ |
|
694
|
|
|
|
|
|
|
/* 5-12 */ UVCONST(3378907169603895030),UVCONST(2466706950238087748),UVCONST(1571012171387856192),UVCONST(913164427599983727),UVCONST(499840874923678341),UVCONST(263157990621533964),UVCONST(135128109904869290),UVCONST(68283616225825256), |
|
695
|
|
|
|
|
|
|
/* 13-22 */ UVCONST(34151861008771016),UVCONST(16967424859951587),UVCONST(8393048221327186),UVCONST(4139595949113890),UVCONST(2037655246635364),UVCONST(1001591348315641),UVCONST(491808604962296),UVCONST(241293656953012),UVCONST(118304122014405),UVCONST(57968649799947), |
|
696
|
|
|
|
|
|
|
/* 23-32 */ UVCONST(28388662714236),UVCONST(13895161400556),UVCONST(6797526392535),UVCONST(3323560145881),UVCONST(1624109166018),UVCONST(793189260998),UVCONST(387148515886),UVCONST(188844769357),UVCONST(92054377509),UVCONST(44841620426), |
|
697
|
|
|
|
|
|
|
/* 33-63 */ UVCONST(21827124353),UVCONST(10616326552),UVCONST(5159281045),UVCONST(2505087309),1215204383,588891145,285076316,137840686,66567488,32103728,15460810,7433670,3567978,1709640,817053,389954,185387,87993,41604,19611,9184,4283,2001,914,421,187,84,37,15,7,2 |
|
698
|
|
|
|
|
|
|
}; |
|
699
|
|
|
|
|
|
|
#endif |
|
700
|
420
|
50
|
|
|
|
|
if (k >= BITS_PER_WORD) return 0; |
|
701
|
|
|
|
|
|
|
/* if (max[k] == 0) return UV_MAX; All filled in so no need */ |
|
702
|
420
|
|
|
|
|
|
return max[k]; |
|
703
|
|
|
|
|
|
|
} |
|
704
|
|
|
|
|
|
|
|
|
705
|
|
|
|
|
|
|
|
|
706
|
|
|
|
|
|
|
/******************************************************************************/ |
|
707
|
|
|
|
|
|
|
/* Construction */ |
|
708
|
|
|
|
|
|
|
/******************************************************************************/ |
|
709
|
|
|
|
|
|
|
|
|
710
|
|
|
|
|
|
|
/* There are a few options for constructing KAPs without sieving/factoring. |
|
711
|
|
|
|
|
|
|
* |
|
712
|
|
|
|
|
|
|
* 1) we can make an iterator that recursively constructs them using |
|
713
|
|
|
|
|
|
|
* a prime list and a k-1 iterator. This is a generalization of |
|
714
|
|
|
|
|
|
|
* Dijkstra's Hamming number algorithm. |
|
715
|
|
|
|
|
|
|
* |
|
716
|
|
|
|
|
|
|
* 2) Given a range [lo,hi], We can ask for all k-1 kaps less than hi/2, |
|
717
|
|
|
|
|
|
|
* then multiply through by primes to see which fall in our range. |
|
718
|
|
|
|
|
|
|
* |
|
719
|
|
|
|
|
|
|
* Each of these (and sieving) is limited in some ways. For example, #1 |
|
720
|
|
|
|
|
|
|
* can output 500-almost-primes quite rapidly which some other methods have |
|
721
|
|
|
|
|
|
|
* trouble with, even with all the calculation in Perl. But it rapidly |
|
722
|
|
|
|
|
|
|
* slows down with increasing n. |
|
723
|
|
|
|
|
|
|
* |
|
724
|
|
|
|
|
|
|
* I suspect there are far more efficient methods. |
|
725
|
|
|
|
|
|
|
*/ |
|
726
|
|
|
|
|
|
|
|
|
727
|
0
|
|
|
|
|
|
static void _tidy_list(UV **list, UV *Lsize, UV *count, bool minimal) { |
|
728
|
0
|
|
|
|
|
|
UV *L = *list; |
|
729
|
|
|
|
|
|
|
|
|
730
|
0
|
0
|
|
|
|
|
if (*count > 1) { |
|
731
|
|
|
|
|
|
|
UV i, j; |
|
732
|
0
|
|
|
|
|
|
sort_uv_array(L, *count); |
|
733
|
0
|
0
|
|
|
|
|
for (j = 0, i = 1; i < *count; i++) { |
|
734
|
0
|
0
|
|
|
|
|
if (L[i] != L[j]) |
|
735
|
0
|
|
|
|
|
|
L[++j] = L[i]; |
|
736
|
|
|
|
|
|
|
} |
|
737
|
0
|
|
|
|
|
|
*count = j+1; |
|
738
|
|
|
|
|
|
|
} |
|
739
|
0
|
0
|
|
|
|
|
if (minimal) { |
|
740
|
0
|
|
|
|
|
|
*Lsize = *count; |
|
741
|
0
|
0
|
|
|
|
|
Renew(*list, *Lsize, UV); |
|
742
|
0
|
0
|
|
|
|
|
} else if (*count * 1.5 > *Lsize) { |
|
743
|
0
|
|
|
|
|
|
*Lsize = *count * 2 + 100; |
|
744
|
0
|
0
|
|
|
|
|
Renew(*list, *Lsize, UV); |
|
745
|
|
|
|
|
|
|
} |
|
746
|
0
|
|
|
|
|
|
} |
|
747
|
|
|
|
|
|
|
|
|
748
|
0
|
|
|
|
|
|
UV range_construct_almost_prime(UV** list, uint32_t k, UV lo, UV hi) { |
|
749
|
0
|
|
|
|
|
|
UV *L, minkap1, lastprime, count = 0; |
|
750
|
|
|
|
|
|
|
|
|
751
|
0
|
0
|
|
|
|
|
if (k == 0 || k >= BITS_PER_WORD) { *list = 0; return 0; } |
|
|
|
0
|
|
|
|
|
|
|
752
|
0
|
0
|
|
|
|
|
if ((lo >> k) == 0) lo = UVCONST(1) << k; |
|
753
|
0
|
0
|
|
|
|
|
if (hi > max_nth_almost_prime(k)) hi = max_nth_almost_prime(k); |
|
754
|
0
|
0
|
|
|
|
|
if (lo > hi) { *list = 0; return 0; } |
|
755
|
|
|
|
|
|
|
|
|
756
|
0
|
0
|
|
|
|
|
if (k == 1) return range_prime_sieve(list, lo, hi); |
|
757
|
0
|
0
|
|
|
|
|
if (k == 2) return range_semiprime_sieve(list, lo, hi); |
|
758
|
|
|
|
|
|
|
/* if (k <= 5) return range_almost_prime_sieve(list, k, lo, hi); */ |
|
759
|
|
|
|
|
|
|
|
|
760
|
0
|
|
|
|
|
|
minkap1 = 1 << (k-1); |
|
761
|
0
|
|
|
|
|
|
lastprime = hi / minkap1; /* lastprime = prev_prime(lastprime+1); */ |
|
762
|
|
|
|
|
|
|
|
|
763
|
|
|
|
|
|
|
{ |
|
764
|
|
|
|
|
|
|
UV i, Lsize; |
|
765
|
0
|
|
|
|
|
|
UV *lkap1, nkap1=range_construct_almost_prime(&lkap1, k-1, minkap1, hi>>1); |
|
766
|
|
|
|
|
|
|
|
|
767
|
|
|
|
|
|
|
/* Now multiply through exhaustively. */ |
|
768
|
0
|
|
|
|
|
|
Lsize = nkap1*4 + 100; |
|
769
|
0
|
0
|
|
|
|
|
New(0, L, Lsize, UV); |
|
770
|
|
|
|
|
|
|
|
|
771
|
0
|
0
|
|
|
|
|
START_DO_FOR_EACH_PRIME(2, lastprime) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
772
|
0
|
0
|
|
|
|
|
for (i = 0; i < nkap1; i++) { |
|
773
|
0
|
|
|
|
|
|
UV prod = p * lkap1[i]; |
|
774
|
0
|
0
|
|
|
|
|
if (prod < lo) continue; |
|
775
|
0
|
0
|
|
|
|
|
if (prod > hi) break; |
|
776
|
0
|
0
|
|
|
|
|
if (count >= Lsize) |
|
777
|
0
|
|
|
|
|
|
_tidy_list(&L, &Lsize, &count, 0); |
|
778
|
0
|
|
|
|
|
|
L[count++] = prod; |
|
779
|
|
|
|
|
|
|
} |
|
780
|
|
|
|
|
|
|
} END_DO_FOR_EACH_PRIME |
|
781
|
0
|
|
|
|
|
|
_tidy_list(&L, &Lsize, &count, 1); |
|
782
|
0
|
|
|
|
|
|
Safefree(lkap1); |
|
783
|
|
|
|
|
|
|
} |
|
784
|
0
|
|
|
|
|
|
*list = L; |
|
785
|
0
|
|
|
|
|
|
return count; |
|
786
|
|
|
|
|
|
|
} |
|
787
|
|
|
|
|
|
|
|
|
788
|
3
|
|
|
|
|
|
UV range_almost_prime_sieve(UV** list, uint32_t k, UV slo, UV shi) |
|
789
|
|
|
|
|
|
|
{ |
|
790
|
|
|
|
|
|
|
UV *S, Ssize, i, j, count; |
|
791
|
3
|
|
|
|
|
|
const UV thresh_pred = 40; |
|
792
|
|
|
|
|
|
|
|
|
793
|
3
|
50
|
|
|
|
|
if (k == 0 || k >= BITS_PER_WORD) { *list = 0; return 0; } |
|
|
|
50
|
|
|
|
|
|
|
794
|
3
|
50
|
|
|
|
|
if ((slo >> k) == 0) slo = UVCONST(1) << k; |
|
795
|
3
|
50
|
|
|
|
|
if (shi > max_nth_almost_prime(k)) shi = max_nth_almost_prime(k); |
|
796
|
3
|
50
|
|
|
|
|
if (slo > shi) { *list = 0; return 0; } |
|
797
|
|
|
|
|
|
|
|
|
798
|
|
|
|
|
|
|
#if 1 |
|
799
|
3
|
50
|
|
|
|
|
if (shi-slo+1 < thresh_pred) { |
|
800
|
0
|
|
|
|
|
|
Ssize = 3 + (thresh_pred >> 1); |
|
801
|
0
|
0
|
|
|
|
|
New(0, S, Ssize, UV); |
|
802
|
0
|
0
|
|
|
|
|
for (i = 0, j = 0; i < shi-slo+1; i++) |
|
803
|
0
|
0
|
|
|
|
|
if (is_almost_prime(k, slo+i)) |
|
804
|
0
|
|
|
|
|
|
S[j++] = slo+i; |
|
805
|
0
|
|
|
|
|
|
*list = S; |
|
806
|
0
|
|
|
|
|
|
return j; |
|
807
|
|
|
|
|
|
|
} |
|
808
|
|
|
|
|
|
|
#endif |
|
809
|
|
|
|
|
|
|
|
|
810
|
3
|
50
|
|
|
|
|
if (k == 1) return range_prime_sieve(list, slo, shi); |
|
811
|
3
|
50
|
|
|
|
|
if (k == 2) return range_semiprime_sieve(list, slo, shi); |
|
812
|
|
|
|
|
|
|
|
|
813
|
|
|
|
|
|
|
/* See if we can reduce k. |
|
814
|
|
|
|
|
|
|
* If for all possible kap from 1 to shi, ap(k,n) = 2*ap(k-1,n), then |
|
815
|
|
|
|
|
|
|
* sieve for k-1 from lo/2 to hi/2+1. |
|
816
|
|
|
|
|
|
|
* For large k this can continue even further so we might reduce a lot. |
|
817
|
|
|
|
|
|
|
*/ |
|
818
|
|
|
|
|
|
|
{ |
|
819
|
3
|
|
|
|
|
|
uint32_t r = reduce_k_for_n(k, shi); |
|
820
|
3
|
50
|
|
|
|
|
if (r > 0) { |
|
821
|
0
|
|
|
|
|
|
UV lo = (slo >> r) + (((slo >> r) << r) < slo); |
|
822
|
0
|
|
|
|
|
|
UV hi = shi >> r; |
|
823
|
0
|
|
|
|
|
|
count = range_almost_prime_sieve(&S, k-r, lo, hi); |
|
824
|
0
|
0
|
|
|
|
|
for (i = 0; i < count; i++) |
|
825
|
0
|
|
|
|
|
|
S[i] <<= r; |
|
826
|
0
|
|
|
|
|
|
*list = S; |
|
827
|
0
|
|
|
|
|
|
return count; |
|
828
|
|
|
|
|
|
|
} |
|
829
|
|
|
|
|
|
|
} |
|
830
|
|
|
|
|
|
|
|
|
831
|
3
|
|
|
|
|
|
Ssize = (almost_prime_count_approx(k,shi) - almost_prime_count_approx(k,slo) + 1) * 1.2 + 100; |
|
832
|
3
|
50
|
|
|
|
|
if (Ssize > 10000000UL) Ssize = 10000000UL; |
|
833
|
3
|
50
|
|
|
|
|
New(0, S, Ssize, UV); |
|
834
|
|
|
|
|
|
|
|
|
835
|
|
|
|
|
|
|
/* Do a range nfactor sieve in small windows, with one optimization. |
|
836
|
|
|
|
|
|
|
* |
|
837
|
|
|
|
|
|
|
* We know that we are looking for numbers with k factors, hence after |
|
838
|
|
|
|
|
|
|
* looking for small factors we could get a remainder R as large as: |
|
839
|
|
|
|
|
|
|
* 2 x 2 x ... x R where R could be prime or semiprime. Hence we can |
|
840
|
|
|
|
|
|
|
* reduce the sieve limit somewhat. Effectively we are sieving to the |
|
841
|
|
|
|
|
|
|
* maximum possible *second largest* factor for a k-almost-prime, |
|
842
|
|
|
|
|
|
|
* allowing us to correctly decide whether R is prime or semiprime |
|
843
|
|
|
|
|
|
|
* (if it has >= k factors). |
|
844
|
|
|
|
|
|
|
* |
|
845
|
|
|
|
|
|
|
* This isn't a big deal for small k, but it's a big impact for high k. |
|
846
|
|
|
|
|
|
|
* |
|
847
|
|
|
|
|
|
|
* I still think there should be a better way to do this for high k. |
|
848
|
|
|
|
|
|
|
* Is there any way to do this just sieving to rootint(hi,k+1)? |
|
849
|
|
|
|
|
|
|
* Given hi=10^6: |
|
850
|
|
|
|
|
|
|
* k=3 => 97^3, 2x701^2, 2x2x249989 |
|
851
|
|
|
|
|
|
|
* k=4 => 31^4, 2x79^3, 2x2x499^2, 2x2x2x724991 |
|
852
|
|
|
|
|
|
|
*/ |
|
853
|
|
|
|
|
|
|
{ |
|
854
|
|
|
|
|
|
|
unsigned char* nf; |
|
855
|
3
|
|
|
|
|
|
UV const segsize = 65536*4; |
|
856
|
|
|
|
|
|
|
UV *N, lo, hi, range; |
|
857
|
3
|
50
|
|
|
|
|
UV kdiv = (k < 3) ? UVCONST(1) : (UVCONST(1) << (k-2)); |
|
858
|
|
|
|
|
|
|
|
|
859
|
3
|
|
|
|
|
|
New(0, nf, segsize+1, unsigned char); |
|
860
|
3
|
50
|
|
|
|
|
New(0, N, segsize+1, UV); |
|
861
|
3
|
|
|
|
|
|
prime_precalc(isqrt(shi/kdiv)); |
|
862
|
3
|
|
|
|
|
|
count = 0; |
|
863
|
|
|
|
|
|
|
|
|
864
|
6
|
100
|
|
|
|
|
for (lo = slo; lo <= shi && lo >= slo; lo = hi+1) { |
|
|
|
50
|
|
|
|
|
|
|
865
|
3
|
|
|
|
|
|
hi = lo+segsize-1; |
|
866
|
3
|
50
|
|
|
|
|
if (hi > shi || hi < lo) hi = shi; |
|
|
|
0
|
|
|
|
|
|
|
867
|
3
|
|
|
|
|
|
range = hi - lo + 1; |
|
868
|
3
|
|
|
|
|
|
memset(nf, 0, range); |
|
869
|
156
|
100
|
|
|
|
|
for (i = lo; i <= hi; i++) { |
|
870
|
153
|
100
|
|
|
|
|
if (!(i&1) && i >= 2) { |
|
|
|
50
|
|
|
|
|
|
|
871
|
78
|
50
|
|
|
|
|
const unsigned char nz = (unsigned char)ctz(i); |
|
872
|
78
|
|
|
|
|
|
nf[i-lo] = nz; |
|
873
|
78
|
|
|
|
|
|
N[i-lo] = UVCONST(1) << nz; |
|
874
|
|
|
|
|
|
|
} else |
|
875
|
75
|
|
|
|
|
|
N[i-lo] = 1; |
|
876
|
|
|
|
|
|
|
} |
|
877
|
381777
|
50
|
|
|
|
|
START_DO_FOR_EACH_PRIME(3, isqrt(hi/kdiv)) { |
|
|
|
50
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
878
|
372021
|
|
|
|
|
|
UV pk, maxpk = UV_MAX/p; \ |
|
879
|
372389
|
50
|
|
|
|
|
for (i = P_GT_LO_0(p,p,lo); i < range; i += p) |
|
|
|
100
|
|
|
|
|
|
|
880
|
368
|
|
|
|
|
|
{ N[i] *= p; nf[i]++; } |
|
881
|
752679
|
100
|
|
|
|
|
for (pk = p*p; pk <= hi; pk *= p) { |
|
882
|
380736
|
50
|
|
|
|
|
for (i = P_GT_LO_0(pk,pk,lo); i < range; i += pk) |
|
|
|
100
|
|
|
|
|
|
|
883
|
78
|
|
|
|
|
|
{ N[i] *= p; nf[i]++; } |
|
884
|
380658
|
50
|
|
|
|
|
if (pk >= maxpk) break; /* Overflow protection */ |
|
885
|
|
|
|
|
|
|
} |
|
886
|
|
|
|
|
|
|
} END_DO_FOR_EACH_PRIME |
|
887
|
156
|
100
|
|
|
|
|
for (i = 0; i < range; i++) { |
|
888
|
153
|
100
|
|
|
|
|
if (N[i] < (lo+i)) |
|
889
|
115
|
|
|
|
|
|
nf[i]++; |
|
890
|
153
|
100
|
|
|
|
|
if (nf[i] == k) { |
|
891
|
34
|
50
|
|
|
|
|
if (count >= Ssize) |
|
892
|
0
|
0
|
|
|
|
|
Renew(S, Ssize += 10000, UV); |
|
893
|
34
|
|
|
|
|
|
S[count++] = i+lo; |
|
894
|
|
|
|
|
|
|
} |
|
895
|
|
|
|
|
|
|
} |
|
896
|
|
|
|
|
|
|
} |
|
897
|
3
|
|
|
|
|
|
Safefree(N); |
|
898
|
3
|
|
|
|
|
|
Safefree(nf); |
|
899
|
|
|
|
|
|
|
} |
|
900
|
3
|
|
|
|
|
|
*list = S; |
|
901
|
3
|
|
|
|
|
|
return count; |
|
902
|
|
|
|
|
|
|
} |
|
903
|
|
|
|
|
|
|
|
|
904
|
|
|
|
|
|
|
/* Algorithm from Trizen, May 2022 */ |
|
905
|
744
|
|
|
|
|
|
static void _genkap(UV lo, UV hi, uint32_t k, UV m, UV begp, UV **List, UV *Lpos, UV *Lsize) { |
|
906
|
744
|
100
|
|
|
|
|
if (k == 1) { |
|
907
|
|
|
|
|
|
|
|
|
908
|
398
|
|
|
|
|
|
UV pos = *Lpos, size = *Lsize, *L = *List; |
|
909
|
398
|
|
|
|
|
|
UV start = lo/m + (lo % m != 0), endp = hi/m; |
|
910
|
|
|
|
|
|
|
|
|
911
|
398
|
100
|
|
|
|
|
if (start > begp) begp = start; |
|
912
|
|
|
|
|
|
|
|
|
913
|
398
|
100
|
|
|
|
|
if (endp < 10000000U) { |
|
914
|
1035
|
50
|
|
|
|
|
START_DO_FOR_EACH_PRIME(begp, endp) { |
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
915
|
642
|
50
|
|
|
|
|
if (L != 0) { |
|
916
|
642
|
50
|
|
|
|
|
if (pos >= size) Renew(L, size += 100000, UV); |
|
|
|
0
|
|
|
|
|
|
|
917
|
642
|
|
|
|
|
|
L[pos] = m*p; |
|
918
|
|
|
|
|
|
|
} |
|
919
|
642
|
|
|
|
|
|
pos++; |
|
920
|
|
|
|
|
|
|
} END_DO_FOR_EACH_PRIME |
|
921
|
|
|
|
|
|
|
} else { |
|
922
|
|
|
|
|
|
|
UV i, count, *list; |
|
923
|
5
|
|
|
|
|
|
count = range_prime_sieve(&list, begp, endp); |
|
924
|
5
|
50
|
|
|
|
|
if (L == 0) { |
|
925
|
0
|
|
|
|
|
|
pos += count; |
|
926
|
|
|
|
|
|
|
} else { |
|
927
|
5
|
50
|
|
|
|
|
if ((pos + count - 1) >= size) Renew(L, size += (count + 100000), UV); |
|
|
|
0
|
|
|
|
|
|
|
928
|
8
|
100
|
|
|
|
|
for (i = 0; i < count; i++) |
|
929
|
3
|
|
|
|
|
|
L[pos++] = m * list[i]; |
|
930
|
|
|
|
|
|
|
} |
|
931
|
5
|
|
|
|
|
|
Safefree(list); |
|
932
|
|
|
|
|
|
|
} |
|
933
|
398
|
|
|
|
|
|
*Lpos = pos; |
|
934
|
398
|
|
|
|
|
|
*Lsize = size; |
|
935
|
398
|
|
|
|
|
|
*List = L; |
|
936
|
|
|
|
|
|
|
|
|
937
|
|
|
|
|
|
|
} else { |
|
938
|
|
|
|
|
|
|
|
|
939
|
|
|
|
|
|
|
UV p, s; |
|
940
|
31497
|
100
|
|
|
|
|
for (s = rootint(hi/m, k), p = begp; p <= s; p = next_prime(p)) { |
|
941
|
31151
|
|
|
|
|
|
UV t = m * p; |
|
942
|
31151
|
100
|
|
|
|
|
if ((lo/t + (lo % t != 0)) <= (hi/t)) |
|
943
|
732
|
|
|
|
|
|
_genkap(lo, hi, k-1, t, p, List, Lpos, Lsize); |
|
944
|
|
|
|
|
|
|
} |
|
945
|
|
|
|
|
|
|
|
|
946
|
|
|
|
|
|
|
} |
|
947
|
744
|
|
|
|
|
|
} |
|
948
|
|
|
|
|
|
|
|
|
949
|
24
|
|
|
|
|
|
UV generate_almost_primes(UV** list, uint32_t k, UV lo, UV hi) { |
|
950
|
24
|
|
|
|
|
|
UV *L, Lpos = 0, Lsize, countest; |
|
951
|
|
|
|
|
|
|
|
|
952
|
24
|
50
|
|
|
|
|
if (k >= BITS_PER_WORD) { *list = 0; return 0; } |
|
953
|
24
|
100
|
|
|
|
|
if ((lo >> k) == 0) lo = UVCONST(1) << k; |
|
954
|
24
|
100
|
|
|
|
|
if (hi > max_nth_almost_prime(k)) hi = max_nth_almost_prime(k); |
|
955
|
24
|
100
|
|
|
|
|
if (lo > hi) { *list = 0; return 0; } |
|
956
|
|
|
|
|
|
|
|
|
957
|
|
|
|
|
|
|
/* For these small k values, these are typically faster */ |
|
958
|
23
|
100
|
|
|
|
|
if (k == 0) { New(0,L,1,UV); L[0]=1; *list=L; return 1; } |
|
959
|
20
|
100
|
|
|
|
|
if (k == 1) return range_prime_sieve(list, lo, hi); |
|
960
|
17
|
100
|
|
|
|
|
if (k == 2) return range_semiprime_sieve(list, lo, hi); |
|
961
|
|
|
|
|
|
|
|
|
962
|
|
|
|
|
|
|
/* Large base with small range: better to sieve */ |
|
963
|
15
|
50
|
|
|
|
|
if ( (k >= 3 && hi >= 1e12 && (hi-lo) <= 5e6) || |
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
964
|
12
|
50
|
|
|
|
|
(k >= 3 && hi >= 1e13 && (hi-lo) <= 2e8) || |
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
965
|
12
|
50
|
|
|
|
|
(k >= 3 && hi >= 1e14 && (hi-lo) <= 4e8) ) |
|
|
|
0
|
|
|
|
|
|
|
966
|
3
|
|
|
|
|
|
return range_almost_prime_sieve(list, k, lo, hi); |
|
967
|
|
|
|
|
|
|
|
|
968
|
|
|
|
|
|
|
/* Optional: we could try reduce_k_for_n() here. */ |
|
969
|
|
|
|
|
|
|
|
|
970
|
12
|
|
|
|
|
|
prime_precalc(10000000U); |
|
971
|
12
|
|
|
|
|
|
countest = almost_prime_count_approx(k,hi) - almost_prime_count_approx(k,lo-1); |
|
972
|
12
|
50
|
|
|
|
|
Lsize = (countest > 10000000U) ? 10000000U : countest+1000; |
|
973
|
|
|
|
|
|
|
|
|
974
|
12
|
50
|
|
|
|
|
New(0, L, Lsize, UV); |
|
975
|
12
|
|
|
|
|
|
_genkap(lo, hi, k, 1, 2, &L, &Lpos, &Lsize); |
|
976
|
12
|
|
|
|
|
|
sort_uv_array(L, Lpos); |
|
977
|
12
|
|
|
|
|
|
*list = L; |
|
978
|
12
|
|
|
|
|
|
return Lpos; |
|
979
|
|
|
|
|
|
|
} |
|
980
|
|
|
|
|
|
|
|
|
981
|
|
|
|
|
|
|
|
|
982
|
|
|
|
|
|
|
/******************************************************************************/ |
|
983
|
|
|
|
|
|
|
/* CHEN PRIMES */ |
|
984
|
|
|
|
|
|
|
/******************************************************************************/ |
|
985
|
|
|
|
|
|
|
|
|
986
|
|
|
|
|
|
|
/* consider Chen(h,k) where p prime and bigomega(p+h) <= k */ |
|
987
|
|
|
|
|
|
|
|
|
988
|
|
|
|
|
|
|
#if BITS_PER_WORD == 64 |
|
989
|
|
|
|
|
|
|
#define MAX_CHEN_PRIME UVCONST(18446744073709551437) |
|
990
|
|
|
|
|
|
|
#else |
|
991
|
|
|
|
|
|
|
#define MAX_CHEN_PRIME UVCONST(4294967291) |
|
992
|
|
|
|
|
|
|
#endif |
|
993
|
|
|
|
|
|
|
|
|
994
|
202
|
|
|
|
|
|
bool is_chen_prime(UV n) { |
|
995
|
202
|
100
|
|
|
|
|
if (n < 2 || n > MAX_CHEN_PRIME) return 0; |
|
|
|
50
|
|
|
|
|
|
|
996
|
200
|
100
|
|
|
|
|
return (is_prime(n) && (is_prime(n+2) || is_semiprime(n+2))); |
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
997
|
|
|
|
|
|
|
} |
|
998
|
|
|
|
|
|
|
|
|
999
|
36
|
|
|
|
|
|
UV next_chen_prime(UV n) { |
|
1000
|
48
|
50
|
|
|
|
|
for ( n = next_prime(n); n != 0 && n < MAX_CHEN_PRIME; n = next_prime(n+2) ) |
|
|
|
50
|
|
|
|
|
|
|
1001
|
48
|
100
|
|
|
|
|
if (is_prime(n+2) || is_semiprime(n+2)) |
|
|
|
100
|
|
|
|
|
|
|
1002
|
36
|
|
|
|
|
|
return n; |
|
1003
|
0
|
|
|
|
|
|
return 0; |
|
1004
|
|
|
|
|
|
|
} |