perfpow.c revision 1.1.1.4 1 1.1 mrg /* mpn_perfect_power_p -- mpn perfect power detection.
2 1.1 mrg
3 1.1 mrg Contributed to the GNU project by Martin Boij.
4 1.1 mrg
5 1.1.1.3 mrg Copyright 2009, 2010, 2012, 2014 Free Software Foundation, Inc.
6 1.1 mrg
7 1.1 mrg This file is part of the GNU MP Library.
8 1.1 mrg
9 1.1 mrg The GNU MP Library is free software; you can redistribute it and/or modify
10 1.1.1.3 mrg it under the terms of either:
11 1.1.1.3 mrg
12 1.1.1.3 mrg * the GNU Lesser General Public License as published by the Free
13 1.1.1.3 mrg Software Foundation; either version 3 of the License, or (at your
14 1.1.1.3 mrg option) any later version.
15 1.1.1.3 mrg
16 1.1.1.3 mrg or
17 1.1.1.3 mrg
18 1.1.1.3 mrg * the GNU General Public License as published by the Free Software
19 1.1.1.3 mrg Foundation; either version 2 of the License, or (at your option) any
20 1.1.1.3 mrg later version.
21 1.1.1.3 mrg
22 1.1.1.3 mrg or both in parallel, as here.
23 1.1 mrg
24 1.1 mrg The GNU MP Library is distributed in the hope that it will be useful, but
25 1.1 mrg WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
26 1.1.1.3 mrg or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
27 1.1.1.3 mrg for more details.
28 1.1 mrg
29 1.1.1.3 mrg You should have received copies of the GNU General Public License and the
30 1.1.1.3 mrg GNU Lesser General Public License along with the GNU MP Library. If not,
31 1.1.1.3 mrg see https://www.gnu.org/licenses/. */
32 1.1 mrg
33 1.1 mrg #include "gmp-impl.h"
34 1.1 mrg #include "longlong.h"
35 1.1 mrg
36 1.1 mrg #define SMALL 20
37 1.1 mrg #define MEDIUM 100
38 1.1 mrg
39 1.1.1.2 mrg /* Return non-zero if {np,nn} == {xp,xn} ^ k.
40 1.1 mrg Algorithm:
41 1.1.1.2 mrg For s = 1, 2, 4, ..., s_max, compute the s least significant limbs of
42 1.1.1.2 mrg {xp,xn}^k. Stop if they don't match the s least significant limbs of
43 1.1.1.2 mrg {np,nn}.
44 1.1.1.2 mrg
45 1.1.1.2 mrg FIXME: Low xn limbs can be expected to always match, if computed as a mod
46 1.1.1.2 mrg B^{xn} root. So instead of using mpn_powlo, compute an approximation of the
47 1.1.1.2 mrg most significant (normalized) limb of {xp,xn} ^ k (and an error bound), and
48 1.1.1.2 mrg compare to {np, nn}. Or use an even cruder approximation based on fix-point
49 1.1.1.2 mrg base 2 logarithm. */
50 1.1 mrg static int
51 1.1.1.2 mrg pow_equals (mp_srcptr np, mp_size_t n,
52 1.1 mrg mp_srcptr xp,mp_size_t xn,
53 1.1 mrg mp_limb_t k, mp_bitcnt_t f,
54 1.1 mrg mp_ptr tp)
55 1.1 mrg {
56 1.1.1.2 mrg mp_bitcnt_t y, z;
57 1.1.1.3 mrg mp_size_t bn;
58 1.1 mrg mp_limb_t h, l;
59 1.1 mrg
60 1.1.1.2 mrg ASSERT (n > 1 || (n == 1 && np[0] > 1));
61 1.1.1.2 mrg ASSERT (np[n - 1] > 0);
62 1.1 mrg ASSERT (xn > 0);
63 1.1 mrg
64 1.1 mrg if (xn == 1 && xp[0] == 1)
65 1.1 mrg return 0;
66 1.1 mrg
67 1.1.1.2 mrg z = 1 + (n >> 1);
68 1.1 mrg for (bn = 1; bn < z; bn <<= 1)
69 1.1 mrg {
70 1.1 mrg mpn_powlo (tp, xp, &k, 1, bn, tp + bn);
71 1.1 mrg if (mpn_cmp (tp, np, bn) != 0)
72 1.1 mrg return 0;
73 1.1 mrg }
74 1.1 mrg
75 1.1.1.2 mrg /* Final check. Estimate the size of {xp,xn}^k before computing the power
76 1.1.1.2 mrg with full precision. Optimization: It might pay off to make a more
77 1.1.1.2 mrg accurate estimation of the logarithm of {xp,xn}, rather than using the
78 1.1.1.2 mrg index of the MSB. */
79 1.1 mrg
80 1.1.1.2 mrg MPN_SIZEINBASE_2EXP(y, xp, xn, 1);
81 1.1.1.2 mrg y -= 1; /* msb_index (xp, xn) */
82 1.1 mrg
83 1.1 mrg umul_ppmm (h, l, k, y);
84 1.1.1.3 mrg h -= l == 0; --l; /* two-limb decrement */
85 1.1 mrg
86 1.1.1.2 mrg z = f - 1; /* msb_index (np, n) */
87 1.1 mrg if (h == 0 && l <= z)
88 1.1 mrg {
89 1.1.1.3 mrg mp_limb_t *tp2;
90 1.1.1.3 mrg mp_size_t i;
91 1.1.1.3 mrg int ans;
92 1.1 mrg mp_limb_t size;
93 1.1.1.3 mrg TMP_DECL;
94 1.1.1.3 mrg
95 1.1 mrg size = l + k;
96 1.1 mrg ASSERT_ALWAYS (size >= k);
97 1.1 mrg
98 1.1.1.3 mrg TMP_MARK;
99 1.1 mrg y = 2 + size / GMP_LIMB_BITS;
100 1.1 mrg tp2 = TMP_ALLOC_LIMBS (y);
101 1.1 mrg
102 1.1 mrg i = mpn_pow_1 (tp, xp, xn, k, tp2);
103 1.1.1.2 mrg if (i == n && mpn_cmp (tp, np, n) == 0)
104 1.1 mrg ans = 1;
105 1.1 mrg else
106 1.1 mrg ans = 0;
107 1.1.1.3 mrg TMP_FREE;
108 1.1.1.3 mrg return ans;
109 1.1 mrg }
110 1.1 mrg
111 1.1.1.3 mrg return 0;
112 1.1 mrg }
113 1.1 mrg
114 1.1 mrg
115 1.1.1.2 mrg /* Return non-zero if N = {np,n} is a kth power.
116 1.1.1.2 mrg I = {ip,n} = N^(-1) mod B^n. */
117 1.1 mrg static int
118 1.1 mrg is_kth_power (mp_ptr rp, mp_srcptr np,
119 1.1.1.2 mrg mp_limb_t k, mp_srcptr ip,
120 1.1.1.2 mrg mp_size_t n, mp_bitcnt_t f,
121 1.1 mrg mp_ptr tp)
122 1.1 mrg {
123 1.1 mrg mp_bitcnt_t b;
124 1.1.1.2 mrg mp_size_t rn, xn;
125 1.1 mrg
126 1.1.1.2 mrg ASSERT (n > 0);
127 1.1.1.2 mrg ASSERT ((k & 1) != 0 || k == 2);
128 1.1 mrg ASSERT ((np[0] & 1) != 0);
129 1.1 mrg
130 1.1 mrg if (k == 2)
131 1.1 mrg {
132 1.1 mrg b = (f + 1) >> 1;
133 1.1 mrg rn = 1 + b / GMP_LIMB_BITS;
134 1.1.1.2 mrg if (mpn_bsqrtinv (rp, ip, b, tp) != 0)
135 1.1 mrg {
136 1.1.1.2 mrg rp[rn - 1] &= (CNST_LIMB(1) << (b % GMP_LIMB_BITS)) - 1;
137 1.1 mrg xn = rn;
138 1.1 mrg MPN_NORMALIZE (rp, xn);
139 1.1.1.2 mrg if (pow_equals (np, n, rp, xn, k, f, tp) != 0)
140 1.1 mrg return 1;
141 1.1 mrg
142 1.1.1.2 mrg /* Check if (2^b - r)^2 == n */
143 1.1.1.2 mrg mpn_neg (rp, rp, rn);
144 1.1.1.2 mrg rp[rn - 1] &= (CNST_LIMB(1) << (b % GMP_LIMB_BITS)) - 1;
145 1.1 mrg MPN_NORMALIZE (rp, rn);
146 1.1.1.2 mrg if (pow_equals (np, n, rp, rn, k, f, tp) != 0)
147 1.1 mrg return 1;
148 1.1 mrg }
149 1.1 mrg }
150 1.1 mrg else
151 1.1 mrg {
152 1.1 mrg b = 1 + (f - 1) / k;
153 1.1 mrg rn = 1 + (b - 1) / GMP_LIMB_BITS;
154 1.1.1.2 mrg mpn_brootinv (rp, ip, rn, k, tp);
155 1.1.1.2 mrg if ((b % GMP_LIMB_BITS) != 0)
156 1.1.1.2 mrg rp[rn - 1] &= (CNST_LIMB(1) << (b % GMP_LIMB_BITS)) - 1;
157 1.1 mrg MPN_NORMALIZE (rp, rn);
158 1.1.1.2 mrg if (pow_equals (np, n, rp, rn, k, f, tp) != 0)
159 1.1 mrg return 1;
160 1.1 mrg }
161 1.1 mrg MPN_ZERO (rp, rn); /* Untrash rp */
162 1.1 mrg return 0;
163 1.1 mrg }
164 1.1 mrg
165 1.1 mrg static int
166 1.1.1.2 mrg perfpow (mp_srcptr np, mp_size_t n,
167 1.1 mrg mp_limb_t ub, mp_limb_t g,
168 1.1 mrg mp_bitcnt_t f, int neg)
169 1.1 mrg {
170 1.1.1.2 mrg mp_ptr ip, tp, rp;
171 1.1.1.2 mrg mp_limb_t k;
172 1.1.1.2 mrg int ans;
173 1.1 mrg mp_bitcnt_t b;
174 1.1 mrg gmp_primesieve_t ps;
175 1.1 mrg TMP_DECL;
176 1.1 mrg
177 1.1.1.2 mrg ASSERT (n > 0);
178 1.1 mrg ASSERT ((np[0] & 1) != 0);
179 1.1 mrg ASSERT (ub > 0);
180 1.1 mrg
181 1.1 mrg TMP_MARK;
182 1.1 mrg gmp_init_primesieve (&ps);
183 1.1 mrg b = (f + 3) >> 1;
184 1.1 mrg
185 1.1.1.3 mrg TMP_ALLOC_LIMBS_3 (ip, n, rp, n, tp, 5 * n);
186 1.1.1.3 mrg
187 1.1.1.2 mrg MPN_ZERO (rp, n);
188 1.1.1.2 mrg
189 1.1.1.2 mrg /* FIXME: It seems the inverse in ninv is needed only to get non-inverted
190 1.1.1.2 mrg roots. I.e., is_kth_power computes n^{1/2} as (n^{-1})^{-1/2} and
191 1.1.1.2 mrg similarly for nth roots. It should be more efficient to compute n^{1/2} as
192 1.1.1.2 mrg n * n^{-1/2}, with a mullo instead of a binvert. And we can do something
193 1.1.1.2 mrg similar for kth roots if we switch to an iteration converging to n^{1/k -
194 1.1.1.2 mrg 1}, and we can then eliminate this binvert call. */
195 1.1.1.2 mrg mpn_binvert (ip, np, 1 + (b - 1) / GMP_LIMB_BITS, tp);
196 1.1 mrg if (b % GMP_LIMB_BITS)
197 1.1.1.2 mrg ip[(b - 1) / GMP_LIMB_BITS] &= (CNST_LIMB(1) << (b % GMP_LIMB_BITS)) - 1;
198 1.1 mrg
199 1.1 mrg if (neg)
200 1.1 mrg gmp_nextprime (&ps);
201 1.1 mrg
202 1.1.1.2 mrg ans = 0;
203 1.1 mrg if (g > 0)
204 1.1 mrg {
205 1.1 mrg ub = MIN (ub, g + 1);
206 1.1 mrg while ((k = gmp_nextprime (&ps)) < ub)
207 1.1 mrg {
208 1.1 mrg if ((g % k) == 0)
209 1.1 mrg {
210 1.1.1.2 mrg if (is_kth_power (rp, np, k, ip, n, f, tp) != 0)
211 1.1 mrg {
212 1.1 mrg ans = 1;
213 1.1 mrg goto ret;
214 1.1 mrg }
215 1.1 mrg }
216 1.1 mrg }
217 1.1 mrg }
218 1.1 mrg else
219 1.1 mrg {
220 1.1 mrg while ((k = gmp_nextprime (&ps)) < ub)
221 1.1 mrg {
222 1.1.1.2 mrg if (is_kth_power (rp, np, k, ip, n, f, tp) != 0)
223 1.1 mrg {
224 1.1 mrg ans = 1;
225 1.1 mrg goto ret;
226 1.1 mrg }
227 1.1 mrg }
228 1.1 mrg }
229 1.1 mrg ret:
230 1.1 mrg TMP_FREE;
231 1.1 mrg return ans;
232 1.1 mrg }
233 1.1 mrg
234 1.1 mrg static const unsigned short nrtrial[] = { 100, 500, 1000 };
235 1.1 mrg
236 1.1.1.2 mrg /* Table of (log_{p_i} 2) values, where p_i is the (nrtrial[i] + 1)'th prime
237 1.1.1.2 mrg number. */
238 1.1.1.2 mrg static const double logs[] =
239 1.1.1.2 mrg { 0.1099457228193620, 0.0847016403115322, 0.0772048195144415 };
240 1.1 mrg
241 1.1 mrg int
242 1.1.1.2 mrg mpn_perfect_power_p (mp_srcptr np, mp_size_t n)
243 1.1 mrg {
244 1.1.1.2 mrg mp_limb_t *nc, factor, g;
245 1.1.1.3 mrg mp_limb_t exp, d;
246 1.1.1.2 mrg mp_bitcnt_t twos, count;
247 1.1.1.2 mrg int ans, where, neg, trial;
248 1.1 mrg TMP_DECL;
249 1.1 mrg
250 1.1.1.3 mrg neg = n < 0;
251 1.1.1.3 mrg if (neg)
252 1.1 mrg {
253 1.1.1.2 mrg n = -n;
254 1.1 mrg }
255 1.1 mrg
256 1.1.1.3 mrg if (n == 0 || (n == 1 && np[0] == 1)) /* Valgrind doesn't like
257 1.1.1.3 mrg (n <= (np[0] == 1)) */
258 1.1 mrg return 1;
259 1.1 mrg
260 1.1 mrg TMP_MARK;
261 1.1 mrg
262 1.1.1.3 mrg count = 0;
263 1.1.1.2 mrg
264 1.1 mrg twos = mpn_scan1 (np, 0);
265 1.1.1.3 mrg if (twos != 0)
266 1.1 mrg {
267 1.1.1.3 mrg mp_size_t s;
268 1.1 mrg if (twos == 1)
269 1.1 mrg {
270 1.1.1.3 mrg return 0;
271 1.1 mrg }
272 1.1 mrg s = twos / GMP_LIMB_BITS;
273 1.1.1.2 mrg if (s + 1 == n && POW2_P (np[s]))
274 1.1 mrg {
275 1.1.1.3 mrg return ! (neg && POW2_P (twos));
276 1.1 mrg }
277 1.1 mrg count = twos % GMP_LIMB_BITS;
278 1.1.1.3 mrg n -= s;
279 1.1.1.3 mrg np += s;
280 1.1 mrg if (count > 0)
281 1.1 mrg {
282 1.1.1.3 mrg nc = TMP_ALLOC_LIMBS (n);
283 1.1.1.3 mrg mpn_rshift (nc, np, n, count);
284 1.1.1.3 mrg n -= (nc[n - 1] == 0);
285 1.1.1.3 mrg np = nc;
286 1.1 mrg }
287 1.1 mrg }
288 1.1.1.3 mrg g = twos;
289 1.1 mrg
290 1.1.1.3 mrg trial = (n > SMALL) + (n > MEDIUM);
291 1.1 mrg
292 1.1.1.2 mrg where = 0;
293 1.1.1.3 mrg factor = mpn_trialdiv (np, n, nrtrial[trial], &where);
294 1.1 mrg
295 1.1 mrg if (factor != 0)
296 1.1 mrg {
297 1.1.1.3 mrg if (count == 0) /* We did not allocate nc yet. */
298 1.1 mrg {
299 1.1.1.3 mrg nc = TMP_ALLOC_LIMBS (n);
300 1.1 mrg }
301 1.1 mrg
302 1.1.1.3 mrg /* Remove factors found by trialdiv. Optimization: If remove
303 1.1.1.3 mrg define _itch, we can allocate its scratch just once */
304 1.1 mrg
305 1.1 mrg do
306 1.1 mrg {
307 1.1 mrg binvert_limb (d, factor);
308 1.1 mrg
309 1.1.1.3 mrg /* After the first round we always have nc == np */
310 1.1.1.3 mrg exp = mpn_remove (nc, &n, np, n, &d, 1, ~(mp_bitcnt_t)0);
311 1.1 mrg
312 1.1 mrg if (g == 0)
313 1.1 mrg g = exp;
314 1.1 mrg else
315 1.1 mrg g = mpn_gcd_1 (&g, 1, exp);
316 1.1 mrg
317 1.1 mrg if (g == 1)
318 1.1 mrg {
319 1.1 mrg ans = 0;
320 1.1 mrg goto ret;
321 1.1 mrg }
322 1.1 mrg
323 1.1.1.3 mrg if ((n == 1) & (nc[0] == 1))
324 1.1 mrg {
325 1.1 mrg ans = ! (neg && POW2_P (g));
326 1.1 mrg goto ret;
327 1.1 mrg }
328 1.1 mrg
329 1.1.1.3 mrg np = nc;
330 1.1.1.3 mrg factor = mpn_trialdiv (np, n, nrtrial[trial], &where);
331 1.1 mrg }
332 1.1 mrg while (factor != 0);
333 1.1 mrg }
334 1.1 mrg
335 1.1.1.3 mrg MPN_SIZEINBASE_2EXP(count, np, n, 1); /* log (np) + 1 */
336 1.1 mrg d = (mp_limb_t) (count * logs[trial] + 1e-9) + 1;
337 1.1.1.3 mrg ans = perfpow (np, n, d, g, count, neg);
338 1.1 mrg
339 1.1 mrg ret:
340 1.1 mrg TMP_FREE;
341 1.1 mrg return ans;
342 1.1 mrg }
343