Ejemplo n.º 1
0
    def test_valuation(self):
        values = [
            1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 3, 0, 0, 0, 0, 0,
            2, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 4, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0,
            0, 0, 3, 1, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0,
            0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0,
            1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 1, 0,
            2, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0, 0, 0, 0, 0, 0, 2, 0, 1, 0, 2, 0, 0, 0, 1, 0, 0, 0, 2, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 1, 3, 0, 0, 0, 0, 0, 1, 0, 1, 3, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 2, 0, 1, 0, 6, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0,
            1, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 3, 2, 0, 0, 0, 0, 0, 0, 0, 0,
            1, 0, 0, 0, 0, 0, 1, 2, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 1, 0, 0, 0,
            4, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0,
            0, 0, 1, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1,
            0, 0, 5, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 0, 0, 2, 0, 0, 1, 2, 0, 2, 0, 0
        ]

        i = 0
        for a in xrange(2, 101):
            for p in [2, 3, 5, 7, 11]:
                self.assertEqual(valuation(p, a), values[i])
                i += 1
Ejemplo n.º 2
0
    def test_valuation(self):
        values = [
            1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 3, 0, 0, 0, 0, 0,
            2, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 4, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0,
            0, 0, 3, 1, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0,
            0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0,
            1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 1, 0,
            2, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0, 0, 0, 0, 0, 0, 2, 0, 1, 0, 2, 0, 0, 0, 1, 0, 0, 0, 2, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 1, 3, 0, 0, 0, 0, 0, 1, 0, 1, 3, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 2, 0, 1, 0, 6, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0,
            1, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 3, 2, 0, 0, 0, 0, 0, 0, 0, 0,
            1, 0, 0, 0, 0, 0, 1, 2, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 1, 0, 0, 0,
            4, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0,
            0, 0, 1, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1,
            0, 0, 5, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 0, 0, 2, 0, 0, 1, 2, 0, 2, 0, 0
        ]

        i = 0
        for a in xrange(2, 101):
            for p in [2, 3, 5, 7, 11]:
                self.assertEqual(valuation(p, a), values[i])
                i += 1
Ejemplo n.º 3
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
Ejemplo n.º 4
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
Ejemplo n.º 5
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