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