Ejemplo n.º 1
0
def fermat(n):
    from _primefac._arith import isqrt
    x = isqrt(n) + 1
    y = isqrt(x**2 - n)
    while True:
        w = x**2 - n - y**2
        if w == 0:
            break
        if w > 0:
            y += 1
        else:
            x += 1
    return x + y
Ejemplo n.º 2
0
def williams_pp1(n):
    from _primefac._arith import ispower, ilog, isqrt, gcd
    from _primefac._prime import isprime, primegen
    from six.moves import xrange
    import itertools
    if isprime(n):
        return n
    m = ispower(n)
    if m:
        return m
    for v in itertools.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
Ejemplo n.º 3
0
def _isprime(n, tb=(3, 5, 7, 11), eb=(2, ), mrb=()):  # TODO: more streamlining
    from _primefac import _arith
    # 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 == _arith.isqrt(n)**2:
        # Remove evens, squares, and numbers less than 13
        return n in (2, 3, 5, 7, 11)
    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
    # BPSW has two phases: SPRP with base 2 and SLPRP.
    # We just did the SPRP; now we do the SLPRP:
    if n >= 3825123056546413051:
        d = 5
        while True:
            if _arith.gcd(d, n) > 1:
                p, q = 0, 0
                break
            if _arith.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 _ 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:
            # This number is also a false positive for primes(19+1).
            mrb = [3, 5, 7, 11, 13, 17]
        elif n < 3825123056546413051:
            # Also a false positive for primes(31+1).
            mrb = [3, 5, 7, 11, 13, 17, 19, 23]
    # Miller-Rabin
    return all(sprp(n, b, s, d) for b in mrb)
Ejemplo n.º 4
0
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?
    """
    from _primefac._arith import ispower, isqrt, ilog, gcd, mod_sqrt, legendre
    from _primefac._arith import modinv
    from _primefac._prime import isprime, nextprime
    from _primefac._util import listprod, mpz
    from six.moves import xrange
    from math import log

    # Special cases: this function poorly handles primes and perfect powers:
    m = ispower(n)
    if m:
        return m
    if isprime(n):
        return n

    root_2n = 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]
                    # the rhs was [int(mod_sqrt(n, p))].
                    # If we get errors, put it back.
                    mod_root += [mod_sqrt(n, p)]
                    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

            # maximum value on the sieved range
            m_val = (x_max * root_2n) >> 1
            """
            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)
            fudge = fudge // 4
            thresh -= fudge

            smooth, used_prime, partial = [], set(), {}
            num_smooth, num_used_prime, num_partial = 0, 0, 0
            num_poly, root_A = 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]
                    g = gcd(A, p)
                    inv_A = modinv(A // g, p // g) * g
                    # 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
                        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:
                                    """
                                    track perfect sqr facs to avoid sqrting
                                    something huge at the end
                                    """
                                    sqr += [p]
                                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:
                            # save partial for later pairing
                            partial[sieve_val] = (vec, (sqr, A * x + B,
                                                        root_A))
                    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, _ 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