| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
/******************************************************************************/ |
|
2
|
|
|
|
|
|
|
/* OMEGA PRIMES */ |
|
3
|
|
|
|
|
|
|
/******************************************************************************/ |
|
4
|
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
#include |
|
6
|
|
|
|
|
|
|
#include |
|
7
|
|
|
|
|
|
|
#include |
|
8
|
|
|
|
|
|
|
#include |
|
9
|
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
#define FUNC_isqrt 1 |
|
11
|
|
|
|
|
|
|
#include "ptypes.h" |
|
12
|
|
|
|
|
|
|
#include "constants.h" |
|
13
|
|
|
|
|
|
|
#include "cache.h" |
|
14
|
|
|
|
|
|
|
#include "sieve.h" |
|
15
|
|
|
|
|
|
|
#include "util.h" |
|
16
|
|
|
|
|
|
|
#include "sort.h" |
|
17
|
|
|
|
|
|
|
#include "prime_counts.h" |
|
18
|
|
|
|
|
|
|
#include "prime_powers.h" |
|
19
|
|
|
|
|
|
|
#include "factor.h" |
|
20
|
|
|
|
|
|
|
#include "inverse_interpolate.h" |
|
21
|
|
|
|
|
|
|
#include "omega_primes.h" |
|
22
|
|
|
|
|
|
|
|
|
23
|
3945
|
|
|
|
|
|
bool is_omega_prime(uint32_t k, UV n) { |
|
24
|
5920
|
50
|
|
|
|
|
if (k > 0 && !(n& 1)) { k--; do { n >>= 1; } while (!(n& 1)); } |
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
25
|
4553
|
100
|
|
|
|
|
if (k > 0 && !(n% 3)) { k--; do { n /= 3; } while (!(n% 3)); } |
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
26
|
4144
|
100
|
|
|
|
|
if (k > 0 && !(n% 5)) { k--; do { n /= 5; } while (!(n% 5)); } |
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
27
|
4034
|
100
|
|
|
|
|
if (k > 0 && !(n% 7)) { k--; do { n /= 7; } while (!(n% 7)); } |
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
28
|
3983
|
100
|
|
|
|
|
if (k > 0 && !(n%11)) { k--; do { n /= 11; } while (!(n%11)); } |
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
|
|
30
|
3945
|
100
|
|
|
|
|
if (n == 1) return (k == 0); |
|
31
|
3745
|
100
|
|
|
|
|
if (k == 0) return (n == 1); |
|
32
|
3581
|
100
|
|
|
|
|
if (k == 1) return is_prime_power(n); |
|
33
|
3367
|
100
|
|
|
|
|
if (n < ipowsafe(13,k)) return 0; |
|
34
|
|
|
|
|
|
|
|
|
35
|
181
|
|
|
|
|
|
return ((UV)prime_omega(n) == k); |
|
36
|
|
|
|
|
|
|
} |
|
37
|
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
/* See https://arxiv.org/pdf/2006.16491.pdf page 12 for a brief note */ |
|
39
|
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
/* For the interpolation */ |
|
41
|
984
|
|
|
|
|
|
static UV opce(UV mid, UV k) { return omega_prime_count(k, mid); } |
|
42
|
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
/********************************* Construction *****************************/ |
|
45
|
|
|
|
|
|
|
|
|
46
|
0
|
|
|
|
|
|
static void _omega_prime_gen_rec(UV** kop, UV* skop, UV* nkop, uint32_t k, UV lo, UV hi, UV m, UV pstart) { |
|
47
|
0
|
|
|
|
|
|
UV v, *l = *kop, lsize = *skop, n = *nkop; |
|
48
|
|
|
|
|
|
|
|
|
49
|
0
|
0
|
|
|
|
|
if (k > 1) { |
|
50
|
0
|
0
|
|
|
|
|
SIMPLE_FOR_EACH_PRIME(pstart, rootint(hi/m, k)) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
51
|
0
|
0
|
|
|
|
|
if ((m % p) == 0) continue; |
|
52
|
0
|
0
|
|
|
|
|
if (UV_MAX/m < p) break; |
|
53
|
0
|
0
|
|
|
|
|
for (v = m*p; UV_MAX/v >= p && v*p <= hi; v *= p) |
|
|
|
0
|
|
|
|
|
|
|
54
|
0
|
|
|
|
|
|
_omega_prime_gen_rec(kop, skop, nkop, k-1, lo, hi, v, p); |
|
55
|
|
|
|
|
|
|
} END_SIMPLE_FOR_EACH_PRIME |
|
56
|
0
|
|
|
|
|
|
return; |
|
57
|
|
|
|
|
|
|
} |
|
58
|
|
|
|
|
|
|
|
|
59
|
0
|
0
|
|
|
|
|
START_DO_FOR_EACH_PRIME(pstart, rootint(hi/m, k)) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
60
|
0
|
0
|
|
|
|
|
if ((m % p) == 0) continue; |
|
61
|
0
|
0
|
|
|
|
|
for (v = m; UV_MAX/v >= p && v*p <= hi; ) { |
|
|
|
0
|
|
|
|
|
|
|
62
|
0
|
|
|
|
|
|
v *= p; |
|
63
|
0
|
0
|
|
|
|
|
if (v >= lo) { /* Add v to kop list */ |
|
64
|
0
|
0
|
|
|
|
|
if (n >= lsize) { |
|
65
|
0
|
|
|
|
|
|
lsize = 1 + lsize * 1.2; |
|
66
|
0
|
0
|
|
|
|
|
Renew(l, lsize, UV); |
|
67
|
|
|
|
|
|
|
} |
|
68
|
0
|
|
|
|
|
|
l[n++] = v; |
|
69
|
|
|
|
|
|
|
} |
|
70
|
|
|
|
|
|
|
} |
|
71
|
|
|
|
|
|
|
} END_DO_FOR_EACH_PRIME |
|
72
|
0
|
|
|
|
|
|
*kop = l; *skop = lsize; *nkop = n; |
|
73
|
|
|
|
|
|
|
} |
|
74
|
|
|
|
|
|
|
|
|
75
|
0
|
|
|
|
|
|
static UV rec_omega_primes(UV** ret, uint32_t k, UV lo, UV hi) { |
|
76
|
|
|
|
|
|
|
UV nkop, skop; |
|
77
|
|
|
|
|
|
|
|
|
78
|
0
|
0
|
|
|
|
|
if (hi < lo) croak("range_omega_prime_sieve error hi %"UVuf" < lo %"UVuf"\n",hi,lo); |
|
79
|
|
|
|
|
|
|
|
|
80
|
0
|
|
|
|
|
|
nkop = 0; |
|
81
|
0
|
|
|
|
|
|
skop = 256; |
|
82
|
0
|
0
|
|
|
|
|
New(0, *ret, skop, UV); |
|
83
|
0
|
|
|
|
|
|
_omega_prime_gen_rec(ret, &skop, &nkop, k, lo, hi, 1, 2); |
|
84
|
0
|
|
|
|
|
|
sort_uv_array(*ret, nkop); |
|
85
|
0
|
|
|
|
|
|
return nkop; |
|
86
|
|
|
|
|
|
|
} |
|
87
|
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
|
|
89
|
5
|
|
|
|
|
|
UV range_omega_prime_sieve(UV** ret, uint32_t k, UV lo, UV hi) { |
|
90
|
5
|
|
|
|
|
|
UV i, min, lmax = 0, n = 0; |
|
91
|
5
|
|
|
|
|
|
UV* l = 0; |
|
92
|
|
|
|
|
|
|
unsigned char *nf; |
|
93
|
|
|
|
|
|
|
|
|
94
|
5
|
50
|
|
|
|
|
if (hi < lo) croak("range_omega_prime_sieve error hi %"UVuf" < lo %"UVuf"\n",hi,lo); |
|
95
|
|
|
|
|
|
|
|
|
96
|
5
|
|
|
|
|
|
min = pn_primorial(k); |
|
97
|
5
|
50
|
|
|
|
|
if (min == 0 || min > hi) return 0; |
|
|
|
50
|
|
|
|
|
|
|
98
|
5
|
50
|
|
|
|
|
if (lo < min) lo = min; |
|
99
|
|
|
|
|
|
|
|
|
100
|
5
|
100
|
|
|
|
|
if (k == 1) return prime_power_sieve(ret, lo, hi); |
|
101
|
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
/* TODO: The recursive routine should compute primes like the count does */ |
|
103
|
4
|
50
|
|
|
|
|
if ( ((hi-lo) > 100000000UL) || (k >= 10 && (hi-lo) > 5000000UL) ) |
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
104
|
0
|
|
|
|
|
|
return rec_omega_primes(ret, k, lo, hi); |
|
105
|
|
|
|
|
|
|
|
|
106
|
4
|
|
|
|
|
|
nf = range_nfactor_sieve(lo, hi, 0); |
|
107
|
4
|
50
|
|
|
|
|
if (ret != 0) { |
|
108
|
4
|
|
|
|
|
|
lmax = 1000; |
|
109
|
4
|
50
|
|
|
|
|
New(0, l, lmax, UV); |
|
110
|
|
|
|
|
|
|
} |
|
111
|
10224
|
100
|
|
|
|
|
for (i = 0; i < hi-lo+1; i++) { |
|
112
|
10220
|
100
|
|
|
|
|
if (nf[i] != k) continue; |
|
113
|
160
|
50
|
|
|
|
|
if (l != 0) { |
|
114
|
160
|
50
|
|
|
|
|
if (n >= lmax) { lmax = 1 + lmax * 1.2; Renew(l, lmax, UV); } |
|
|
|
0
|
|
|
|
|
|
|
115
|
160
|
|
|
|
|
|
l[n] = lo+i; |
|
116
|
|
|
|
|
|
|
} |
|
117
|
160
|
|
|
|
|
|
n++; |
|
118
|
|
|
|
|
|
|
} |
|
119
|
4
|
|
|
|
|
|
Safefree(nf); |
|
120
|
4
|
50
|
|
|
|
|
if (ret != 0) *ret = l; |
|
121
|
4
|
|
|
|
|
|
return n; |
|
122
|
|
|
|
|
|
|
} |
|
123
|
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
/* TODO: Should make a single construct routine that calls sieve or recurse */ |
|
125
|
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
/********************************* Counting *********************************/ |
|
128
|
|
|
|
|
|
|
|
|
129
|
403
|
|
|
|
|
|
UV max_omega_prime_count(uint32_t k) { |
|
130
|
|
|
|
|
|
|
#if BITS_PER_WORD == 32 |
|
131
|
|
|
|
|
|
|
static const UV max[10] = {1,203287168,838888926,1389246717,1178725572,540561553,129357524,14327954,567659,4221}; |
|
132
|
|
|
|
|
|
|
if (k >= 10) return 0; |
|
133
|
|
|
|
|
|
|
#else |
|
134
|
|
|
|
|
|
|
static const UV max[16] = {1, UVCONST(425656284140516112), /* prime powers */ |
|
135
|
|
|
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* TODO: find these */ |
|
136
|
|
|
|
|
|
|
UVCONST(5512134903353),UVCONST(87133769732),UVCONST(446745559),299178 |
|
137
|
|
|
|
|
|
|
}; |
|
138
|
403
|
50
|
|
|
|
|
if (k >= 16) return 0; |
|
139
|
|
|
|
|
|
|
#endif |
|
140
|
403
|
50
|
|
|
|
|
if (k >= BITS_PER_WORD) return 0; |
|
141
|
403
|
100
|
|
|
|
|
if (max[k] == 0) return UV_MAX; |
|
142
|
81
|
|
|
|
|
|
return max[k]; |
|
143
|
|
|
|
|
|
|
} |
|
144
|
|
|
|
|
|
|
|
|
145
|
0
|
|
|
|
|
|
UV max_nth_omega_prime(uint32_t k) { |
|
146
|
|
|
|
|
|
|
#if BITS_PER_WORD == 32 |
|
147
|
|
|
|
|
|
|
static const UV offset[10] = {0,4,1,8,5,0,34,3,1305,46665}; |
|
148
|
|
|
|
|
|
|
if (k >= 10) return 0; |
|
149
|
|
|
|
|
|
|
#else |
|
150
|
|
|
|
|
|
|
static const UV offset[16] = {0,58,7,2,3,5,25,0,48,255,1155,46017,15, |
|
151
|
|
|
|
|
|
|
UVCONST(125585475),UVCONST(522131625),UVCONST(338362334325)}; |
|
152
|
0
|
0
|
|
|
|
|
if (k >= 16) return 0; |
|
153
|
|
|
|
|
|
|
#endif |
|
154
|
0
|
0
|
|
|
|
|
if (k >= BITS_PER_WORD) return 0; |
|
155
|
0
|
|
|
|
|
|
return UV_MAX - offset[k]; |
|
156
|
|
|
|
|
|
|
} |
|
157
|
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
#define RECURSIVE_OMEGA_COUNT(k,n,pr,npr) \ |
|
160
|
|
|
|
|
|
|
_omega_prime_count_rec2(k, n, 1, 2, rootint(n,k), 1, pr, npr) |
|
161
|
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
/* Initial call: m = 1, p = 2, s = sqrtn(n), j = 1 */ |
|
163
|
15357
|
|
|
|
|
|
static UV _omega_prime_count_rec2(uint32_t k, UV n, UV m, UV p, UV s, UV j, uint32_t* pr, UV numprimes) { |
|
164
|
15357
|
|
|
|
|
|
UV t, r, count = 0; |
|
165
|
|
|
|
|
|
|
|
|
166
|
15357
|
100
|
|
|
|
|
if (k == 2) { |
|
167
|
|
|
|
|
|
|
UV r2, w, u, k, rlim; |
|
168
|
23795
|
100
|
|
|
|
|
for (; p <= s; j++, p = r) { |
|
169
|
18185
|
100
|
|
|
|
|
r = (j < numprimes) ? pr[j] : next_prime(p); |
|
170
|
35667
|
50
|
|
|
|
|
for (t = m*p, w = n/t; t <= n && w >= r; t *= p, w = n/t) { |
|
|
|
100
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
#if 1 |
|
172
|
17482
|
|
|
|
|
|
count += prime_count(w) - j; |
|
173
|
17482
|
|
|
|
|
|
for (k = j, r2 = r, rlim = isqrt(w); |
|
174
|
28352
|
100
|
|
|
|
|
r2 <= rlim; |
|
175
|
10870
|
100
|
|
|
|
|
r2 = (++k < numprimes) ? pr[k] : rlim+1) { |
|
176
|
10870
|
|
|
|
|
|
u = t * r2; |
|
177
|
12630
|
100
|
|
|
|
|
do { u *= r2; count++; } while (n/r2 >= u); |
|
178
|
|
|
|
|
|
|
} |
|
179
|
|
|
|
|
|
|
#else |
|
180
|
|
|
|
|
|
|
/* This is the basic method from the definition, before optimizing */ |
|
181
|
|
|
|
|
|
|
UV q; |
|
182
|
|
|
|
|
|
|
count += prime_power_count(w); |
|
183
|
|
|
|
|
|
|
rlim = prev_prime(r); |
|
184
|
|
|
|
|
|
|
for (k = 1, q = 2; |
|
185
|
|
|
|
|
|
|
q <= rlim; |
|
186
|
|
|
|
|
|
|
q = (++k < numprimes) ? pr[k-1] : nth_prime(k)) { |
|
187
|
|
|
|
|
|
|
count -= logint(w, q); |
|
188
|
|
|
|
|
|
|
} |
|
189
|
|
|
|
|
|
|
#endif |
|
190
|
17482
|
50
|
|
|
|
|
if (t > n/p) break; |
|
191
|
|
|
|
|
|
|
} |
|
192
|
|
|
|
|
|
|
} |
|
193
|
5610
|
|
|
|
|
|
return count; |
|
194
|
|
|
|
|
|
|
} |
|
195
|
|
|
|
|
|
|
|
|
196
|
26228
|
100
|
|
|
|
|
for (; p <= s; j++, p = r) { |
|
197
|
16481
|
50
|
|
|
|
|
r = (j < numprimes) ? pr[j] : next_prime(p); |
|
198
|
30964
|
50
|
|
|
|
|
for (t = m*p; t <= n; t *= p) { |
|
199
|
30964
|
|
|
|
|
|
UV S = rootint(n/t, k-1); |
|
200
|
30964
|
100
|
|
|
|
|
if (r > S) break; |
|
201
|
14483
|
|
|
|
|
|
count += _omega_prime_count_rec2(k-1, n, t, r, S, j+1, pr, numprimes); |
|
202
|
14483
|
50
|
|
|
|
|
if (t > n/p) break; |
|
203
|
|
|
|
|
|
|
} |
|
204
|
|
|
|
|
|
|
} |
|
205
|
9747
|
|
|
|
|
|
return count; |
|
206
|
|
|
|
|
|
|
} |
|
207
|
|
|
|
|
|
|
|
|
208
|
1038
|
|
|
|
|
|
UV omega_prime_count(uint32_t k, UV n) |
|
209
|
|
|
|
|
|
|
{ |
|
210
|
|
|
|
|
|
|
uint32_t* pr; |
|
211
|
|
|
|
|
|
|
UV maxpr, npr, sum, lo; |
|
212
|
|
|
|
|
|
|
|
|
213
|
1038
|
100
|
|
|
|
|
if (k == 0) return (n >= 1); |
|
214
|
1036
|
100
|
|
|
|
|
if (k == 1) return prime_power_count(n); |
|
215
|
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
/* The first k-omega-prime is primorial(p_k) (ignoring zero for k=1) */ |
|
217
|
903
|
|
|
|
|
|
lo = pn_primorial(k); |
|
218
|
903
|
100
|
|
|
|
|
if (lo == 0 || n < lo) return 0; |
|
|
|
100
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
|
|
220
|
874
|
50
|
|
|
|
|
maxpr = rootint(n, (k > 10) ? 4 : (k > 6) ? 3 : 2); |
|
|
|
100
|
|
|
|
|
|
|
221
|
874
|
|
|
|
|
|
npr = range_prime_sieve_32(&pr, maxpr, 0); /* p[0]=2, p[1]=3,... */ |
|
222
|
874
|
|
|
|
|
|
sum = RECURSIVE_OMEGA_COUNT(k, n, pr, npr); |
|
223
|
874
|
|
|
|
|
|
Safefree(pr); |
|
224
|
874
|
|
|
|
|
|
return sum; |
|
225
|
|
|
|
|
|
|
} |
|
226
|
|
|
|
|
|
|
|
|
227
|
|
|
|
|
|
|
/* An upper bound for the omega prime count, when n >= 10^12 is shown in |
|
228
|
|
|
|
|
|
|
* Bayless,Kinlaw,Klyve 2019, page 4 |
|
229
|
|
|
|
|
|
|
* https://www.researchgate.net/profile/Paul-Kinlaw/publication/329788487_Sums_over_primitive_sets_with_a_fixed_number_of_prime_factors/links/5c44103d92851c22a3825286/Sums-over-primitive-sets-with-a-fixed-number-of-prime-factors.pdf |
|
230
|
|
|
|
|
|
|
* double logn = log(n), loglogn = log(logn); |
|
231
|
|
|
|
|
|
|
* double lim = (1.0989 * n * pow(loglogn + 1.1174, k-1)) / (factorial(k-1)*logn); |
|
232
|
|
|
|
|
|
|
*/ |
|
233
|
|
|
|
|
|
|
|
|
234
|
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
/************************************ nth ***********************************/ |
|
236
|
|
|
|
|
|
|
|
|
237
|
202
|
|
|
|
|
|
UV nth_omega_prime(uint32_t k, UV n) { |
|
238
|
|
|
|
|
|
|
UV lo, hi; |
|
239
|
|
|
|
|
|
|
|
|
240
|
202
|
50
|
|
|
|
|
if (n == 0) return 0; |
|
241
|
202
|
100
|
|
|
|
|
if (k == 0) return (n == 1) ? 1 : 0; |
|
242
|
|
|
|
|
|
|
|
|
243
|
201
|
50
|
|
|
|
|
if (k > 15 || n > max_omega_prime_count(k)) return 0; |
|
|
|
50
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
|
|
245
|
201
|
|
|
|
|
|
lo = pn_primorial(k); |
|
246
|
201
|
50
|
|
|
|
|
if (lo == 0) return 0; |
|
247
|
201
|
100
|
|
|
|
|
if (n == 1) return lo; |
|
248
|
|
|
|
|
|
|
|
|
249
|
196
|
100
|
|
|
|
|
if (k == 1) { |
|
250
|
39
|
|
|
|
|
|
hi = nth_prime(n); |
|
251
|
39
|
50
|
|
|
|
|
if (hi == 0) hi = max_nth_omega_prime(1); |
|
252
|
39
|
|
|
|
|
|
lo = hi >> 1; /* We could do better */ |
|
253
|
|
|
|
|
|
|
} else { |
|
254
|
157
|
|
|
|
|
|
hi = 0; /* Let the interpolation routine find it */ |
|
255
|
|
|
|
|
|
|
} |
|
256
|
196
|
|
|
|
|
|
hi = inverse_interpolate_k(lo, hi, n, k, &opce, 600); |
|
257
|
|
|
|
|
|
|
|
|
258
|
3330
|
100
|
|
|
|
|
while (!is_omega_prime(k,hi)) |
|
259
|
3134
|
|
|
|
|
|
hi--; |
|
260
|
|
|
|
|
|
|
/* if (omega_prime_count(k,hi) != n) croak("bad nth"); */ |
|
261
|
196
|
|
|
|
|
|
return hi; |
|
262
|
|
|
|
|
|
|
} |