Beispiel #1
0
    def find_multiplier():
        """
        Computes a multiplier for input into the cfrac factorization algorithm.

        The method is based on Remark 5.3 from the paper "A Method of Factoring
        and the Factorization of F7" by Morrison and Brillhart.
        """
        choices = {}
        # Look for multpliers in the range [1, 1000).
        for k in xrange(1, 1000):
            if jacobi_symbol(k*n, 3) >= 0 and jacobi_symbol(k*n, 5) >= 0:
                # Find the multiplier k that allows the largest number of primes
                # <= 31 into the factor base.
                count = 0
                for p in prime_list:
                    # We've already looked at p = 3 and p = 5.
                    if p <= 5:
                        continue
                    if p > 31:
                        break
                    if jacobi_symbol(k*n, p) >= 0:
                        count += 1
                if count not in choices:
                    choices[count] = [k]
                else:
                    choices[count].append(k)
        # If several values of k allow this maximal number, we simply choose the
        # smallest of them.
        max_count = max(choices)
        return min(choices[max_count])
Beispiel #2
0
def _cfrac_multiplier(n):
    r"""Computes a multiplier for input into the cfrac algorithm.

    Parameters
    ----------
    n : int
        Integer to be factored.

    Returns
    -------
    k : int
        Multiplier for the cfrac algorithm.

    Notes
    -----
    The continued fraction of sqrt(n) is always periodic. In the cases
    where the period of sqrt(n) is too short, it is necessary to expand
    sqrt(k*n) for some k > 1. We choose the multiplier `k` which allows th
    elargest number of primes <= 31 to be in the factor base. The method
    follows Remark 5.3 of [1].

    References
    ----------
    .. [1] M.A. Morrison, J. Brillhart, "A Method of Factoring and the
    Factorization of F7", Mathematics of Computation, Vol. 29, Num. 129,
    Jan. 1975.

    Examples
    --------
    >>> _cfrac_multiplier(5**77 - 1)
    781
    """
    prime_list = [3, 5, 7, 11, 13, 17, 19, 23, 29, 31]
    choices = {}
    # Look for multpliers in the range [1, 1000).
    for k in xrange(1, 1000):
        if jacobi_symbol(k*n, 3) >= 0 and jacobi_symbol(k*n, 5) >= 0:
            # Find the multiplier k that allows the largest number of
            # primes <= 31 into the factor base.
            count = sum(1 for p in prime_list if jacobi_symbol(k*n, p) >= 0)
            if count not in choices:
                choices[count] = [k]
            else:
                choices[count].append(k)
    # If several values of k allow this maximal number, we simply choose the
    # smallest of them.
    max_count = max(choices)
    return min(choices[max_count])
Beispiel #3
0
def _cfrac_multiplier(n):
    r"""Computes a multiplier for input into the cfrac algorithm.

    Parameters
    ----------
    n : int
        Integer to be factored.

    Returns
    -------
    k : int
        Multiplier for the cfrac algorithm.

    Notes
    -----
    The continued fraction of sqrt(n) is always periodic. In the cases
    where the period of sqrt(n) is too short, it is necessary to expand
    sqrt(k*n) for some k > 1. We choose the multiplier `k` which allows th
    elargest number of primes <= 31 to be in the factor base. The method
    follows Remark 5.3 of [1].

    References
    ----------
    .. [1] M.A. Morrison, J. Brillhart, "A Method of Factoring and the
    Factorization of F7", Mathematics of Computation, Vol. 29, Num. 129,
    Jan. 1975.

    Examples
    --------
    >>> _cfrac_multiplier(5**77 - 1)
    781
    """
    prime_list = [3, 5, 7, 11, 13, 17, 19, 23, 29, 31]
    choices = {}
    # Look for multpliers in the range [1, 1000).
    for k in xrange(1, 1000):
        if jacobi_symbol(k * n, 3) >= 0 and jacobi_symbol(k * n, 5) >= 0:
            # Find the multiplier k that allows the largest number of
            # primes <= 31 into the factor base.
            count = sum(1 for p in prime_list if jacobi_symbol(k * n, p) >= 0)
            if count not in choices:
                choices[count] = [k]
            else:
                choices[count].append(k)
    # If several values of k allow this maximal number, we simply choose the
    # smallest of them.
    max_count = max(choices)
    return min(choices[max_count])
Beispiel #4
0
def solovay_strassen(n, a=None):
    r"""Determines if `n` is a probable prime.

    Parameters
    ----------
    n : positive integer

    Returns
    -------
    b : boolean
        Returns the value True if `n` is a probable prime, and False
        otherwise.

    See Also
    --------
    miller_rabin, solovay_strassen_deterministic, is_probable_prime

    Notes
    -----
    This method uses the Solovay Strassen test to determine the
    compositeness of `n`. The test is based on the relationship
    ``a^((p - 1)/2) = (a | p) (mod p)`` proven by Euler, where ``(a | p)``
    is the Jacobi symbol, `p` is prime, and ``gcd(a, p) == 1``.

    The Solovay Strassen test computes this for a random base `a` Since
    this is an identity for primes, this method always returns True when
    `n` is prime. On the other hand, for odd composite `n`, this test
    returns False for at least half of all `a` coprime to `n`. Thus, the
    likelihood of returning True for a composite number is less than 1/2.

    This idea may be used to create a more accurate compositeness test, and
    may even be generalized to a deterministic primality test, pending the
    Extended Riemann Hypothesis.

    References
    ----------
    .. [1] Bach, Shallitt, "Algorithmic Number Theory", MIT Press,
    Cambridge, MA, 1996

    Examples
    --------
    >>> solovay_strassen(341, 2)
    False
    >>> solovay_strassen(341, 29)
    True
    """
    if a is None:
        a = randint(2, n - 2)

    jacobi = jacobi_symbol(a, n)
    if jacobi == 0 or jacobi % n != pow(a, (n - 1) // 2, n):
        return False
    return True
Beispiel #5
0
    def test_jacobi_symbol(self):
        values = [
            1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 0, -1, -1, 0, 1, 1, 0, -1, -1, 1, 1, 1,
            1, 1, 1, 1, 1, 1, 1, 1, -1, 0, -1, 1, 1, -1, 0, -1, 1, 1, 0, 1, -1, 0, -1, -1, 0, -1, 1, 1, 1, -1, 0, 1, -1,
            -1, -1, -1, 1, 1, -1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, -1, 1, -1, 1, 0,
            -1, -1, 1, -1, 1, 1, 1, 0, -1, -1, -1, 1, 1, 0, -1, -1, 0, 1, 1, 0, -1, -1, 1, 1, -1, -1, 1, -1, 0, -1, 1,
            -1, 1, -1, 1, 0, 1, 1, 1, -1, -1, -1, 1, 0, 0, 1, 0, 1, -1, 0, 1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1,
            -1, -1, 1, -1, 1, 1, 0, 1, 1, 0, -1, 1, 0, -1, -1, 0, 1, -1, 1, 1, 1, -1, 1, -1, -1, 1, 1, 0, 1, -1, 0, -1,
            1, 1, -1, 0, -1, 1
        ]

        i = 0
        for a in xrange(1, 21):
            for b in xrange(1, 21, 2):
                self.assertEqual(jacobi_symbol(a, b), values[i])
                i += 1
Beispiel #6
0
    def test_jacobi_symbol(self):
        self.assertRaisesRegexp(ValueError, "jacobi_symbol: Must have m odd.", jacobi_symbol, 19, 4)

        values = [
            1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 0, -1, -1, 0, 1, 1, 0, -1, -1, 1, 1, 1,
            1, 1, 1, 1, 1, 1, 1, 1, -1, 0, -1, 1, 1, -1, 0, -1, 1, 1, 0, 1, -1, 0, -1, -1, 0, -1, 1, 1, 1, -1, 0, 1, -1,
            -1, -1, -1, 1, 1, -1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, -1, 1, -1, 1, 0,
            -1, -1, 1, -1, 1, 1, 1, 0, -1, -1, -1, 1, 1, 0, -1, -1, 0, 1, 1, 0, -1, -1, 1, 1, -1, -1, 1, -1, 0, -1, 1,
            -1, 1, -1, 1, 0, 1, 1, 1, -1, -1, -1, 1, 0, 0, 1, 0, 1, -1, 0, 1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1,
            -1, -1, 1, -1, 1, 1, 0, 1, 1, 0, -1, 1, 0, -1, -1, 0, 1, -1, 1, 1, 1, -1, 1, -1, -1, 1, 1, 0, 1, -1, 0, -1,
            1, 1, -1, 0, -1, 1
        ]

        i = 0
        for a in xrange(1, 21):
            for b in xrange(1, 21, 2):
                self.assertEqual(jacobi_symbol(a, b), values[i])
                i += 1
Beispiel #7
0
    def test_jacobi_symbol(self):
        self.assertRaisesRegexp(ValueError, "jacobi_symbol: Must have m odd.", jacobi_symbol, 19, 4)

        values = [
            1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 0, -1, -1, 0, 1, 1, 0, -1, -1, 1, 1, 1,
            1, 1, 1, 1, 1, 1, 1, 1, -1, 0, -1, 1, 1, -1, 0, -1, 1, 1, 0, 1, -1, 0, -1, -1, 0, -1, 1, 1, 1, -1, 0, 1, -1,
            -1, -1, -1, 1, 1, -1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, -1, 1, -1, 1, 0,
            -1, -1, 1, -1, 1, 1, 1, 0, -1, -1, -1, 1, 1, 0, -1, -1, 0, 1, 1, 0, -1, -1, 1, 1, -1, -1, 1, -1, 0, -1, 1,
            -1, 1, -1, 1, 0, 1, 1, 1, -1, -1, -1, 1, 0, 0, 1, 0, 1, -1, 0, 1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1,
            -1, -1, 1, -1, 1, 1, 0, 1, 1, 0, -1, 1, 0, -1, -1, 0, 1, -1, 1, 1, 1, -1, 1, -1, -1, 1, 1, 0, 1, -1, 0, -1,
            1, 1, -1, 0, -1, 1
        ]

        i = 0
        for a in xrange(1, 21):
            for b in xrange(1, 21, 2):
                self.assertEqual(jacobi_symbol(a, b), values[i])
                i += 1
Beispiel #8
0
def fibonacci_primitive_roots(p):
    """Returns a sorted list of the Fibonacci primitive roots mod p.

    Input:
        * p: int
            A prime number. The primality of p is not verified.

    Returns:
        * roots: list
            This is a list of the Fibonacci primitive roots mod p. This list
            will contain no more than 2 elements.

    Examples:
        >>> fibonacci_primitive_roots(11)
        [8]
        >>> fibonacci_primitive_roots(19)
        [15]
        >>> fibonacci_primitive_roots(41)
        [7, 35]

    Details:
        A Fibonacci primitive root mod p is a primitive root satisfying g**2 = g
        + 1. These can only exist for primes p = 1, 9 (mod 10). See the paper
        "Fibonacci Primitive Roots" by Shanks for details.
    """
    if p % 2 == 0:
        return []
    if p == 5:
        return [3]
    if p < 5 or jacobi_symbol(5, p) != 1:
        return []

    sqrts = sqrts_mod_p(5, p)
    inverse = inverse_mod(2, p)
    quad_roots = [(1 + root) * inverse % p for root in sqrts]
    phi_divisors = factor.prime_divisors(p - 1)
    roots = []

    for r in quad_roots:
        if is_primitive_root(r, p, phi=p - 1, phi_divisors=phi_divisors):
            roots.append(r)

    return sorted(roots)
Beispiel #9
0
def fibonacci_primitive_roots(p):
    """Returns a sorted list of the Fibonacci primitive roots mod p.

    Input:
        * p: int
            A prime number. The primality of p is not verified.

    Returns:
        * roots: list
            This is a list of the Fibonacci primitive roots mod p. This list
            will contain no more than 2 elements.

    Examples:
        >>> fibonacci_primitive_roots(11)
        [8]
        >>> fibonacci_primitive_roots(19)
        [15]
        >>> fibonacci_primitive_roots(41)
        [7, 35]

    Details:
        A Fibonacci primitive root mod p is a primitive root satisfying g**2 = g
        + 1. These can only exist for primes p = 1, 9 (mod 10). See the paper
        "Fibonacci Primitive Roots" by Shanks for details.
    """
    if p % 2 == 0:
        return []
    if p == 5:
        return [3]
    if p < 5 or jacobi_symbol(5, p) != 1:
        return []

    sqrts = sqrts_mod_p(5, p)
    inverse = inverse_mod(2, p)
    quad_roots = [(1 + root)*inverse % p for root in sqrts]
    phi_divisors = factor.prime_divisors(p - 1)
    roots = []

    for r in quad_roots:
        if is_primitive_root(r, p, phi=p - 1, phi_divisors=phi_divisors):
            roots.append(r)

    return sorted(roots)
Beispiel #10
0
def fibonacci_primitive_roots(p):
    """
    Returns a list of the Fibonacci primitive roots mod p.

    A Fibonacci primitive root mod p is a primitive root satisfying g^2 = g + 1.
    These can only exist for primes p = 1, 9 (mod 10).

    Input:
        * p: int
            A prime number. The primality of p is not verified.

    Output:
        * roots: list
            This is a list of the fibonacci primitive roots mod p. This list
            will contain no more than 2 elements.

    Examples:
        >>> fibonacci_primitive_roots(11)
        [8]
        >>> fibonacci_primitive_roots(19)
        [15]
        >>> fibonacci_primitive_roots(41)
        [7, 35]
    """
    if p % 2 == 0:
        return []
    if p == 5:
        return [3]
    if p < 5 or jacobi_symbol(5, p) != 1:
        return []

    sqrts = sqrts_mod_p(5, p)
    inverse = inverse_mod(2, p)
    roots = [(1 + root)*inverse % p for root in sqrts]
    prime_divisors = rosemary.number_theory.factorization.prime_divisors(p - 1)
    primitive_roots = []

    for r in roots:
        if is_primitive_root(r, p, prime_divisors):
            primitive_roots.append(r)
    return primitive_roots
Beispiel #11
0
def cfrac(n, k=1):
    """
    """
    def find_multiplier():
        """
        Computes a multiplier for input into the cfrac factorization algorithm.

        The method is based on Remark 5.3 from the paper "A Method of Factoring
        and the Factorization of F7" by Morrison and Brillhart.
        """
        choices = {}
        # Look for multpliers in the range [1, 1000).
        for k in xrange(1, 1000):
            if jacobi_symbol(k*n, 3) >= 0 and jacobi_symbol(k*n, 5) >= 0:
                # Find the multiplier k that allows the largest number of primes
                # <= 31 into the factor base.
                count = 0
                for p in prime_list:
                    # We've already looked at p = 3 and p = 5.
                    if p <= 5:
                        continue
                    if p > 31:
                        break
                    if jacobi_symbol(k*n, p) >= 0:
                        count += 1
                if count not in choices:
                    choices[count] = [k]
                else:
                    choices[count].append(k)
        # If several values of k allow this maximal number, we simply choose the
        # smallest of them.
        max_count = max(choices)
        return min(choices[max_count])

    def cfrac_aq_pairs(n):
        """
        Yields tripes (i, A_{i - 1}, Q_i) for i > 0, where
            A_{i - 1}^2 = (-1)^i Q_i (mod n)

        Input:
            * n: int

        Output:
            * X: generator

        Details
            This algorithm expands sqrt(n) into a simple continued fraction. The
            values (i, A_{i - 1}, Q_i) output by this algorithm correspond to
        """
        g = integer_sqrt(n)
        A0, A1 = 0, 1
        Q0, Q1 = n, 1
        P0 = 0
        r0 = g

        for i in itertools.count():
            q = (g + P0)//Q1
            r1 = g + P0 - q*Q1
            A2 = (q*A1 + A0) % n
            P1 = g - r1
            Q2 = Q0 + q*(r1 - r0)

            if i > 0:
                yield (i, A1, Q1)

            A0, A1 = A1, A2
            Q0, Q1 = Q1, Q2
            P0 = P1
            r0 = r1

    # B is our smoothness bound.
    B = int(exp(0.5*sqrt(log(n)*log(log(n))))) + 1
    prime_list = rosemary.number_theory.sieves.primes(B)

    # Choose a multiplier if none is provided.
    if k == 0:
        k = find_multiplier()
    kn = k*n

    # Perform simple trial division by the primes we computed to find any small
    # prime divisors.
    for p in prime_list:
        if n % p == 0:
            return p

    # Our factor base needs to include -1 and 2, and the odd primes p for which
    # (kN|p) = 0 or 1.
    factor_base = [-1]
    for p in prime_list:
        if p == 2 or jacobi_symbol(kn, p) >= 0:
            factor_base.append(p)

    # We compute the product of the elements in our factor base for smoothness
    # checking computations later.
    prod = 1
    for p in factor_base:
        prod *= p

    num_primes = len(factor_base)

    # Instead of using trial division to check each value for smoothness
    # individually, we use a batch smoothness test, processing batches of size
    # 'batch_size' at once.

    exponent_matrix = []
    num_smooths_found = 0
    a_list = []

    max_element = n
    power = 1
    while 2**power < max_element:
        power *= 2

    aq_pairs = cfrac_aq_pairs(kn)

    while num_smooths_found <= num_primes:
        (i, a, q) = aq_pairs.next()

        pp = pow(prod, power, q)
        g = gcd(q, pp)
        if g != q:
            continue

        if i % 2 == 1:
            q *= -1

        exponent_vector = smooth_factor(q, factor_base, num_primes)
        exponent_matrix.append(exponent_vector)
        num_smooths_found += 1
        a_list.append(a)

    kernel = z2_gaussian_elimination(exponent_matrix)

    for i in xrange(len(kernel)):
        y = 1
        x2_exponents = [0]*num_primes
        for j in xrange(len(kernel[i])):
            if kernel[i][j]:
                y = (a_list[j]*y) % n
                for f in xrange(num_primes):
                    x2_exponents[f] += exponent_matrix[j][f]

        x = 1
        for j in xrange(num_primes):
            x *= factor_base[j]**(x2_exponents[j]//2)

        for val in [x - y, x + y]:
            d = gcd(val, n)
            if 1 < d < n:
                return d
Beispiel #12
0
def sqrts_mod_p(a, p):
    """Returns the solutions x to x**2 = a (mod p).

    Given a prime p and an integer a, this function returns a sorted list of all
    solutions to the congruence x**2 = a (mod p).

    Input:
        * a: int

        * p: int (p >= 2)
            The prime modulus. The primality of p is not verified.

    Returns:
        * solutions: list
            A sorted list of solutions to x**2 = a (mod p).

    Raises:
        * ValueError: if p < 2.

    Examples:
        >>> sqrts_mod_p(10, 13)
        [6, 7]
        >>> sqrts_mod_p(3615, 2**16 + 1)
        [367, 65170]
        >>> a = 552512556430486016984082237
        >>> sqrts_mod_p(a, 2**89 - 1)
        [1000000000000000000L, 618970018642690137449562111L]
        >>> sqrts_mod_p(10, 1)
        Traceback (most recent call last):
        ...
        ValueError: sqrts_mod_p: Must have p >= 2 be prime.

    Details:
        This function uses the algorithm due to Tonelli and Shanks. One problem
        that must be solved in this algorithm is that of finding a quadratic
        nonresidue d (mod p). There is no known efficient deterministic
        algorithm to do this, so we use a randomized algorithm to find such a d.
        This gives the algorithm of Tonelli and Shanks an expected runtime of
        O(log(p)**4).

        Our implementation follows the description given as Algorithm 2.3.8 in
        "Prime Numbers - A Computational Perspective" by Crandall and Pomerance.
        See also Section 7.1 of "Algorithmic Number Theory - Efficient
        Algorithms" by Bach and Shallit. For information about some of the
        optimizations made, see Section 1.5 of "A Course in Computational
        Algebraic Number Theory" by Cohen.
    """
    # We don't test the primality of p, but we do some simple error detection.
    if p < 2:
        raise ValueError("sqrts_mod_p: Must have p >= 2 be prime.")

    # The easy case is when p == 2.
    if p == 2:
        return [a % p]

    # Take care of the case when p | a.
    a = a % p
    if a == 0:
        return [0]

    # No solutions if a is not a square modulo p.
    if jacobi_symbol(a, p) != 1:
        return []

    # Below, p is odd, so we use Tonelli-Shanks.
    # Half of the time, there is an easy solution. Namely, for primes
    # p = 3 (mod 4) a solution is given by x = a**((p + 1)/4) (mod p).
    if p % 8 in (3, 7):
        x = pow(a, (p + 1) // 4, p)

    # A slightly less trivial solution works for half of the remaining primes.
    # For p = 5 (mod 8), one can verify that a**((p - 1)/4) = 1, -1 (mod p). In
    # the positive case, then x = a**((p + 3)//8) (mod p) is a solution.
    elif p % 8 == 5:
        x = pow(a, (p + 3) // 8, p)
        if x * x % p != a:
            x = x * pow(2, (p - 1) // 4, p) % p

    # The remaining case is p = 1 (mod 8).
    else:
        # Find a quadratic nonresidue. Each choice of d will be a quadratic
        # nonresidue with probability close to 1/2, so we expect to find one
        # very quickly.
        d = randint(2, p - 1)
        while jacobi_symbol(d, p) != -1:
            d = randint(2, p - 1)

        # Write p - 1 = 2**s * t with t odd
        s = valuation(2, p - 1)
        t = (p - 1) >> s

        A = pow(a, t, p)
        D = pow(d, t, p)
        m = 0

        for i in xrange(s):
            if pow(A * D**m, 2**(s - 1 - i), p) == p - 1:
                m += 2**i

        x = pow(a, (t + 1) // 2, p) * pow(D, m // 2, p) % p

    # We want both solutions.
    solutions = sorted([x, p - x])
    return solutions
Beispiel #13
0
def sqrts_mod_p(a, p):
    """
    Returns a solution x to x^2 = a (mod p).

    Given a prime p and an integer a, this function returns all solutions to the
    congruence x^2 = a (mod p).

    Input:
        * a: int
        * p: int

    Output:
        * solutions: list

    Examples:
        >>> sqrts_mod_p(10, 13)
        [6, 7]

    Details:
        For odd primes p, this function uses the algorithm due to Tonelli and
        Shanks. See Algorithm 2.3.8 in "Prime Numbers - A Computational
        Perspective" by Crandall and Pomerance for details of the algorithm. For
        p = 2, simple checking is done to find solutions.
    """
    if p == 2:
        return [a % p]

    a = a % p
    if a == 0:
        return [0]

    if jacobi_symbol(a, p) != 1:
        return []

    if p % 8 in (3, 7):
        x = pow(a, (p + 1)//4, p)
    elif p % 8 == 5:
        x = pow(a, (p + 3)//8, p)
        if x*x % p != a:
            x = x*pow(2, (p - 1)//4, p) % p
    else:
        # Find a quadratic nonresidue
        d = randint(2, p - 1)
        while jacobi_symbol(d, p) != -1:
            d = randint(2, p - 1)

        # Write p - 1 = 2^s * t with t odd
        s = valuation(2, p - 1)
        t = (p - 1) >> s

        A = pow(a, t, p)
        D = pow(d, t, p)
        m = 0
        for i in xrange(s):
            if pow(A*D**m, 2**(s - 1 - i), p) == p - 1:
                m += 2**i
        x = pow(a, (t + 1)//2, p)*pow(D, m//2, p) % p

    solutions = [x, p - x]
    solutions.sort()
    return solutions
Beispiel #14
0
def cfrac(n, k=None):
    r"""Returns a nontrivial divisor of `n`.

    Given a composite integer `n` > 1, this algorithm attempts to find a
    factor of `n` using Morrison and Brillhart's continued fraction method
    CFRAC.

    Parameters
    ----------
    n : int (n > 1)
        Number to be factored.

    k : int, optional (default=None)
        Multiplier to use in case the period of sqrt(n) is too short.

    Returns
    -------
    d : int
        Divisor of n.

    Notes
    -----
    Morrison and Brillhart's continued fraction method was the first
    factorization algorithm of subexponential running time. The idea is to
    find a nontrivial solution to the congrunce x^2 = y^2 (mod n), and
    extracting a factor from gcd(x + y, n). See [1] for details, and see
    [2] for implementation details.

    References
    ----------
    .. [1] H. Cohen, "A Course in Computational Algebraic Number Theory",
    Springer-Verlag, New York, 2000.

    .. [2] M.A. Morrison, J. Brillhart, "A Method of Factoring and the
    Factorization of F7", Mathematics of Computation, Vol. 29, Num. 129,
    Jan. 1975.

    .. [3] H. Riesel, "Prime Numbers and Computer Methods for
    Factorization", 2nd edition, Birkhauser Verlag, Basel, Switzerland,
    1994.

    Examples
    --------
    >>> cfrac(12007001)
    4001
    >>> cfrac(1112470797641561909)
    1052788969L
    >>> cfrac(2175282241519502424792841)
    513741730823L
    """
    # B is our smoothness bound.
    B = int(exp(0.5 * sqrt(log(n) * log(log(n))))) + 1
    prime_list = sieves.primes(B)

    # Choose a multiplier if none is provided.
    if k is None:
        k = _cfrac_multiplier(n)
    kn = k * n

    # Perform simple trial division by the primes we computed to find any
    # small prime divisors.
    for p in prime_list:
        if n % p == 0:
            return p

    # Our factor base needs to include -1 and 2, and the odd primes p for
    # which (kN|p) = 0 or 1.
    factor_base = [-1]
    for p in prime_list:
        if p == 2 or jacobi_symbol(kn, p) >= 0:
            factor_base.append(p)

    num_primes = len(factor_base)

    # Compute the product of the elements in our factor base for smoothness
    # checking computations later.
    prod = 1
    for p in factor_base:
        prod *= p

    # Instead of using trial division to check each value for smoothness
    # individually, we use a batch smoothness test, processing batches of
    # size `batch_size` at once.

    # Set e as the least positive integer with n <= 2**e.
    e = 1
    while 2**e < n:
        e *= 2

    aq_pairs = _cfrac_aq_pairs(kn)

    num_smooths_found = 0
    exponent_matrix = []
    a_list = []

    while num_smooths_found <= num_primes:
        (i, a, q) = aq_pairs.next()

        # This is from the batch smoothness test given as Algorithm 3.3.1
        # in [1].
        if gcd(q, pow(prod, e, q)) != q:
            continue

        if i % 2 == 1:
            q *= -1

        # At this point, we know q is smooth, and we can factor it
        # completely using our factor base.
        exponent_vector = smooth_factor(q, factor_base)
        exponent_matrix.append(exponent_vector)
        num_smooths_found += 1
        a_list.append(a)

    kernel = _z2_gaussian_elimination(exponent_matrix)

    for i in xrange(len(kernel)):
        y = 1
        x2_exponents = [0] * num_primes
        for j in xrange(len(kernel[i])):
            if kernel[i][j]:
                y = (a_list[j] * y) % n
                for f in xrange(num_primes):
                    x2_exponents[f] += exponent_matrix[j][f]

        x = 1
        for j in xrange(num_primes):
            x *= factor_base[j]**(x2_exponents[j] // 2)

        for val in [x - y, x + y]:
            d = gcd(val, n)
            if 1 < d < n:
                return d
Beispiel #15
0
def sqrts_mod_p(a, p):
    """Returns the solutions x to x**2 = a (mod p).

    Given a prime p and an integer a, this function returns a sorted list of all
    solutions to the congruence x**2 = a (mod p).

    Input:
        * a: int

        * p: int (p >= 2)
            The prime modulus. The primality of p is not verified.

    Returns:
        * solutions: list
            A sorted list of solutions to x**2 = a (mod p).

    Raises:
        * ValueError: if p < 2.

    Examples:
        >>> sqrts_mod_p(10, 13)
        [6, 7]
        >>> sqrts_mod_p(3615, 2**16 + 1)
        [367, 65170]
        >>> a = 552512556430486016984082237
        >>> sqrts_mod_p(a, 2**89 - 1)
        [1000000000000000000L, 618970018642690137449562111L]
        >>> sqrts_mod_p(10, 1)
        Traceback (most recent call last):
        ...
        ValueError: sqrts_mod_p: Must have p >= 2 be prime.

    Details:
        This function uses the algorithm due to Tonelli and Shanks. One problem
        that must be solved in this algorithm is that of finding a quadratic
        nonresidue d (mod p). There is no known efficient deterministic
        algorithm to do this, so we use a randomized algorithm to find such a d.
        This gives the algorithm of Tonelli and Shanks an expected runtime of
        O(log(p)**4).

        Our implementation follows the description given as Algorithm 2.3.8 in
        "Prime Numbers - A Computational Perspective" by Crandall and Pomerance.
        See also Section 7.1 of "Algorithmic Number Theory - Efficient
        Algorithms" by Bach and Shallit. For information about some of the
        optimizations made, see Section 1.5 of "A Course in Computational
        Algebraic Number Theory" by Cohen.
    """
    # We don't test the primality of p, but we do some simple error detection.
    if p < 2:
        raise ValueError("sqrts_mod_p: Must have p >= 2 be prime.")

    # The easy case is when p == 2.
    if p == 2:
        return [a % p]

    # Take care of the case when p | a.
    a = a % p
    if a == 0:
        return [0]

    # No solutions if a is not a square modulo p.
    if jacobi_symbol(a, p) != 1:
        return []

    # Below, p is odd, so we use Tonelli-Shanks.
    # Half of the time, there is an easy solution. Namely, for primes
    # p = 3 (mod 4) a solution is given by x = a**((p + 1)/4) (mod p).
    if p % 8 in (3, 7):
        x = pow(a, (p + 1)//4, p)

    # A slightly less trivial solution works for half of the remaining primes.
    # For p = 5 (mod 8), one can verify that a**((p - 1)/4) = 1, -1 (mod p). In
    # the positive case, then x = a**((p + 3)//8) (mod p) is a solution.
    elif p % 8 == 5:
        x = pow(a, (p + 3)//8, p)
        if x*x % p != a:
            x = x*pow(2, (p - 1)//4, p) % p

    # The remaining case is p = 1 (mod 8).
    else:
        # Find a quadratic nonresidue. Each choice of d will be a quadratic
        # nonresidue with probability close to 1/2, so we expect to find one
        # very quickly.
        d = randint(2, p - 1)
        while jacobi_symbol(d, p) != -1:
            d = randint(2, p - 1)

        # Write p - 1 = 2**s * t with t odd
        s = valuation(2, p - 1)
        t = (p - 1) >> s

        A = pow(a, t, p)
        D = pow(d, t, p)
        m = 0

        for i in xrange(s):
            if pow(A*D**m, 2**(s - 1 - i), p) == p - 1:
                m += 2**i

        x = pow(a, (t + 1)//2, p)*pow(D, m//2, p) % p

    # We want both solutions.
    solutions = sorted([x, p - x])
    return solutions
Beispiel #16
0
def cfrac(n, k=None):
    r"""Returns a nontrivial divisor of `n`.

    Given a composite integer `n` > 1, this algorithm attempts to find a
    factor of `n` using Morrison and Brillhart's continued fraction method
    CFRAC.

    Parameters
    ----------
    n : int (n > 1)
        Number to be factored.

    k : int, optional (default=None)
        Multiplier to use in case the period of sqrt(n) is too short.

    Returns
    -------
    d : int
        Divisor of n.

    Notes
    -----
    Morrison and Brillhart's continued fraction method was the first
    factorization algorithm of subexponential running time. The idea is to
    find a nontrivial solution to the congrunce x^2 = y^2 (mod n), and
    extracting a factor from gcd(x + y, n). See [1] for details, and see
    [2] for implementation details.

    References
    ----------
    .. [1] H. Cohen, "A Course in Computational Algebraic Number Theory",
    Springer-Verlag, New York, 2000.

    .. [2] M.A. Morrison, J. Brillhart, "A Method of Factoring and the
    Factorization of F7", Mathematics of Computation, Vol. 29, Num. 129,
    Jan. 1975.

    .. [3] H. Riesel, "Prime Numbers and Computer Methods for
    Factorization", 2nd edition, Birkhauser Verlag, Basel, Switzerland,
    1994.

    Examples
    --------
    >>> cfrac(12007001)
    4001
    >>> cfrac(1112470797641561909)
    1052788969L
    >>> cfrac(2175282241519502424792841)
    513741730823L
    """
    # B is our smoothness bound.
    B = int(exp(0.5*sqrt(log(n)*log(log(n))))) + 1
    prime_list = sieves.primes(B)

    # Choose a multiplier if none is provided.
    if k is None:
        k = _cfrac_multiplier(n)
    kn = k*n

    # Perform simple trial division by the primes we computed to find any
    # small prime divisors.
    for p in prime_list:
        if n % p == 0:
            return p

    # Our factor base needs to include -1 and 2, and the odd primes p for
    # which (kN|p) = 0 or 1.
    factor_base = [-1]
    for p in prime_list:
        if p == 2 or jacobi_symbol(kn, p) >= 0:
            factor_base.append(p)

    num_primes = len(factor_base)

    # Compute the product of the elements in our factor base for smoothness
    # checking computations later.
    prod = 1
    for p in factor_base:
        prod *= p

    # Instead of using trial division to check each value for smoothness
    # individually, we use a batch smoothness test, processing batches of
    # size `batch_size` at once.

    # Set e as the least positive integer with n <= 2**e.
    e = 1
    while 2**e < n:
        e *= 2

    aq_pairs = _cfrac_aq_pairs(kn)

    num_smooths_found = 0
    exponent_matrix = []
    a_list = []

    while num_smooths_found <= num_primes:
        (i, a, q) = aq_pairs.next()

        # This is from the batch smoothness test given as Algorithm 3.3.1
        # in [1].
        if gcd(q, pow(prod, e, q)) != q:
            continue

        if i % 2 == 1:
            q *= -1

        # At this point, we know q is smooth, and we can factor it
        # completely using our factor base.
        exponent_vector = smooth_factor(q, factor_base)
        exponent_matrix.append(exponent_vector)
        num_smooths_found += 1
        a_list.append(a)

    kernel = _z2_gaussian_elimination(exponent_matrix)

    for i in xrange(len(kernel)):
        y = 1
        x2_exponents = [0]*num_primes
        for j in xrange(len(kernel[i])):
            if kernel[i][j]:
                y = (a_list[j]*y) % n
                for f in xrange(num_primes):
                    x2_exponents[f] += exponent_matrix[j][f]

        x = 1
        for j in xrange(num_primes):
            x *= factor_base[j]**(x2_exponents[j]//2)

        for val in [x - y, x + y]:
            d = gcd(val, n)
            if 1 < d < n:
                return d