perfpow.c revision 1.1.1.1 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 mrg Copyright 2009, 2010 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 mrg it under the terms of the GNU Lesser General Public License as published by
11 1.1 mrg the Free Software Foundation; either version 3 of the License, or (at your
12 1.1 mrg option) any later version.
13 1.1 mrg
14 1.1 mrg The GNU MP Library is distributed in the hope that it will be useful, but
15 1.1 mrg WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16 1.1 mrg or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
17 1.1 mrg License for more details.
18 1.1 mrg
19 1.1 mrg You should have received a copy of the GNU Lesser General Public License
20 1.1 mrg along with the GNU MP Library. If not, see http://www.gnu.org/licenses/. */
21 1.1 mrg
22 1.1 mrg #include "gmp.h"
23 1.1 mrg #include "gmp-impl.h"
24 1.1 mrg #include "longlong.h"
25 1.1 mrg
26 1.1 mrg #define SMALL 20
27 1.1 mrg #define MEDIUM 100
28 1.1 mrg
29 1.1 mrg /*
30 1.1 mrg Returns non-zero if {np,nn} == {xp,xn} ^ k.
31 1.1 mrg Algorithm:
32 1.1 mrg For s = 1, 2, 4, ..., s_max, compute the s least significant
33 1.1 mrg limbs of {xp,xn}^k. Stop if they don't match the s least
34 1.1 mrg significant limbs of {np,nn}.
35 1.1 mrg */
36 1.1 mrg static int
37 1.1 mrg pow_equals (mp_srcptr np, mp_size_t nn,
38 1.1 mrg mp_srcptr xp,mp_size_t xn,
39 1.1 mrg mp_limb_t k, mp_bitcnt_t f,
40 1.1 mrg mp_ptr tp)
41 1.1 mrg {
42 1.1 mrg mp_limb_t *tp2;
43 1.1 mrg mp_bitcnt_t y, z, count;
44 1.1 mrg mp_size_t i, bn;
45 1.1 mrg int ans;
46 1.1 mrg mp_limb_t h, l;
47 1.1 mrg TMP_DECL;
48 1.1 mrg
49 1.1 mrg ASSERT (nn > 1 || (nn == 1 && np[0] > 1));
50 1.1 mrg ASSERT (np[nn - 1] > 0);
51 1.1 mrg ASSERT (xn > 0);
52 1.1 mrg
53 1.1 mrg if (xn == 1 && xp[0] == 1)
54 1.1 mrg return 0;
55 1.1 mrg
56 1.1 mrg z = 1 + (nn >> 1);
57 1.1 mrg for (bn = 1; bn < z; bn <<= 1)
58 1.1 mrg {
59 1.1 mrg mpn_powlo (tp, xp, &k, 1, bn, tp + bn);
60 1.1 mrg if (mpn_cmp (tp, np, bn) != 0)
61 1.1 mrg return 0;
62 1.1 mrg }
63 1.1 mrg
64 1.1 mrg TMP_MARK;
65 1.1 mrg
66 1.1 mrg /* Final check. Estimate the size of {xp,xn}^k before computing
67 1.1 mrg the power with full precision.
68 1.1 mrg Optimization: It might pay off to make a more accurate estimation of
69 1.1 mrg the logarithm of {xp,xn}, rather than using the index of the MSB.
70 1.1 mrg */
71 1.1 mrg
72 1.1 mrg count_leading_zeros (count, xp[xn - 1]);
73 1.1 mrg y = xn * GMP_LIMB_BITS - count - 1; /* msb_index (xp, xn) */
74 1.1 mrg
75 1.1 mrg umul_ppmm (h, l, k, y);
76 1.1 mrg h -= l == 0; l--; /* two-limb decrement */
77 1.1 mrg
78 1.1 mrg z = f - 1; /* msb_index (np, nn) */
79 1.1 mrg if (h == 0 && l <= z)
80 1.1 mrg {
81 1.1 mrg mp_limb_t size;
82 1.1 mrg size = l + k;
83 1.1 mrg ASSERT_ALWAYS (size >= k);
84 1.1 mrg
85 1.1 mrg y = 2 + size / GMP_LIMB_BITS;
86 1.1 mrg tp2 = TMP_ALLOC_LIMBS (y);
87 1.1 mrg
88 1.1 mrg i = mpn_pow_1 (tp, xp, xn, k, tp2);
89 1.1 mrg if (i == nn && mpn_cmp (tp, np, nn) == 0)
90 1.1 mrg ans = 1;
91 1.1 mrg else
92 1.1 mrg ans = 0;
93 1.1 mrg }
94 1.1 mrg else
95 1.1 mrg {
96 1.1 mrg ans = 0;
97 1.1 mrg }
98 1.1 mrg
99 1.1 mrg TMP_FREE;
100 1.1 mrg return ans;
101 1.1 mrg }
102 1.1 mrg
103 1.1 mrg /*
104 1.1 mrg Computes rp such that rp^k * yp = 1 (mod 2^b).
105 1.1 mrg Algorithm:
106 1.1 mrg Apply Hensel lifting repeatedly, each time
107 1.1 mrg doubling (approx.) the number of known bits in rp.
108 1.1 mrg */
109 1.1 mrg static void
110 1.1 mrg binv_root (mp_ptr rp, mp_srcptr yp,
111 1.1 mrg mp_limb_t k, mp_size_t bn,
112 1.1 mrg mp_bitcnt_t b, mp_ptr tp)
113 1.1 mrg {
114 1.1 mrg mp_limb_t *tp2 = tp + bn, *tp3 = tp + 2 * bn, di, k2 = k + 1;
115 1.1 mrg mp_bitcnt_t order[GMP_LIMB_BITS * 2];
116 1.1 mrg int i, d = 0;
117 1.1 mrg
118 1.1 mrg ASSERT (bn > 0);
119 1.1 mrg ASSERT (b > 0);
120 1.1 mrg ASSERT ((k & 1) != 0);
121 1.1 mrg
122 1.1 mrg binvert_limb (di, k);
123 1.1 mrg
124 1.1 mrg rp[0] = 1;
125 1.1 mrg for (; b != 1; b = (b + 1) >> 1)
126 1.1 mrg order[d++] = b;
127 1.1 mrg
128 1.1 mrg for (i = d - 1; i >= 0; i--)
129 1.1 mrg {
130 1.1 mrg b = order[i];
131 1.1 mrg bn = 1 + (b - 1) / GMP_LIMB_BITS;
132 1.1 mrg
133 1.1 mrg mpn_mul_1 (tp, rp, bn, k2);
134 1.1 mrg
135 1.1 mrg mpn_powlo (tp2, rp, &k2, 1, bn, tp3);
136 1.1 mrg mpn_mullo_n (rp, yp, tp2, bn);
137 1.1 mrg
138 1.1 mrg mpn_sub_n (tp2, tp, rp, bn);
139 1.1 mrg mpn_pi1_bdiv_q_1 (rp, tp2, bn, k, di, 0);
140 1.1 mrg if ((b % GMP_LIMB_BITS) != 0)
141 1.1 mrg rp[(b - 1) / GMP_LIMB_BITS] &= (((mp_limb_t) 1) << (b % GMP_LIMB_BITS)) - 1;
142 1.1 mrg }
143 1.1 mrg return;
144 1.1 mrg }
145 1.1 mrg
146 1.1 mrg /*
147 1.1 mrg Computes rp such that rp^2 * yp = 1 (mod 2^{b+1}).
148 1.1 mrg Returns non-zero if such an integer rp exists.
149 1.1 mrg */
150 1.1 mrg static int
151 1.1 mrg binv_sqroot (mp_ptr rp, mp_srcptr yp,
152 1.1 mrg mp_size_t bn, mp_bitcnt_t b,
153 1.1 mrg mp_ptr tp)
154 1.1 mrg {
155 1.1 mrg mp_limb_t k = 3, *tp2 = tp + bn, *tp3 = tp + (bn << 1);
156 1.1 mrg mp_bitcnt_t order[GMP_LIMB_BITS * 2];
157 1.1 mrg int i, d = 0;
158 1.1 mrg
159 1.1 mrg ASSERT (bn > 0);
160 1.1 mrg ASSERT (b > 0);
161 1.1 mrg
162 1.1 mrg rp[0] = 1;
163 1.1 mrg if (b == 1)
164 1.1 mrg {
165 1.1 mrg if ((yp[0] & 3) != 1)
166 1.1 mrg return 0;
167 1.1 mrg }
168 1.1 mrg else
169 1.1 mrg {
170 1.1 mrg if ((yp[0] & 7) != 1)
171 1.1 mrg return 0;
172 1.1 mrg
173 1.1 mrg for (; b != 2; b = (b + 2) >> 1)
174 1.1 mrg order[d++] = b;
175 1.1 mrg
176 1.1 mrg for (i = d - 1; i >= 0; i--)
177 1.1 mrg {
178 1.1 mrg b = order[i];
179 1.1 mrg bn = 1 + b / GMP_LIMB_BITS;
180 1.1 mrg
181 1.1 mrg mpn_mul_1 (tp, rp, bn, k);
182 1.1 mrg
183 1.1 mrg mpn_powlo (tp2, rp, &k, 1, bn, tp3);
184 1.1 mrg mpn_mullo_n (rp, yp, tp2, bn);
185 1.1 mrg
186 1.1 mrg #if HAVE_NATIVE_mpn_rsh1sub_n
187 1.1 mrg mpn_rsh1sub_n (rp, tp, rp, bn);
188 1.1 mrg #else
189 1.1 mrg mpn_sub_n (tp2, tp, rp, bn);
190 1.1 mrg mpn_rshift (rp, tp2, bn, 1);
191 1.1 mrg #endif
192 1.1 mrg rp[b / GMP_LIMB_BITS] &= (((mp_limb_t) 1) << (b % GMP_LIMB_BITS)) - 1;
193 1.1 mrg }
194 1.1 mrg }
195 1.1 mrg return 1;
196 1.1 mrg }
197 1.1 mrg
198 1.1 mrg /*
199 1.1 mrg Returns non-zero if {np,nn} is a kth power.
200 1.1 mrg */
201 1.1 mrg static int
202 1.1 mrg is_kth_power (mp_ptr rp, mp_srcptr np,
203 1.1 mrg mp_limb_t k, mp_srcptr yp,
204 1.1 mrg mp_size_t nn, mp_bitcnt_t f,
205 1.1 mrg mp_ptr tp)
206 1.1 mrg {
207 1.1 mrg mp_limb_t x, c;
208 1.1 mrg mp_bitcnt_t b;
209 1.1 mrg mp_size_t i, rn, xn;
210 1.1 mrg
211 1.1 mrg ASSERT (nn > 0);
212 1.1 mrg ASSERT (((k & 1) != 0) || (k == 2));
213 1.1 mrg ASSERT ((np[0] & 1) != 0);
214 1.1 mrg
215 1.1 mrg if (k == 2)
216 1.1 mrg {
217 1.1 mrg b = (f + 1) >> 1;
218 1.1 mrg rn = 1 + b / GMP_LIMB_BITS;
219 1.1 mrg if (binv_sqroot (rp, yp, rn, b, tp) != 0)
220 1.1 mrg {
221 1.1 mrg xn = rn;
222 1.1 mrg MPN_NORMALIZE (rp, xn);
223 1.1 mrg if (pow_equals (np, nn, rp, xn, k, f, tp) != 0)
224 1.1 mrg return 1;
225 1.1 mrg
226 1.1 mrg /* Check if (2^b - rp)^2 == np */
227 1.1 mrg c = 0;
228 1.1 mrg for (i = 0; i < rn; i++)
229 1.1 mrg {
230 1.1 mrg x = rp[i];
231 1.1 mrg rp[i] = -x - c;
232 1.1 mrg c |= (x != 0);
233 1.1 mrg }
234 1.1 mrg rp[rn - 1] &= (((mp_limb_t) 1) << (b % GMP_LIMB_BITS)) - 1;
235 1.1 mrg MPN_NORMALIZE (rp, rn);
236 1.1 mrg if (pow_equals (np, nn, rp, rn, k, f, tp) != 0)
237 1.1 mrg return 1;
238 1.1 mrg }
239 1.1 mrg }
240 1.1 mrg else
241 1.1 mrg {
242 1.1 mrg b = 1 + (f - 1) / k;
243 1.1 mrg rn = 1 + (b - 1) / GMP_LIMB_BITS;
244 1.1 mrg binv_root (rp, yp, k, rn, b, tp);
245 1.1 mrg MPN_NORMALIZE (rp, rn);
246 1.1 mrg if (pow_equals (np, nn, rp, rn, k, f, tp) != 0)
247 1.1 mrg return 1;
248 1.1 mrg }
249 1.1 mrg MPN_ZERO (rp, rn); /* Untrash rp */
250 1.1 mrg return 0;
251 1.1 mrg }
252 1.1 mrg
253 1.1 mrg static int
254 1.1 mrg perfpow (mp_srcptr np, mp_size_t nn,
255 1.1 mrg mp_limb_t ub, mp_limb_t g,
256 1.1 mrg mp_bitcnt_t f, int neg)
257 1.1 mrg {
258 1.1 mrg mp_limb_t *yp, *tp, k = 0, *rp1;
259 1.1 mrg int ans = 0;
260 1.1 mrg mp_bitcnt_t b;
261 1.1 mrg gmp_primesieve_t ps;
262 1.1 mrg TMP_DECL;
263 1.1 mrg
264 1.1 mrg ASSERT (nn > 0);
265 1.1 mrg ASSERT ((np[0] & 1) != 0);
266 1.1 mrg ASSERT (ub > 0);
267 1.1 mrg
268 1.1 mrg TMP_MARK;
269 1.1 mrg gmp_init_primesieve (&ps);
270 1.1 mrg b = (f + 3) >> 1;
271 1.1 mrg
272 1.1 mrg yp = TMP_ALLOC_LIMBS (nn);
273 1.1 mrg rp1 = TMP_ALLOC_LIMBS (nn);
274 1.1 mrg tp = TMP_ALLOC_LIMBS (5 * nn); /* FIXME */
275 1.1 mrg MPN_ZERO (rp1, nn);
276 1.1 mrg
277 1.1 mrg mpn_binvert (yp, np, 1 + (b - 1) / GMP_LIMB_BITS, tp);
278 1.1 mrg if (b % GMP_LIMB_BITS)
279 1.1 mrg yp[(b - 1) / GMP_LIMB_BITS] &= (((mp_limb_t) 1) << (b % GMP_LIMB_BITS)) - 1;
280 1.1 mrg
281 1.1 mrg if (neg)
282 1.1 mrg gmp_nextprime (&ps);
283 1.1 mrg
284 1.1 mrg if (g > 0)
285 1.1 mrg {
286 1.1 mrg ub = MIN (ub, g + 1);
287 1.1 mrg while ((k = gmp_nextprime (&ps)) < ub)
288 1.1 mrg {
289 1.1 mrg if ((g % k) == 0)
290 1.1 mrg {
291 1.1 mrg if (is_kth_power (rp1, np, k, yp, nn, f, tp) != 0)
292 1.1 mrg {
293 1.1 mrg ans = 1;
294 1.1 mrg goto ret;
295 1.1 mrg }
296 1.1 mrg }
297 1.1 mrg }
298 1.1 mrg }
299 1.1 mrg else
300 1.1 mrg {
301 1.1 mrg while ((k = gmp_nextprime (&ps)) < ub)
302 1.1 mrg {
303 1.1 mrg if (is_kth_power (rp1, np, k, yp, nn, f, tp) != 0)
304 1.1 mrg {
305 1.1 mrg ans = 1;
306 1.1 mrg goto ret;
307 1.1 mrg }
308 1.1 mrg }
309 1.1 mrg }
310 1.1 mrg ret:
311 1.1 mrg TMP_FREE;
312 1.1 mrg return ans;
313 1.1 mrg }
314 1.1 mrg
315 1.1 mrg static const unsigned short nrtrial[] = { 100, 500, 1000 };
316 1.1 mrg
317 1.1 mrg /* Table of (log_{p_i} 2) values, where p_i is
318 1.1 mrg the (nrtrial[i] + 1)'th prime number.
319 1.1 mrg */
320 1.1 mrg static const double logs[] = { 0.1099457228193620, 0.0847016403115322, 0.0772048195144415 };
321 1.1 mrg
322 1.1 mrg int
323 1.1 mrg mpn_perfect_power_p (mp_srcptr np, mp_size_t nn)
324 1.1 mrg {
325 1.1 mrg mp_size_t ncn, s, pn, xn;
326 1.1 mrg mp_limb_t *nc, factor, g = 0;
327 1.1 mrg mp_limb_t exp, *prev, *next, d, l, r, c, *tp, cry;
328 1.1 mrg mp_bitcnt_t twos = 0, count;
329 1.1 mrg int ans, where = 0, neg = 0, trial;
330 1.1 mrg TMP_DECL;
331 1.1 mrg
332 1.1 mrg nc = (mp_ptr) np;
333 1.1 mrg
334 1.1 mrg if (nn < 0)
335 1.1 mrg {
336 1.1 mrg neg = 1;
337 1.1 mrg nn = -nn;
338 1.1 mrg }
339 1.1 mrg
340 1.1 mrg if (nn == 0 || (nn == 1 && np[0] == 1))
341 1.1 mrg return 1;
342 1.1 mrg
343 1.1 mrg TMP_MARK;
344 1.1 mrg
345 1.1 mrg ncn = nn;
346 1.1 mrg twos = mpn_scan1 (np, 0);
347 1.1 mrg if (twos > 0)
348 1.1 mrg {
349 1.1 mrg if (twos == 1)
350 1.1 mrg {
351 1.1 mrg ans = 0;
352 1.1 mrg goto ret;
353 1.1 mrg }
354 1.1 mrg s = twos / GMP_LIMB_BITS;
355 1.1 mrg if (s + 1 == nn && POW2_P (np[s]))
356 1.1 mrg {
357 1.1 mrg ans = ! (neg && POW2_P (twos));
358 1.1 mrg goto ret;
359 1.1 mrg }
360 1.1 mrg count = twos % GMP_LIMB_BITS;
361 1.1 mrg ncn = nn - s;
362 1.1 mrg nc = TMP_ALLOC_LIMBS (ncn);
363 1.1 mrg if (count > 0)
364 1.1 mrg {
365 1.1 mrg mpn_rshift (nc, np + s, ncn, count);
366 1.1 mrg ncn -= (nc[ncn - 1] == 0);
367 1.1 mrg }
368 1.1 mrg else
369 1.1 mrg {
370 1.1 mrg MPN_COPY (nc, np + s, ncn);
371 1.1 mrg }
372 1.1 mrg g = twos;
373 1.1 mrg }
374 1.1 mrg
375 1.1 mrg if (ncn <= SMALL)
376 1.1 mrg trial = 0;
377 1.1 mrg else if (ncn <= MEDIUM)
378 1.1 mrg trial = 1;
379 1.1 mrg else
380 1.1 mrg trial = 2;
381 1.1 mrg
382 1.1 mrg factor = mpn_trialdiv (nc, ncn, nrtrial[trial], &where);
383 1.1 mrg
384 1.1 mrg if (factor != 0)
385 1.1 mrg {
386 1.1 mrg if (twos == 0)
387 1.1 mrg {
388 1.1 mrg nc = TMP_ALLOC_LIMBS (ncn);
389 1.1 mrg MPN_COPY (nc, np, ncn);
390 1.1 mrg }
391 1.1 mrg
392 1.1 mrg /* Remove factors found by trialdiv.
393 1.1 mrg Optimization: Perhaps better to use
394 1.1 mrg the strategy in mpz_remove ().
395 1.1 mrg */
396 1.1 mrg prev = TMP_ALLOC_LIMBS (ncn + 2);
397 1.1 mrg next = TMP_ALLOC_LIMBS (ncn + 2);
398 1.1 mrg tp = TMP_ALLOC_LIMBS (4 * ncn);
399 1.1 mrg
400 1.1 mrg do
401 1.1 mrg {
402 1.1 mrg binvert_limb (d, factor);
403 1.1 mrg prev[0] = d;
404 1.1 mrg pn = 1;
405 1.1 mrg exp = 1;
406 1.1 mrg while (2 * pn - 1 <= ncn)
407 1.1 mrg {
408 1.1 mrg mpn_sqr (next, prev, pn);
409 1.1 mrg xn = 2 * pn;
410 1.1 mrg xn -= (next[xn - 1] == 0);
411 1.1 mrg
412 1.1 mrg if (mpn_divisible_p (nc, ncn, next, xn) == 0)
413 1.1 mrg break;
414 1.1 mrg
415 1.1 mrg exp <<= 1;
416 1.1 mrg pn = xn;
417 1.1 mrg MP_PTR_SWAP (next, prev);
418 1.1 mrg }
419 1.1 mrg
420 1.1 mrg /* Binary search for the exponent */
421 1.1 mrg l = exp + 1;
422 1.1 mrg r = 2 * exp - 1;
423 1.1 mrg while (l <= r)
424 1.1 mrg {
425 1.1 mrg c = (l + r) >> 1;
426 1.1 mrg if (c - exp > 1)
427 1.1 mrg {
428 1.1 mrg xn = mpn_pow_1 (tp, &d, 1, c - exp, next);
429 1.1 mrg if (pn + xn - 1 > ncn)
430 1.1 mrg {
431 1.1 mrg r = c - 1;
432 1.1 mrg continue;
433 1.1 mrg }
434 1.1 mrg mpn_mul (next, prev, pn, tp, xn);
435 1.1 mrg xn += pn;
436 1.1 mrg xn -= (next[xn - 1] == 0);
437 1.1 mrg }
438 1.1 mrg else
439 1.1 mrg {
440 1.1 mrg cry = mpn_mul_1 (next, prev, pn, d);
441 1.1 mrg next[pn] = cry;
442 1.1 mrg xn = pn + (cry != 0);
443 1.1 mrg }
444 1.1 mrg
445 1.1 mrg if (mpn_divisible_p (nc, ncn, next, xn) == 0)
446 1.1 mrg {
447 1.1 mrg r = c - 1;
448 1.1 mrg }
449 1.1 mrg else
450 1.1 mrg {
451 1.1 mrg exp = c;
452 1.1 mrg l = c + 1;
453 1.1 mrg MP_PTR_SWAP (next, prev);
454 1.1 mrg pn = xn;
455 1.1 mrg }
456 1.1 mrg }
457 1.1 mrg
458 1.1 mrg if (g == 0)
459 1.1 mrg g = exp;
460 1.1 mrg else
461 1.1 mrg g = mpn_gcd_1 (&g, 1, exp);
462 1.1 mrg
463 1.1 mrg if (g == 1)
464 1.1 mrg {
465 1.1 mrg ans = 0;
466 1.1 mrg goto ret;
467 1.1 mrg }
468 1.1 mrg
469 1.1 mrg mpn_divexact (next, nc, ncn, prev, pn);
470 1.1 mrg ncn = ncn - pn;
471 1.1 mrg ncn += next[ncn] != 0;
472 1.1 mrg MPN_COPY (nc, next, ncn);
473 1.1 mrg
474 1.1 mrg if (ncn == 1 && nc[0] == 1)
475 1.1 mrg {
476 1.1 mrg ans = ! (neg && POW2_P (g));
477 1.1 mrg goto ret;
478 1.1 mrg }
479 1.1 mrg
480 1.1 mrg factor = mpn_trialdiv (nc, ncn, nrtrial[trial], &where);
481 1.1 mrg }
482 1.1 mrg while (factor != 0);
483 1.1 mrg }
484 1.1 mrg
485 1.1 mrg count_leading_zeros (count, nc[ncn-1]);
486 1.1 mrg count = GMP_LIMB_BITS * ncn - count; /* log (nc) + 1 */
487 1.1 mrg d = (mp_limb_t) (count * logs[trial] + 1e-9) + 1;
488 1.1 mrg ans = perfpow (nc, ncn, d, g, count, neg);
489 1.1 mrg
490 1.1 mrg ret:
491 1.1 mrg TMP_FREE;
492 1.1 mrg return ans;
493 1.1 mrg }
494