Example #1
0
    def test_inverse_mod(self):
        self.assertRaisesRegexp(ValueError, "inverse_mod: Integers must be relatively prime.", inverse_mod, 2, 4)
        self.assertRaisesRegexp(ValueError, "inverse_mod: Must have m >= 2.", inverse_mod, 10, 1)

        self.assertEqual(inverse_mod(5, 17), 7)
        self.assertEqual(inverse_mod(2, 9), 5)

        for k in xrange(1, 101):
            a = inverse_mod(k, 101)
            self.assertEqual(a*k % 101, 1)
Example #2
0
    def test_inverse_mod(self):
        self.assertRaisesRegexp(ValueError, "inverse_mod: Integers must be relatively prime.", inverse_mod, 2, 4)
        self.assertRaisesRegexp(ValueError, "inverse_mod: Must have m >= 2.", inverse_mod, 10, 1)

        self.assertEqual(inverse_mod(5, 17), 7)
        self.assertEqual(inverse_mod(2, 9), 5)

        for k in xrange(1, 101):
            a = inverse_mod(k, 101)
            self.assertEqual(a*k % 101, 1)
Example #3
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)
Example #4
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)
Example #5
0
 def hensel(a, r, p, k):
     """
     Lifts solution r^2 = a (mod p^k) to solutions modulo p^{k + 1}.
     """
     solutions = []
     if 2*r % p != 0:
         # In this case, r lifts to a unique solution.
         inverse = inverse_mod(2*r, p)
         # Note that r^2 = a (mod p^k) so the division below is exact.
         t = (-inverse*((r*r - a)//p**k)) % p
         root = r + t*p**k
         solutions.append(root)
     else:
         # Here, r lifts to p incongruent solutions modulo p^k.
         if (r*r - a) % (p**(k + 1)) == 0:
             for t in xrange(p):
                 root = r + t*p**k
                 solutions.append(root)
     solutions.sort()
     return solutions
Example #6
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
Example #7
0
def quadratic_congruence(coeff_list, n, n_factorization=None):
    """Returns a list of the roots of the quadratic equation modulo n.

    Input:
        * coeff_list: list
            A list of the coefficients of the quadratic.

        * n: int
            The modulus.

        * n_factorization: list (default=None)
            The factorization of the modulus n.

    Returns:
        * roots: list
            A sorted list of the roots of the quadratic modulo n.

    Examples:
        >>> quadratic_congruence([1, 3, -18], 1000)
        [3, 378, 619, 994]
        >>> quadratic_congruence([1, -31, -12], 36)
        [7, 15, 16, 24]
        >>> quadratic_congruence([11, 5, 18], 29)
        [22, 25]

    Details:
        The algorithm proceeds by finding roots modulo p**k for each prime power
        p**k in the factorization of the modulus n. These roots are then
        combined using the Chinese Remainder Theorem. See Chapter 5 of "The
        Theory of Numbers - A Text and Source Book of Problems" by Adler and
        Coury for detailed information.
    """
    if n_factorization is None:
        n_factorization = factor.factor(n)

    (a, b, c) = coeff_list
    discriminant = b * b - 4 * a * c
    all_roots = []

    if gcd(2 * a, n) == 1:
        # This is the easy case where we can complete the square.
        # First, we solve the congruence y^2 = b^2 - 4*a*c (mod n) for y.
        discriminant_roots = sqrts_mod_n(discriminant, n, n_factorization)

        # Next, we solve the congruence 2*a*x = y - b (mod n) for x to obtain
        # the solutions to the quadratic. Since gcd(2*a, n) == 1, this is
        # simple, and each each value of y leads to one value of x.
        inverse = inverse_mod(2 * a, n)
        for y in discriminant_roots:
            x = (y - b) * inverse % n
            all_roots.append(x)
    else:
        # Here, gcd(4*a, n) != 1, so we can't complete the square as usual.
        # Write 4*a = a1*a2, with a2 coprime to n.
        a1 = 1
        a2 = 4 * a
        d = gcd(n, a2)
        while d > 1:
            a1 *= d
            a2 /= d
            d = gcd(n, a2)

        # We solve the congruence y^2 = b^2 - 4*a*c (mod a1*n) for y.
        discriminant_roots = sqrts_mod_n(discriminant, a1 * n)

        # For each solution y, we solve 2*a*x = y - b (mod a1*n) for x. Since
        # gcd(2*a, n) > 1, each solution y leads to multiple values of x.
        for y in discriminant_roots:
            roots = linear_congruence(2 * a, y - b, a1 * n)
            all_roots.extend(roots)

        # Eliminate repeated solutions, and reduce modulo the original modulus.
        distinct_roots = {x % n for x in all_roots}
        all_roots = list(distinct_roots)

    all_roots.sort()
    return all_roots
Example #8
0
def _quadratic_lift(a, r, p, k):
    """Lifts a solution v to the congruence r**2 = a (mod p**k) to solutions
    modulo p**(k + 1).

    Suppose that for some k >= 1 we have an integer r satisfying
    r**2 = a (mod p**k). This function returns all solutions q satisfying
    q**2 = a (mod p**(k + 1)).

    Input:
        * a: int

        * r: int
            The root the the congruence r**2 = a (mod p**k).

        * p: int (p >= 2)
            A prime p, the primality of which is not verified.

        * k: int (k >= 1)
            The exponent such that r**2 = a (mod p**k).

    Returns:
        * solutions: list
            A list of all solutions c to the congruence
            c**2 = a (mod p**(k + 1))

    Raises:
        * ValueError: if k < 1 or p < 2 or r**2 != a (mod p**k).

    Examples:
        >>> 5154**2 % 11213
        119
        >>> _quadratic_lift(119, 5154, 11213, 1)
        [5869553]
        >>> 5869553**2 % 11213**2
        119
        >>> _quadratic_lift(0, 0, 7, 1)
        [0, 7, 14, 21, 28, 35, 42]

    Details:
        This function uses a simple form of Hensel lifting to obtain solutions
        modulo higher powers. See Section 12.5.2 of "A Computational
        Introduction to Number Theory and Algebra" by Shoup for details. See
        also Section 15.1 of "Introduction to Number Theory" by Hua and Theorem
        2.24 in "Fundamental Number Theory with Applications" by Mollin.
    """
    if k < 1:
        raise ValueError("_quadratic_lift: Must have k >= 1.")

    if p < 2:
        raise ValueError("_quadratic_lift: Must have p >= 2.")

    if (r * r - a) % p**k != 0:
        raise ValueError("_quadratic_lift: Must have r**2 = a (mod p**k).")

    solutions = []
    if 2 * r % p != 0:
        # In this case, r lifts to a unique solution.
        inverse = inverse_mod(2 * r, p)
        # Note that r**2 = a (mod p**k) so the division below is exact.
        t = (-inverse * ((r * r - a) // p**k)) % p
        root = r + t * p**k
        solutions.append(root)
    else:
        # Here, r lifts to p incongruent solutions modulo p**k.
        if (r * r - a) % (p**(k + 1)) == 0:
            for t in xrange(p):
                root = r + t * p**k
                solutions.append(root)

    solutions.sort()
    return solutions
Example #9
0
def quadratic_congruence(coeff_list, n, n_factorization=None):
    """
    Returns the roots of the quadratic equation modulo n.

    Input:
        * coeff_list: list
            A list of the coefficients of the quadratic.

        * n: int
            The modulus.

        * n_factorization: list (default=None)
            The factorization of the modulus n.

    Output:
        * roots: list
            A list of the roots of the quadratic modulo n.

    Details:
        The algorithm proceeds by finding roots modulo p^k for each prime power
        p^k in the factorization of the modulus n. These roots are then combined
        using the Chinese Remainder Theorem.

        The quadratic formula is used to find the roots, with the square roots
        computed modulo p^k, for each p^k dividing n. For odd primes p, the
        Tonelli-Shanks algorithm is used. For p = 2, a simple search is
        performed.

    Examples:
        >>> quadratic_congruence([1, 3, -18], 1000)
        [3, 378, 619, 994]
    """

    if n_factorization is None:
        n_factorization = rosemary.number_theory.factorization.factor(n)

    (a, b, c) = coeff_list
    discriminant = b*b - 4*a*c
    all_roots = []

    if gcd(2*a, n) == 1:
        # This is the easy case where we can complete the square.
        # First, we solve the congruence y^2 = b^2 - 4*a*c (mod n) for y.
        discriminant_roots = sqrts_mod_n(discriminant, n, n_factorization)

        # Next, we solve the congruence 2*a*x = y - b (mod n) for x to obtain
        # the solutions to the quadratic. Since gcd(2*a, n) == 1, this is
        # simple, and each each value of y leads to one value of x.
        inverse = inverse_mod(2*a, n)
        for y in discriminant_roots:
            x = (y - b)*inverse % n
            all_roots.append(x)
    else:
        # Here, gcd(4*a, n) != 1, so we can't complete the square as usual.
        # Write 4*a = a1*a2, with a2 coprime to n.
        a1 = 1
        a2 = 4*a
        d = gcd(n, a2)
        while d > 1:
            a1 *= d
            a2 /= d
            d = gcd(n, a2)

        # We solve the congruence y^2 = b^2 - 4*a*c (mod a1*n) for y.
        discriminant_roots = sqrts_mod_n(discriminant, a1*n)

        # For each solution y, we solve 2*a*x = y - b (mod a1*n) for x. Since
        # gcd(2*a, n) > 1, each solution y leads to multiple values of x.
        for y in discriminant_roots:
            roots = linear_congruence(2*a, y - b, a1*n)
            all_roots.extend(roots)

        # Eliminate repeated solutions, and reduce modulo the original modulus.
        distinct_roots = {x % n for x in all_roots}
        all_roots = list(distinct_roots)

    all_roots.sort()
    return all_roots
Example #10
0
def quadratic_congruence(coeff_list, n, n_factorization=None):
    """Returns a list of the roots of the quadratic equation modulo n.

    Input:
        * coeff_list: list
            A list of the coefficients of the quadratic.

        * n: int
            The modulus.

        * n_factorization: list (default=None)
            The factorization of the modulus n.

    Returns:
        * roots: list
            A sorted list of the roots of the quadratic modulo n.

    Examples:
        >>> quadratic_congruence([1, 3, -18], 1000)
        [3, 378, 619, 994]
        >>> quadratic_congruence([1, -31, -12], 36)
        [7, 15, 16, 24]
        >>> quadratic_congruence([11, 5, 18], 29)
        [22, 25]

    Details:
        The algorithm proceeds by finding roots modulo p**k for each prime power
        p**k in the factorization of the modulus n. These roots are then
        combined using the Chinese Remainder Theorem. See Chapter 5 of "The
        Theory of Numbers - A Text and Source Book of Problems" by Adler and
        Coury for detailed information.
    """
    if n_factorization is None:
        n_factorization = factor.factor(n)

    (a, b, c) = coeff_list
    discriminant = b*b - 4*a*c
    all_roots = []

    if gcd(2*a, n) == 1:
        # This is the easy case where we can complete the square.
        # First, we solve the congruence y^2 = b^2 - 4*a*c (mod n) for y.
        discriminant_roots = sqrts_mod_n(discriminant, n, n_factorization)

        # Next, we solve the congruence 2*a*x = y - b (mod n) for x to obtain
        # the solutions to the quadratic. Since gcd(2*a, n) == 1, this is
        # simple, and each each value of y leads to one value of x.
        inverse = inverse_mod(2*a, n)
        for y in discriminant_roots:
            x = (y - b)*inverse % n
            all_roots.append(x)
    else:
        # Here, gcd(4*a, n) != 1, so we can't complete the square as usual.
        # Write 4*a = a1*a2, with a2 coprime to n.
        a1 = 1
        a2 = 4*a
        d = gcd(n, a2)
        while d > 1:
            a1 *= d
            a2 /= d
            d = gcd(n, a2)

        # We solve the congruence y^2 = b^2 - 4*a*c (mod a1*n) for y.
        discriminant_roots = sqrts_mod_n(discriminant, a1*n)

        # For each solution y, we solve 2*a*x = y - b (mod a1*n) for x. Since
        # gcd(2*a, n) > 1, each solution y leads to multiple values of x.
        for y in discriminant_roots:
            roots = linear_congruence(2*a, y - b, a1*n)
            all_roots.extend(roots)

        # Eliminate repeated solutions, and reduce modulo the original modulus.
        distinct_roots = {x % n for x in all_roots}
        all_roots = list(distinct_roots)

    all_roots.sort()
    return all_roots
Example #11
0
def _quadratic_lift(a, r, p, k):
    """Lifts a solution v to the congruence r**2 = a (mod p**k) to solutions
    modulo p**(k + 1).

    Suppose that for some k >= 1 we have an integer r satisfying
    r**2 = a (mod p**k). This function returns all solutions q satisfying
    q**2 = a (mod p**(k + 1)).

    Input:
        * a: int

        * r: int
            The root the the congruence r**2 = a (mod p**k).

        * p: int (p >= 2)
            A prime p, the primality of which is not verified.

        * k: int (k >= 1)
            The exponent such that r**2 = a (mod p**k).

    Returns:
        * solutions: list
            A list of all solutions c to the congruence
            c**2 = a (mod p**(k + 1))

    Raises:
        * ValueError: if k < 1 or p < 2 or r**2 != a (mod p**k).

    Examples:
        >>> 5154**2 % 11213
        119
        >>> _quadratic_lift(119, 5154, 11213, 1)
        [5869553]
        >>> 5869553**2 % 11213**2
        119
        >>> _quadratic_lift(0, 0, 7, 1)
        [0, 7, 14, 21, 28, 35, 42]

    Details:
        This function uses a simple form of Hensel lifting to obtain solutions
        modulo higher powers. See Section 12.5.2 of "A Computational
        Introduction to Number Theory and Algebra" by Shoup for details. See
        also Section 15.1 of "Introduction to Number Theory" by Hua and Theorem
        2.24 in "Fundamental Number Theory with Applications" by Mollin.
    """
    if k < 1:
        raise ValueError("_quadratic_lift: Must have k >= 1.")

    if p < 2:
        raise ValueError("_quadratic_lift: Must have p >= 2.")

    if (r*r - a) % p**k != 0:
        raise ValueError("_quadratic_lift: Must have r**2 = a (mod p**k).")

    solutions = []
    if 2*r % p != 0:
        # In this case, r lifts to a unique solution.
        inverse = inverse_mod(2*r, p)
        # Note that r**2 = a (mod p**k) so the division below is exact.
        t = (-inverse*((r*r - a)//p**k)) % p
        root = r + t*p**k
        solutions.append(root)
    else:
        # Here, r lifts to p incongruent solutions modulo p**k.
        if (r*r - a) % (p**(k + 1)) == 0:
            for t in xrange(p):
                root = r + t*p**k
                solutions.append(root)

    solutions.sort()
    return solutions