1 /* mpn_perfect_power_p -- mpn perfect power detection.
3 Contributed to the GNU project by Martin Boij.
5 Copyright 2009, 2010 Free Software Foundation, Inc.
7 This file is part of the GNU MP Library.
9 The GNU MP Library is free software; you can redistribute it and/or modify
10 it under the terms of the GNU Lesser General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or (at your
12 option) any later version.
14 The GNU MP Library is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
17 License for more details.
19 You should have received a copy of the GNU Lesser General Public License
20 along with the GNU MP Library. If not, see http://www.gnu.org/licenses/. */
30 Returns non-zero if {np,nn} == {xp,xn} ^ k.
32 For s = 1, 2, 4, ..., s_max, compute the s least significant
33 limbs of {xp,xn}^k. Stop if they don't match the s least
34 significant limbs of {np,nn}.
37 pow_equals (mp_srcptr np, mp_size_t nn,
38 mp_srcptr xp,mp_size_t xn,
39 mp_limb_t k, mp_bitcnt_t f,
43 mp_bitcnt_t y, z, count;
49 ASSERT (nn > 1 || (nn == 1 && np[0] > 1));
50 ASSERT (np[nn - 1] > 0);
53 if (xn == 1 && xp[0] == 1)
57 for (bn = 1; bn < z; bn <<= 1)
59 mpn_powlo (tp, xp, &k, 1, bn, tp + bn);
60 if (mpn_cmp (tp, np, bn) != 0)
66 /* Final check. Estimate the size of {xp,xn}^k before computing
67 the power with full precision.
68 Optimization: It might pay off to make a more accurate estimation of
69 the logarithm of {xp,xn}, rather than using the index of the MSB.
72 count_leading_zeros (count, xp[xn - 1]);
73 y = xn * GMP_LIMB_BITS - count - 1; /* msb_index (xp, xn) */
75 umul_ppmm (h, l, k, y);
76 h -= l == 0; l--; /* two-limb decrement */
78 z = f - 1; /* msb_index (np, nn) */
83 ASSERT_ALWAYS (size >= k);
85 y = 2 + size / GMP_LIMB_BITS;
86 tp2 = TMP_ALLOC_LIMBS (y);
88 i = mpn_pow_1 (tp, xp, xn, k, tp2);
89 if (i == nn && mpn_cmp (tp, np, nn) == 0)
104 Computes rp such that rp^k * yp = 1 (mod 2^b).
106 Apply Hensel lifting repeatedly, each time
107 doubling (approx.) the number of known bits in rp.
110 binv_root (mp_ptr rp, mp_srcptr yp,
111 mp_limb_t k, mp_size_t bn,
112 mp_bitcnt_t b, mp_ptr tp)
114 mp_limb_t *tp2 = tp + bn, *tp3 = tp + 2 * bn, di, k2 = k + 1;
115 mp_bitcnt_t order[GMP_LIMB_BITS * 2];
120 ASSERT ((k & 1) != 0);
122 binvert_limb (di, k);
125 for (; b != 1; b = (b + 1) >> 1)
128 for (i = d - 1; i >= 0; i--)
131 bn = 1 + (b - 1) / GMP_LIMB_BITS;
133 mpn_mul_1 (tp, rp, bn, k2);
135 mpn_powlo (tp2, rp, &k2, 1, bn, tp3);
136 mpn_mullo_n (rp, yp, tp2, bn);
138 mpn_sub_n (tp2, tp, rp, bn);
139 mpn_pi1_bdiv_q_1 (rp, tp2, bn, k, di, 0);
140 if ((b % GMP_LIMB_BITS) != 0)
141 rp[(b - 1) / GMP_LIMB_BITS] &= (((mp_limb_t) 1) << (b % GMP_LIMB_BITS)) - 1;
147 Computes rp such that rp^2 * yp = 1 (mod 2^{b+1}).
148 Returns non-zero if such an integer rp exists.
151 binv_sqroot (mp_ptr rp, mp_srcptr yp,
152 mp_size_t bn, mp_bitcnt_t b,
155 mp_limb_t k = 3, *tp2 = tp + bn, *tp3 = tp + (bn << 1);
156 mp_bitcnt_t order[GMP_LIMB_BITS * 2];
165 if ((yp[0] & 3) != 1)
170 if ((yp[0] & 7) != 1)
173 for (; b != 2; b = (b + 2) >> 1)
176 for (i = d - 1; i >= 0; i--)
179 bn = 1 + b / GMP_LIMB_BITS;
181 mpn_mul_1 (tp, rp, bn, k);
183 mpn_powlo (tp2, rp, &k, 1, bn, tp3);
184 mpn_mullo_n (rp, yp, tp2, bn);
186 #if HAVE_NATIVE_mpn_rsh1sub_n
187 mpn_rsh1sub_n (rp, tp, rp, bn);
189 mpn_sub_n (tp2, tp, rp, bn);
190 mpn_rshift (rp, tp2, bn, 1);
192 rp[b / GMP_LIMB_BITS] &= (((mp_limb_t) 1) << (b % GMP_LIMB_BITS)) - 1;
199 Returns non-zero if {np,nn} is a kth power.
202 is_kth_power (mp_ptr rp, mp_srcptr np,
203 mp_limb_t k, mp_srcptr yp,
204 mp_size_t nn, mp_bitcnt_t f,
212 ASSERT (((k & 1) != 0) || (k == 2));
213 ASSERT ((np[0] & 1) != 0);
218 rn = 1 + b / GMP_LIMB_BITS;
219 if (binv_sqroot (rp, yp, rn, b, tp) != 0)
222 MPN_NORMALIZE (rp, xn);
223 if (pow_equals (np, nn, rp, xn, k, f, tp) != 0)
226 /* Check if (2^b - rp)^2 == np */
228 for (i = 0; i < rn; i++)
234 rp[rn - 1] &= (((mp_limb_t) 1) << (b % GMP_LIMB_BITS)) - 1;
235 MPN_NORMALIZE (rp, rn);
236 if (pow_equals (np, nn, rp, rn, k, f, tp) != 0)
243 rn = 1 + (b - 1) / GMP_LIMB_BITS;
244 binv_root (rp, yp, k, rn, b, tp);
245 MPN_NORMALIZE (rp, rn);
246 if (pow_equals (np, nn, rp, rn, k, f, tp) != 0)
249 MPN_ZERO (rp, rn); /* Untrash rp */
254 perfpow (mp_srcptr np, mp_size_t nn,
255 mp_limb_t ub, mp_limb_t g,
256 mp_bitcnt_t f, int neg)
258 mp_limb_t *yp, *tp, k = 0, *rp1;
265 ASSERT ((np[0] & 1) != 0);
269 gmp_init_primesieve (&ps);
272 yp = TMP_ALLOC_LIMBS (nn);
273 rp1 = TMP_ALLOC_LIMBS (nn);
274 tp = TMP_ALLOC_LIMBS (5 * nn); /* FIXME */
277 mpn_binvert (yp, np, 1 + (b - 1) / GMP_LIMB_BITS, tp);
278 if (b % GMP_LIMB_BITS)
279 yp[(b - 1) / GMP_LIMB_BITS] &= (((mp_limb_t) 1) << (b % GMP_LIMB_BITS)) - 1;
286 ub = MIN (ub, g + 1);
287 while ((k = gmp_nextprime (&ps)) < ub)
291 if (is_kth_power (rp1, np, k, yp, nn, f, tp) != 0)
301 while ((k = gmp_nextprime (&ps)) < ub)
303 if (is_kth_power (rp1, np, k, yp, nn, f, tp) != 0)
315 static const unsigned short nrtrial[] = { 100, 500, 1000 };
317 /* Table of (log_{p_i} 2) values, where p_i is
318 the (nrtrial[i] + 1)'th prime number.
320 static const double logs[] = { 0.1099457228193620, 0.0847016403115322, 0.0772048195144415 };
323 mpn_perfect_power_p (mp_srcptr np, mp_size_t nn)
325 mp_size_t ncn, s, pn, xn;
326 mp_limb_t *nc, factor, g = 0;
327 mp_limb_t exp, *prev, *next, d, l, r, c, *tp, cry;
328 mp_bitcnt_t twos = 0, count;
329 int ans, where = 0, neg = 0, trial;
340 if (nn == 0 || (nn == 1 && np[0] == 1))
346 twos = mpn_scan1 (np, 0);
354 s = twos / GMP_LIMB_BITS;
355 if (s + 1 == nn && POW2_P (np[s]))
357 ans = ! (neg && POW2_P (twos));
360 count = twos % GMP_LIMB_BITS;
362 nc = TMP_ALLOC_LIMBS (ncn);
365 mpn_rshift (nc, np + s, ncn, count);
366 ncn -= (nc[ncn - 1] == 0);
370 MPN_COPY (nc, np + s, ncn);
377 else if (ncn <= MEDIUM)
382 factor = mpn_trialdiv (nc, ncn, nrtrial[trial], &where);
388 nc = TMP_ALLOC_LIMBS (ncn);
389 MPN_COPY (nc, np, ncn);
392 /* Remove factors found by trialdiv.
393 Optimization: Perhaps better to use
394 the strategy in mpz_remove ().
396 prev = TMP_ALLOC_LIMBS (ncn + 2);
397 next = TMP_ALLOC_LIMBS (ncn + 2);
398 tp = TMP_ALLOC_LIMBS (4 * ncn);
402 binvert_limb (d, factor);
406 while (2 * pn - 1 <= ncn)
408 mpn_sqr (next, prev, pn);
410 xn -= (next[xn - 1] == 0);
412 if (mpn_divisible_p (nc, ncn, next, xn) == 0)
417 MP_PTR_SWAP (next, prev);
420 /* Binary search for the exponent */
428 xn = mpn_pow_1 (tp, &d, 1, c - exp, next);
429 if (pn + xn - 1 > ncn)
434 mpn_mul (next, prev, pn, tp, xn);
436 xn -= (next[xn - 1] == 0);
440 cry = mpn_mul_1 (next, prev, pn, d);
442 xn = pn + (cry != 0);
445 if (mpn_divisible_p (nc, ncn, next, xn) == 0)
453 MP_PTR_SWAP (next, prev);
461 g = mpn_gcd_1 (&g, 1, exp);
469 mpn_divexact (next, nc, ncn, prev, pn);
471 ncn += next[ncn] != 0;
472 MPN_COPY (nc, next, ncn);
474 if (ncn == 1 && nc[0] == 1)
476 ans = ! (neg && POW2_P (g));
480 factor = mpn_trialdiv (nc, ncn, nrtrial[trial], &where);
485 count_leading_zeros (count, nc[ncn-1]);
486 count = GMP_LIMB_BITS * ncn - count; /* log (nc) + 1 */
487 d = (mp_limb_t) (count * logs[trial] + 1e-9) + 1;
488 ans = perfpow (nc, ncn, d, g, count, neg);