File Coverage

powerfree.c
Criterion Covered Total %
statement 139 143 97.2
branch 132 156 84.6
condition n/a
subroutine n/a
pod n/a
total 271 299 90.6


line stmt bran cond sub pod time code
1             #include
2             #include
3             #include
4              
5             #define FUNC_isqrt 1
6             #define FUNC_ipow 1
7             #define FUNC_ctz 1
8             #include "ptypes.h"
9             #include "constants.h"
10             #include "powerfree.h"
11             #include "util.h"
12             #include "factor.h"
13             #include "real.h"
14              
15 2380           static INLINE UV T(UV n) {
16 2380           return (n+1)/2 * (n|1);
17             }
18 192           static UV fprod(UV n, UV r) {
19             factored_t nf;
20             UV P;
21             uint32_t i;
22              
23 192           nf = factorint(n);
24 409 100         for (P = 1, i = 0; i < nf.nfactors; i++)
25 217           P *= 1 - ipow(nf.f[i], r);
26 192           return P;
27             }
28              
29 111313           bool is_powerfree(UV n, uint32_t k)
30             {
31             factored_t nf;
32             uint32_t i;
33              
34 111313 100         if (k < 2 || n <= 1) return (n==1);
    100          
35              
36 89304 50         if (k >= BITS_PER_WORD) return 1;
37 89304 100         if (n < (UVCONST(1) << (k-1))) return 1;
38 41894 100         if (n == ((n >> k) << k)) return 0;
39 37392 100         if (k == 2) return is_square_free(n);
40              
41             /* Try to quickly find common powers so we don't have to factor */
42 29840 100         if (k == 3) {
43 8383 100         if ( !(n % 27) || !(n % 125) || !(n % 343) || !(n%1331) || !(n%2197) )
    50          
    100          
    50          
    50          
44 286           return 0;
45 8097 100         if (n < 4913) return 1;
46             }
47              
48             /* A factor iterator would be good to use here */
49 21471           nf = factorint(n);
50 59108 100         for (i = 0; i < nf.nfactors; i++) {
51 37677 100         if (nf.e[i] >= k)
52 40           return 0;
53             }
54              
55 21431           return 1;
56             }
57              
58             /* Basic method from https://arxiv.org/pdf/1107.4890.pdf */
59 100           static UV squarefree_count(UV n)
60             {
61             signed char* mu;
62             IV *M, *Mx, Mxisum, mert;
63 100           UV I, D, i, j, S1 = 0, S2 = 0;
64              
65 100 50         if (n < 4) return n;
66              
67 100           I = rootint(n, 5); /* times loglogn ^ (4/5) */
68 100           D = isqrt(n / I);
69 100           mu = range_moebius(0, D);
70              
71 100           S1 += n;
72 100 50         New(0, M, D+1, IV);
73 100           M[0] = 0;
74 100           M[1] = 1;
75 100           mert = 1;
76 862 100         for (i = 2; i <= D; i++) {
77 762 100         if (mu[i] != 0) {
78 525           S1 += mu[i] * (n/(i*i));
79 525           mert += mu[i];
80             }
81 762           M[i] = mert;
82             }
83 100           Safefree(mu);
84              
85 100 50         Newz(0, Mx, I+1, IV);
86 100           Mxisum = 0;
87 195 100         for (i = I-1; i > 0; i--) {
88 95           IV Mxi = 1;
89 95           UV xi = isqrt(n/i);
90 95           UV L = isqrt(xi);
91 649 100         for (j = 1; j <= xi/(L+1); j++)
92 554           Mxi -= M[j] * (xi/j - xi/(j+1));
93 592 100         for (j = 2; j <= L; j++)
94 497 100         Mxi -= (xi/j <= D) ? M[xi/j] : Mx[j*j*i];
95 95           Mx[i] = Mxi;
96 95           Mxisum += Mxi;
97             }
98 100           S2 = Mxisum - (I - 1) * M[D];
99 100           Safefree(Mx);
100 100           Safefree(M);
101              
102 100           return S1 + S2;
103             }
104              
105 1122           UV powerfree_count(UV n, uint32_t k)
106             {
107             UV i, nk, count;
108              
109 1122 100         if (k < 2) return (n >= 1);
110 920 100         if (n < 4) return n;
111 884 100         if (k == 2) return squarefree_count(n);
112              
113 784           count = n;
114 784           nk = rootint(n, k);
115              
116 784 100         if (nk <= 100) {
117 1298 100         for (i = 2; i <= nk; i++) {
118 516           int m = moebius(i);
119 516 100         if (m != 0)
120 445           count += m * (n / ipow(i, k));
121             }
122             } else {
123 2           signed char* mu = range_moebius(0, nk);
124 209 100         for (i = 2; i <= nk; i++)
125 207 100         if (mu[i] != 0)
126 128           count += mu[i] * (n/ipow(i,k));
127 2           Safefree(mu);
128             }
129 784           return count;
130             }
131              
132 1115           UV powerfree_sum(UV n, uint32_t k)
133             {
134             UV i, nk, sum;
135              
136 1115 100         if (k < 2) return (n >= 1);
137              
138 913 50         if (n >= (UVCONST(1) << (BITS_PER_WORD/2))) return 0; /* Overflow */
139              
140 913           sum = T(n);
141 913           nk = rootint(n, k);
142              
143 1994 100         for (i = 2; i <= nk; i++) {
144 1081           int m = moebius(i);
145 1081 100         if (m != 0) {
146 851 100         UV ik = (k==2) ? i*i : ipow(i,k);
147 851           UV nik = n / ik;
148 851           sum += m * ik * T(nik);
149             }
150             }
151 913           return sum;
152             }
153              
154              
155 4265           UV powerfree_part(UV n, uint32_t k)
156             {
157             factored_t nf;
158             UV t, P;
159             uint32_t i;
160              
161 4265 100         if (k < 2 || n <= 1)
    100          
162 1252           return (n==1);
163              
164 3013 50         if (k >= BITS_PER_WORD || n < (UVCONST(1) << (k-1)))
    100          
165 1566           return n;
166              
167             /* Pull all powers of two out */
168 1447 50         t = ctz(n);
169 1447           P = n >> t;
170 1447 100         if ((t % k)) P <<= (t % k);
171              
172 1447           nf = factorint(P);
173 3386 100         for (i = 0; i < nf.nfactors; i++)
174 1939 100         if (nf.e[i] >= k)
175 68           P /= ipow(nf.f[i], nf.e[i] - (nf.e[i] % k));
176              
177 1447           return P;
178             }
179              
180              
181 272           UV powerfree_part_sum(UV n, uint32_t k)
182             {
183 272           UV j, nk, sum = 0;
184              
185 272 100         if (k < 2 || n <= 1) return (n >= 1);
    100          
186              
187 192 50         if (n >= (UVCONST(1) << (BITS_PER_WORD/2))) return 0; /* Overflow */
188              
189 192           sum = T(n);
190 192           nk = rootint(n,k);
191              
192             /* Using the factor iterator is overkill because of the limited range. */
193              
194 192 100         if (nk <= 100) {
195 383 100         for (j = 2; j <= nk; j++)
196 192           sum += fprod(j,k) * T(n/ipow(j,k));
197             } else {
198             UV P, *factors;
199             factor_range_context_t fctx;
200             int i, nfactors;
201              
202 1           fctx = factor_range_init(2, nk, 0);
203 233 100         for (j = 2; j <= nk; j++) {
204 232           nfactors = factor_range_next(&fctx);
205 232           factors = fctx.factors;
206 833 100         for (P = 1, i = 0; i < nfactors; i++)
207 601 100         if (i == 0 || factors[i] != factors[i-1])
    100          
208 438           P *= 1 - ipow(factors[i], k);
209 232           sum += P * T(n/ipow(j,k));
210             }
211 1           factor_range_destroy(&fctx);
212             }
213              
214 192           return sum;
215             }
216              
217             #if BITS_PER_WORD == 64
218             #define MAX_PFC2 UVCONST(11214275663373200251)
219             #define MAX_PFC3 UVCONST(15345982395028449439)
220             #define MAX_PFC4 UVCONST(17043655258566511333)
221             #else
222             #define MAX_PFC2 UVCONST(2611027094)
223             #define MAX_PFC3 UVCONST(3573014938)
224             #define MAX_PFC4 UVCONST(3968285222)
225             #endif
226              
227 7           UV nth_powerfree(UV n, uint32_t k)
228             {
229             long double zm;
230             UV qk, count, diff, thresh, i;
231              
232 7 50         if (k < 2) return 0;
233 7 50         if (n < 4) return n;
234              
235             /* Check for overflow. */
236 7 100         if (k == 2 && n > MAX_PFC2) return 0;
    50          
237 7 100         if (k == 3 && n > MAX_PFC3) return 0;
    50          
238 7 100         if (k >= 4 && n > MAX_PFC4) {
    50          
239 0 0         if (k == 4) return 0;
240 0 0         if (n > powerfree_count(UV_MAX,k)) return 0;
241             }
242              
243             /* Step 1: Density ZM and expected value QK. */
244 7           zm = 1.0 + ld_riemann_zeta(k);
245 7           qk = (UV)(zm * (long double) n + 0.5);
246 7 100         thresh = (k <= 2) ? 200 : (k == 3) ? 60 : (k == 4) ? 2 : 1;
    100          
    100          
247              
248 7 50         for (i = 0; i < 10; i++) {
249             /* Step 2: Initial count at QK and difference from goal. */
250 7           count = powerfree_count(qk, k);
251 7 100         diff = (count >= n) ? count-n : n-count;
252             /* Step 3: Update estimate using expected density. */
253 7 50         if (diff <= thresh) break;
254 0 0         if (count > n) qk -= (UV)((long double)diff * zm);
255 0           else qk += (UV)((long double)diff * zm);
256             }
257              
258             /* Step 4: Get ourselves onto a powerfree number */
259 11 100         while (!is_powerfree(qk,k)) qk--;
260              
261             /* Step 5: Walk forwards or backwards until we get to the goal. */
262 23 100         while (count != n) {
263 25 100         do { qk += (count < n) ? 1 : -1; } while (!is_powerfree(qk,k));
    100          
264 16 100         count += (count < n) ? 1 : -1;
265             }
266 7           return qk;
267             }
268              
269             /******************************************************************************/
270              
271 9           UV squarefree_kernel(UV n)
272             {
273             factored_t nf;
274             UV P;
275             uint32_t i;
276              
277 9           nf = factorint(n);
278 30 100         for (P = 1, i = 0; i < nf.nfactors; i++)
279 21           P *= nf.f[i];
280 9           return P;
281             }