def williams_pp1(n): if isprime(n): return n m = ispower(n) if m: return m for v in count(1): for p in primegen(): e = ilog(isqrt(n), p) if e == 0: break for _ in xrange(e): v = mlucas(v, p, n) g = gcd(v - 2, n) if 1 < g < n: return g if g == n: break
def introot(n, r=2): if n < 0: return None if r%2 == 0 else -introot(-n, r) if n < 2: return n if r == 2: return isqrt(n) lower, upper = 0, n while lower != upper - 1: mid = (lower + upper) / 2 m = mid**r if m == n: return mid elif m < n: lower = mid elif m > n: upper = mid return lower
def primefac(n, trial_limit=1000, rho_rounds=42000, verbose=False, methods=(pollardRho_brent, pollard_pm1, williams_pp1, ecm, mpqs)): # Obtains a complete factorization of n, yielding the prime factors as they are obtained. # If the user explicitly specifies a splitting method, use that method. Otherwise, # 1. Pull out small factors with trial division. # TODO: a few rounds of Fermat's method? # 2. Do a few rounds of Pollard's Rho algorithm. # TODO: a few rounds of ECM by itself? # TODO: a certain amount of P-1? # 3. Launch multifactor on the remainder. Multifactor has enough overhead that we want to be fairly sure that rho isn't # likely to yield new factors soon. The default value of rho_rounds=42000 seems good for that but is probably overkill. if n < 2: return if isprime(n): yield n; return factors, nroot = [], isqrt(n) for p in primegen(): # Note that we remove factors of 2 whether the user wants to or not. if n%p == 0: while n%p == 0: yield p n /= p nroot = isqrt(n) if isprime(n): yield n return if p > nroot: if n != 1: yield n return if p >= trial_limit: break if isprime(n): yield n; return if rho_rounds == "inf": factors = [n] while len(factors) != 0: n = min(factors) factors.remove(n) f = pollardRho_brent(n) if isprime(f): yield f else: factors.append(f) n /= f if isprime(n): yield n else: factors.append(n) return factors, difficult = [n], [] while len(factors) != 0: rhocount = 0 n = factors.pop() try: g = n while g == n: x, c, g = randrange(1, n), randrange(1, n), 1 y = x while g==1: if rhocount >= rho_rounds: raise Exception rhocount += 1 x = (x**2 + c) % n y = (y**2 + c) % n y = (y**2 + c) % n g = gcd(x-y, n) # We now have a nontrivial factor g of n. If we took too long to get here, we're actually at the except statement. if isprime(g): yield g else: factors.append(g) n /= g if isprime(n): yield n else: factors.append(n) except Exception: difficult.append(n) # Factoring n took too long. We'll have multifactor chug on it. factors = difficult while len(factors) != 0: n = min(factors) factors.remove(n) f = multifactor(n, methods=methods, verbose=verbose) if isprime(f): yield f else: factors.append(f) n /= f if isprime(n): yield n else: factors.append(n)
def mpqs(n): # When the bound proves insufficiently large, we throw out all our work and start over. # TODO: When this happens, get more data, but don't trash what we already have. # TODO: Rewrite to get a few more relations before proceeding to the linear algebra. # TODO: When we need to increase the bound, what is the optimal increment? # Special cases: this function poorly handles primes and perfect powers: m = ispower(n) if m: return m if isprime(n): return n root_n, root_2n = isqrt(n), isqrt(2*n) bound = ilog(n**6, 10)**2 # formula chosen by experiment while True: try: prime, mod_root, log_p, num_prime = [], [], [], 0 # find a number of small primes for which n is a quadratic residue p = 2 while p < bound or num_prime < 3: leg = legendre(n%p, p) if leg == 1: prime += [p] mod_root += [mod_sqrt(n, p)] # the rhs was [int(mod_sqrt(n, p))]. If we get errors, put it back. log_p += [log(p, 10)] num_prime += 1 elif leg == 0: return p p = nextprime(p) x_max = len(prime)*60 # size of the sieve m_val = (x_max * root_2n) >> 1 # maximum value on the sieved range # fudging the threshold down a bit makes it easier to find powers of primes as factors # as well as partial-partial relationships, but it also makes the smoothness check slower. # there's a happy medium somewhere, depending on how efficient the smoothness check is thresh = log(m_val, 10) * 0.735 # skip small primes. they contribute very little to the log sum # and add a lot of unnecessary entries to the table # instead, fudge the threshold down a bit, assuming ~1/4 of them pass min_prime = mpz(thresh*3) fudge = sum(log_p[i] for i,p in enumerate(prime) if p < min_prime)/4 thresh -= fudge smooth, used_prime, partial = [], set(), {} num_smooth, num_used_prime, num_partial, num_poly, root_A = 0, 0, 0, 0, isqrt(root_2n / x_max) while num_smooth <= num_used_prime: # find an integer value A such that: # A is =~ sqrt(2*n) / x_max # A is a perfect square # sqrt(A) is prime, and n is a quadratic residue mod sqrt(A) while True: root_A = nextprime(root_A) leg = legendre(n, root_A) if leg == 1: break elif leg == 0: return root_A A = root_A**2 # solve for an adequate B # B*B is a quadratic residue mod n, such that B*B-A*C = n # this is unsolvable if n is not a quadratic residue mod sqrt(A) b = mod_sqrt(n, root_A) B = (b + (n - b*b) * modinv(b + b, root_A))%A C = (B*B - n) / A # B*B-A*C = n <=> C = (B*B-n)/A num_poly += 1 # sieve for prime factors sums, i = [0.0]*(2*x_max), 0 for p in prime: if p < min_prime: i += 1 continue logp = log_p[i] inv_A = modinv(A, p) # modular root of the quadratic a, b, k = mpz(((mod_root[i] - B) * inv_A)%p), mpz(((p - mod_root[i] - B) * inv_A)%p), 0 while k < x_max: if k+a < x_max: sums[k+a] += logp if k+b < x_max: sums[k+b] += logp if k: sums[k-a+x_max] += logp sums[k-b+x_max] += logp k += p i += 1 # check for smooths i = 0 for v in sums: if v > thresh: x, vec, sqr = x_max-i if i > x_max else i, set(), [] # because B*B-n = A*C # (A*x+B)^2 - n = A*A*x*x+2*A*B*x + B*B - n # = A*(A*x*x+2*B*x+C) # gives the congruency # (A*x+B)^2 = A*(A*x*x+2*B*x+C) (mod n) # because A is chosen to be square, it doesn't need to be sieved val = sieve_val = (A*x + 2*B)*x + C if sieve_val < 0: vec, sieve_val = {-1}, -sieve_val for p in prime: while sieve_val%p == 0: if p in vec: sqr += [p] # track perfect sqr facs to avoid sqrting something huge at the end vec ^= {p} sieve_val = mpz(sieve_val / p) if sieve_val == 1: # smooth smooth += [(vec, (sqr, (A*x+B), root_A))] used_prime |= vec elif sieve_val in partial: # combine two partials to make a (xor) smooth # that is, every prime factor with an odd power is in our factor base pair_vec, pair_vals = partial[sieve_val] sqr += list(vec & pair_vec) + [sieve_val] vec ^= pair_vec smooth += [(vec, (sqr + pair_vals[0], (A*x+B)*pair_vals[1], root_A*pair_vals[2]))] used_prime |= vec num_partial += 1 else: partial[sieve_val] = (vec, (sqr, A*x+B, root_A)) # save partial for later pairing i += 1 num_smooth, num_used_prime = len(smooth), len(used_prime) used_prime = sorted(list(used_prime)) # set up bit fields for gaussian elimination masks, mask, bitfields = [], 1, [0]*num_used_prime for vec, vals in smooth: masks += [mask] i = 0 for p in used_prime: if p in vec: bitfields[i] |= mask i += 1 mask <<= 1 # row echelon form offset = 0 null_cols = [] for col in xrange(num_smooth): pivot = bitfields[col-offset] & masks[col] == 0 # This occasionally throws IndexErrors. # TODO: figure out why it throws errors and fix it. for row in xrange(col+1-offset, num_used_prime): if bitfields[row] & masks[col]: if pivot: bitfields[col-offset], bitfields[row], pivot = bitfields[row], bitfields[col-offset], False else: bitfields[row] ^= bitfields[col-offset] if pivot: null_cols += [col] offset += 1 # reduced row echelon form for row in xrange(num_used_prime): mask = bitfields[row] & -bitfields[row] # lowest set bit for up_row in xrange(row): if bitfields[up_row] & mask: bitfields[up_row] ^= bitfields[row] # check for non-trivial congruencies # TODO: if none exist, check combinations of null space columns... # if _still_ none exist, sieve more values for col in null_cols: all_vec, (lh, rh, rA) = smooth[col] lhs = lh # sieved values (left hand side) rhs = [rh] # sieved values - n (right hand side) rAs = [rA] # root_As (cofactor of lhs) i = 0 for field in bitfields: if field & masks[col]: vec, (lh, rh, rA) = smooth[i] lhs += list(all_vec & vec) + lh all_vec ^= vec rhs += [rh] rAs += [rA] i += 1 factor = gcd(listprod(rAs)*listprod(lhs) - listprod(rhs), n) if 1 < factor < n: return factor except IndexError: pass bound *= 1.2
def isprime(n, tb=(3,5,7,11), eb=(2,), mrb=()): # TODO: more streamlining # tb: trial division basis # eb: Euler's test basis # mrb: Miller-Rabin basis # This test suite's first false positve is unknown but has been shown to be greater than 2**64. # Infinitely many are thought to exist. if n%2 == 0 or n < 13 or n == isqrt(n)**2: return n in (2, 3, 5, 7, 11) # Remove evens, squares, and numbers less than 13 if any(n%p == 0 for p in tb): return n in tb # Trial division for b in eb: # Euler's test if b >= n: continue if not pow(b, n-1, n) == 1: return False r = n - 1 while r%2 == 0: r /= 2 c = pow(b, r, n) if c == 1: continue while c != 1 and c != n-1: c = pow(c, 2, n) if c == 1: return False s, d = pfactor(n) if not sprp(n, 2, s, d): return False if n < 2047: return True if n >= 3825123056546413051: # BPSW has two phases: SPRP with base 2 and SLPRP. We just did the SPRP; now we do the SLPRP: d = 5 while True: if gcd(d, n) > 1: p, q = 0, 0 break if jacobi(d, n) == -1: p, q = 1, (1 - d) / 4 break d = -d - 2*d/abs(d) if p == 0: return n == d s, t = pfactor(n + 2) u, v, u2, v2, m = 1, p, 1, p, t/2 k = q while m > 0: u2, v2, q = (u2*v2)%n, (v2*v2-2*q)%n, (q*q)%n if m%2 == 1: u, v = u2*v+u*v2, v2*v+u2*u*d if u%2 == 1: u += n if v%2 == 1: v += n u, v, k = (u/2)%n, (v/2)%n, (q*k)%n m /= 2 if (u == 0) or (v == 0): return True for i in xrange(1, s): v, k = (v*v-2*k)%n, (k*k)%n if v == 0: return True return False if not mrb: if n < 1373653: mrb = [3] elif n < 25326001: mrb = [3,5] elif n < 3215031751: mrb = [3,5,7] elif n < 2152302898747: mrb = [3,5,7,11] elif n < 3474749660383: mrb = [3,5,6,11,13] elif n < 341550071728321: mrb = [3,5,7,11,13,17] # This number is also a false positive for primes(19+1). elif n < 3825123056546413051: mrb = [3,5,7,11,13,17,19,23] # Also a false positive for primes(31+1). return all(sprp(n, b, s, d) for b in mrb) # Miller-Rabin