Beispiel #1
0
 def register(self, divisor, isprime=Unknown):
     """
     Register a divisor of the number, if the divisor is a true
     divisor of the number.  The number is divided by the divisor
     as many times as possible.
     """
     for base, index in self.factors:
         if base == divisor:
             if isprime and not self.primality[base]:
                 self.setPrimality(base, isprime)
             break
         common_divisor = gcd.gcd(base, divisor)
         if common_divisor == 1:
             continue
         # common_divisor > 1:
         if common_divisor == divisor:
             if isprime:
                 self.setPrimality(divisor, isprime)
             k, coprime = arith1.vp(base, common_divisor)
             while not gcd.coprime(common_divisor, coprime):
                 # try a smaller factor
                 common_divisor = gcd.gcd(common_divisor, coprime)
                 k, coprime = arith1.vp(base, common_divisor)
             if k:
                 if coprime > 1:
                     self.replace(base, [(common_divisor, k), (coprime, 1)])
                 else:
                     self.replace(base, [(common_divisor, k)])
         else:  # common_divisor properly divides divisor.
             self.register(common_divisor)
             self.register(divisor // common_divisor)
Beispiel #2
0
def _lucas_test_sequence(n, a, b):
    """
    Return x_0, x_1, x_m, x_{m+1} of Lucas sequence of parameter a, b,
    where m = (n - (a**2 - 4*b / n)) // 2.
    """
    d = a**2 - 4*b
    if (d >= 0 and arith1.floorsqrt(d) ** 2 == d) \
    or not(gcd.coprime(n, 2*a*b*d)):
        raise ValueError("Choose another parameters.")

    x_0 = 2
    inv_b = arith1.inverse(b, n)
    x_1 = ((a ** 2) * inv_b - 2) % n

    # Chain functions
    def even_step(u):
        """
        'double' u.
        """
        return (u**2 - x_0) % n

    def odd_step(u, v):
        """
        'add' u and v.
        """
        return (u*v - x_1) % n

    m = (n - arith1.legendre(d, n)) // 2
    x_m, x_mplus1 = Lucas_chain(m, even_step, odd_step, x_0, x_1)

    return x_0, x_1, x_m, x_mplus1
def _lucas_test_sequence(n, a, b):
    """
    Return x_0, x_1, x_m, x_{m+1} of Lucas sequence of parameter a, b,
    where m = (n - (a**2 - 4*b / n)) // 2.
    """
    d = a**2 - 4 * b
    if (d >= 0 and arith1.issquare(d) or not (gcd.coprime(n, 2 * a * b * d))):
        raise ValueError("Choose another parameters.")

    x_0 = 2
    inv_b = arith1.inverse(b, n)
    x_1 = ((a**2) * inv_b - 2) % n

    # Chain functions
    def even_step(u):
        """
        'double' u.
        """
        return (u**2 - x_0) % n

    def odd_step(u, v):
        """
        'add' u and v.
        """
        return (u * v - x_1) % n

    m = (n - arith1.legendre(d, n)) // 2
    x_m, x_mplus1 = _lucas_chain(m, even_step, odd_step, x_0, x_1)

    return x_0, x_1, x_m, x_mplus1
Beispiel #4
0
 def register(self, divisor, isprime=Unknown):
     """
     Register a divisor of the number, if the divisor is a true
     divisor of the number.  The number is divided by the divisor
     as many times as possible.
     """
     for base, index in self.factors:
         if base == divisor:
             if isprime and not self.primality[base]:
                 self.setPrimality(base, isprime)
             break
         common_divisor = gcd.gcd(base, divisor)
         if common_divisor == 1:
             continue
         # common_divisor > 1:
         if common_divisor == divisor:
             if isprime:
                 self.setPrimality(divisor, isprime)
             k, coprime = arith1.vp(base, common_divisor)
             while not gcd.coprime(common_divisor, coprime):
                 # try a smaller factor
                 common_divisor = gcd.gcd(common_divisor, coprime)
                 k, coprime = arith1.vp(base, common_divisor)
             if k:
                 if coprime > 1:
                     self.replace(base, [(common_divisor, k), (coprime, 1)])
                 else:
                     self.replace(base, [(common_divisor, k)])
         else: # common_divisor properly divides divisor.
             self.register(common_divisor)
             self.register(divisor // common_divisor)
def next_probable_prime(n, times=20):
    """
    Return the smallest probable prime bigger than the given integer.
    n ought to be greater than, say, 1000.  There is no penalty to use
    prime.nextPrime(n) for n less than 10**12.

    This implementation uses miller_rabin to determine the
    pseudoprimality, and 'times' parameter can be specified.
    """
    n += (1 + (n & 1))  # make n be odd.
    while not gcd.coprime(n, 510510) or not miller_rabin(n, times):
        n += 2
    return n
Beispiel #6
0
def embedding(f_q1, f_q2):
    """
    Return embedding homomorphism function from f_q1 to f_q2,
    where q1 = p ** k1, q2 = p ** k2 and k1 divides k2.
    """
    if card(f_q1) == card(f_q2):
        return fqiso(f_q1, f_q2)
    # search multiplicative generators of both fields and relate them.
    # 0. initialize basic variables
    p = f_q2.getCharacteristic()
    q1, q2 = card(f_q1), card(f_q2)
    q1_mult_order, q2_mult_order = q1 - 1, q2 - 1

    # 1. find a multiplicative generator of f_q2
    for i in bigrange.range(p, q2):
        f_q2_gen = f_q2.createElement(i)
        if f_q2.order(f_q2_gen) == q2_mult_order:
            break
    f_q2_subgen = f_q2_gen**((q2 - 1) // (q1 - 1))

    # 2.1 minimal polynomial of g = f_q2_gen ** ((q2 - 1) // (q1 - 1))
    #   minpoly = (X - g)(X - g**p)...(X - g**(p**(k1 - 1)))
    q, gpow = 1, f_q2_subgen
    linear_factors = []
    while q < q2:
        linear_factors.append(univar.BasicPolynomial({0: gpow, 1: f_q2.one}))
        # finally, raise power (Frobenius map).
        q *= p
        gpow **= p
    minpoly = arith1.product(linear_factors)
    # 2.2 minpoly has f_q2 coefficints but they are indeed f_p elements
    minpoly = univar.BasicPolynomial([(d, c.rep[0]) for (d, c) in minpoly])

    # 3. find a multiplicative generator of f_q1
    for i in bigrange.range(p, q1):
        f_q1_gen = f_q1.createElement(i)
        if f_q1.order(f_q1_gen) == q1_mult_order:
            break

    # 4. find f_q1_gen ** c of a root of minpoly and let it f_q1_gen
    for c in bigrange.range(1, q1):
        if gcd.coprime(c, q1_mult_order):
            if not minpoly(f_q1_gen**c):
                break
    f_q1_gen = f_q1_gen**c

    # 5. solve DLP:
    #   x_1 = f_q1_gen ** t
    #   (Here uses "brute force" method)
    x_1 = f_q1.createElement(p)
    gpow = f_q1_gen
    for i in bigrange.range(1, q):
        if gpow == x_1:
            image_of_x_1 = f_q2_subgen**i
            break
        gpow *= f_q1_gen

    # finally, define a function
    def f_q1_to_f_q2_homo(f_q1_elem):
        """
        Return the image of the isomorphism of the given element.
        """
        if not f_q1_elem:
            return f_q2.zero
        if f_q1_elem.rep.degree() == 0:
            # F_p elements
            return f_q2.createElement(f_q1_elem.rep)
        return f_q1_elem.rep(image_of_x_1)

    return f_q1_to_f_q2_homo