Ejemplo n.º 1
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.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
Ejemplo n.º 2
0
def cornacchiamodify(d, p):
    """
    Algorithm 26 (Modified cornacchia)
    Input : p be a prime and d be an integer such that d < 0 and d > -4p with
            d = 0, 1 (mod 4)
    Output : the solution of u^2 -d * v^2 = 4p.
    """
    q = 4 * p
    if (d >= 0) or (d <= -q):
        raise ValueError("invalid input")
    if p == 2:
        b = arith1.issquare(d + 8)
        if b:
            return (b, 1)
        else:
            raise ValueError("no solution")
    if arith1.legendre(d, p) == -1:
        raise ValueError("no solution")
    x0 = arith1.modsqrt(d, p)
    if (x0 - d) & 1:
        x0 = p - x0
    a = 2 * p
    b = x0
    l = arith1.floorsqrt(q)
    while b > l:
        a, b = b, a % b
    c, r = divmod(q - b * b, -d)
    if r:
        raise ValueError("no solution")
    t = arith1.issquare(c)
    if t:
        return (b, t)
    else:
        raise ValueError("no solution")
Ejemplo n.º 3
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
Ejemplo n.º 4
0
def quasi_primitive(p, disc_is_minus3):
    """
    Return g s.t.
    0) 1 < g < p
    1) quadratic nonresidue modulo p
    and
    2) cubic nonresidue modulo p if p == 1 mod 3
    with p >= 3, a prime.

    For p, not a prime, condition 1 means the Jacobi symbol
    (g/p) != -1, and condition 2 means g doesn't have order
    dividing (p - 1)//3.

    if disc_is_minus3 is True, cubic nonresidue check becomes
    stricter so that g**((p-1)//3) must match with one of the
    primitive third roots of unity.
    """
    third_order = (p - 1) // 3
    for g in bigrange.range(2, p):
        # if g is not quadratic nonresidue, then skipped.
        legendre_jacobi = arith1.legendre(g, p)
        if legendre_jacobi != -1:
            continue
        # if p != 1 mod 3 or g is cubic nonresidue, it's what we need.
        if p % 3 != 1:
            return g
        cubic_symbol = pow(g, third_order, p)
        if cubic_symbol != 1:
            # g is cubic nonresidue.
            if disc_is_minus3 and pow(cubic_symbol, 3, p) != 1:
                # stricter check
                continue
            return g
    else:
        raise ValueError("p is not prime.")
Ejemplo n.º 5
0
def _ecpp_find_disc(n, era=None):
    """
    Return (disc, m, k, q, era) where:
    - disc: appropriate discriminant for ecpp
    - m: one of possible orders for disc
    - k: smooth part of m
    - q: rough part of m which is greater than (n^(1/4) + 1)^2
    - era: list of small primes
    """
    up = (arith1.floorpowerroot(n, 4) + 1) ** 2
    for disc in disc_gen(n):
        legendre = arith1.legendre(disc, n)
        if legendre == 0:
            return False
        elif legendre == -1:
            continue
        # legendre == 1:
        try:
            u, v = cornacchiamodify(disc, n)
        except ValueError:
            continue
        for m in (f(n, u, v) for f in orders.get(disc, default_orders)):
            k, q, era = _factor_order(m, up, era)
            if k:
                return disc, m, k, q, era
    else:
        # no usable discriminat found
        return False
Ejemplo n.º 6
0
def cornacchiamodify(d, p):
    """
    Algorithm 26 (Modified cornacchia)
    Input : p be a prime and d be an integer such that d < 0 and d > -4p with
            d = 0, 1 (mod 4)
    Output : the solution of u^2 -d * v^2 = 4p.
    """
    q = 4 * p
    if (d >= 0) or (d <= -q):
        raise ValueError("invalid input")
    if p == 2:
        b = arith1.issquare(d + 8)
        if b:
            return (b, 1)
        else:
            raise ValueError("no solution")
    if arith1.legendre(d, p) == -1:
        raise ValueError("no solution")
    x0 = arith1.modsqrt(d, p)
    if (x0 - d) % 2 != 0:
        x0 = p - x0
    a = 2 * p
    b = x0
    l = arith1.floorsqrt(q)
    while b > l:
        a, b = b, a % b
    c, r = divmod(q - b * b, -d)
    if r:
        raise ValueError("no solution")
    t = arith1.issquare(c)
    if t:
        return (b, t)
    else:
        raise ValueError("no solution")
Ejemplo n.º 7
0
def full_euler(n, divisors):
    """
    Return True iff n is prime.

    The method proves the primality of n by the equality
    phi(n) = n - 1, where phi denotes the Euler totient.
    It requires a sequence of all prime divisors of n - 1.

    Brillhart,J. & Selfridge,J.L., Some Factorizations of $2^n\pm 1$
    and Related Results, Math.Comp., Vol.21, 87-96, 1967
    """
    m_order = n - 1
    primes = set(divisors)
    for g in bigrange.range(2, n):
        if pow(g, m_order, n) != 1:
            return False
        if 2 in primes:
            jacobi = arith1.legendre(g, n)
            if jacobi == 0:
                return False
            elif jacobi == -1:
                primes.remove(2)
        satisfied = [
            p for p in primes if p > 2 and pow(g, m_order // p, n) != 1
        ]
        if satisfied:
            primes.difference_update(satisfied)
        if not primes:
            return True
    return True  # only when n=2, flow reaches this line
Ejemplo n.º 8
0
def _ecpp_find_disc(n, era=None):
    """
    Return (disc, m, k, q, era) where:
    - disc: appropriate discriminant for ecpp
    - m: one of possible orders for disc
    - k: smooth part of m
    - q: rough part of m which is greater than (n^(1/4) + 1)^2
    - era: list of small primes
    """
    up = (arith1.floorpowerroot(n, 4) + 1)**2
    for disc in disc_gen(n):
        legendre = arith1.legendre(disc, n)
        if legendre == 0:
            return False
        elif legendre == -1:
            continue
        # legendre == 1:
        try:
            u, v = cornacchiamodify(disc, n)
        except ValueError:
            continue
        for m in (f(n, u, v) for f in orders.get(disc, default_orders)):
            k, q, era = _factor_order(m, up, era)
            if k:
                return disc, m, k, q, era
    else:
        # no usable discriminat found
        return False
Ejemplo n.º 9
0
def cornacchia(d, p):
    """
    Return the solution of x^2 + d * y^2 = p .
    p be a prime and d be an integer such that 0 < d < p.
    """
    if (d <= 0) or (d >= p):
        raise ValueError("invalid input")
    k = arith1.legendre(-d, p)
    if k == -1:
        raise ValueError("no solution")
    x0 = arith1.modsqrt(-d, p)
    if x0 < (p / 2):
        x0 = p - x0
    a = p
    b = x0
    l = arith1.floorsqrt(p)
    while b > l:
        a, b = b, a % b
    c, r = divmod(p - b * b, d)
    if r:
        raise ValueError("no solution")
    t = arith1.issquare(c)
    if t == 0:
        raise ValueError("no solution")
    else:
        return (b, t)
Ejemplo n.º 10
0
def cornacchia(d, p):
    """
    Return the solution of x^2 + d * y^2 = p .
    p be a prime and d be an integer such that 0 < d < p.
    """
    if (d <= 0) or (d >= p):
        raise ValueError("invalid input")
    k = arith1.legendre(-d, p)
    if k == -1:
        raise ValueError("no solution")
    x0 = arith1.modsqrt(-d, p)
    if x0 < (p / 2):
        x0 = p - x0
    a = p
    b = x0
    l = arith1.floorsqrt(p)
    while b > l:
        a, b = b, a % b
    c, r = divmod(p - b * b, d)
    if r:
        raise ValueError("no solution")
    t = arith1.issquare(c)
    if t == 0:
        raise ValueError("no solution")
    else:
        return (b, t)
Ejemplo n.º 11
0
def quasi_primitive(p, disc_is_minus3):
    """
    Return g s.t.
    0) 1 < g < p
    1) quadratic nonresidue modulo p
    and
    2) cubic nonresidue modulo p if p == 1 mod 3
    with p >= 3, a prime.

    For p, not a prime, condition 1 means the Jacobi symbol
    (g/p) != -1, and condition 2 means g doesn't have order
    dividing (p - 1)//3.

    if disc_is_minus3 is True, cubic nonresidue check becomes
    stricter so that g**((p-1)//3) must match with one of the
    primitive third roots of unity.
    """
    third_order = (p - 1) // 3
    for g in bigrange.range(2, p):
        # if g is not quadratic nonresidue, then skipped.
        legendre_jacobi = arith1.legendre(g, p)
        if legendre_jacobi != -1:
            continue
        # if p != 1 mod 3 or g is cubic nonresidue, it's what we need.
        if p % 3 != 1:
            return g
        cubic_symbol = pow(g, third_order, p)
        if cubic_symbol != 1:
            # g is cubic nonresidue.
            if disc_is_minus3 and pow(cubic_symbol, 3, p) != 1:
                # stricter check
                continue
            return g
    else:
        raise ValueError("p is not prime.")
Ejemplo n.º 12
0
    def Legendre(self, element):
        """ Return generalize Legendre Symbol for FinitePrimeField.
        """
        if not element:
            return 0
        if element.n == 1 or element.m == 2:
            return 1  # trivial

        return arith1.legendre(element.n, element.m)
Ejemplo n.º 13
0
    def Legendre(self, element):
        """ Return generalize Legendre Symbol for FinitePrimeField.
        """
        if not element:
            return 0
        if element.n == 1 or element.m == 2:
            return 1 # trivial

        return arith1.legendre(element.n, element.m)
Ejemplo n.º 14
0
    def __init__(self, n, sieverange, factorbase):
        self.number = n
        self.sqrt_n = int(math.sqrt(n))
        for i in [2,3,5,7,11,17,19]:
            if n % i == 0:
                raise ValueError("This number is divided by %d" % i)

        self.digit = arith1.log(self.number, 10) + 1
        self.Srange = sieverange
        self.FBN = factorbase

        self.move_range = range(self.sqrt_n-self.Srange, self.sqrt_n+self.Srange+1)

        i = 0
        k = 0
        factor_base = [-1]
        FB_log = [0]
        while True:
            ii = primes_table[i]
            if arith1.legendre(self.number, ii) == 1:
                factor_base.append(ii)
                FB_log.append(primes_log_table[i])
                k += 1
                i += 1
                if k == self.FBN:
                    break
            else:
                i += 1

        self.FB = factor_base
        self.FB_log = FB_log
        self.maxFB = factor_base[-1]
        N_sqrt_list = []
        for i in self.FB:
            if i != 2 and i != -1:
                e = int(math.log(2*self.Srange, i))
                N_sqrt_modp = sqroot_power(self.number, i, e)
                N_sqrt_list.append(N_sqrt_modp)
        self.solution = N_sqrt_list  #This is square roots of N on Z/pZ, p in factor base.

        poly_table = []
        log_poly = []
        minus_val = []
        for j in self.move_range:
            jj = (j**2)-self.number
            if jj < 0:
                jj = -jj
                minus_val.append(j-self.sqrt_n+self.Srange)
            elif jj == 0:
                jj = 1
            lj = int((math.log(jj)*30)*0.97)  # 0.97 is an erroe
            poly_table.append(jj)
            log_poly.append(lj)
        self.poly_table = poly_table  # This is Q(x) value , x in [-M+sqrt_n,M+sqrt_n].
        self.log_poly = log_poly      # This is log(Q(x)) value.
        self.minus_check = minus_val # This is "x" that Q(x) is minus value.
Ejemplo n.º 15
0
 def choose_point(self):
     """
     Choose point on E_{a,b}(Z_n)
     Algorithm 27 (Atkin-morain ECPP) Step5
     """
     n, f = self.modulus, self.f
     x = bigrandom.randrange(n)
     Q = f(x)
     while arith1.legendre(Q, n) == -1:
         x = bigrandom.randrange(n)
         Q = f(x)
     y = arith1.modsqrt(Q, n)
     return [intresidue.IntegerResidueClass(t, n) for t in (x, y)]
Ejemplo n.º 16
0
 def choose_point(self):
     """
     Choose point on E_{a,b}(Z_n)
     Algorithm 27 (Atkin-morain ECPP) Step5
     """
     n, f = self.modulus, self.f
     x = bigrandom.randrange(n)
     Q = f(x)
     while arith1.legendre(Q, n) == -1:
         x = bigrandom.randrange(n)
         Q = f(x)
     y = arith1.modsqrt(Q, n)
     return [intresidue.IntegerResidueClass(t, n) for t in (x, y)]
Ejemplo n.º 17
0
    def make_poly(self):
        """
        Make coefficients of f(x)= ax^2+b*x+c
        """
        T = time.time()
        if self.d_list == []:
            d = int(math.sqrt((math.sqrt(self.number)/(math.sqrt(2)*self.Srange))))
            if d%2 == 0:
                if (d+1)%4 == 1: #case d=0 mod4
                    d += 3
                else:
                    d += 1       #case d=2 mod4
            elif d%4 == 1:       #case d=1 mod4
                d += 2
                                 #case d=3 mod4
        else:
            d = self.d_list[-1]

        while d in self.d_list or not prime.primeq(d) or \
              arith1.legendre(self.number,d) != 1 or d in self.FB:
            d += 4
        a = d**2
        h_0 = pow(self.number, (d-3)//4, d)
        h_1 = (h_0*self.number) % d
        h_2 = ((arith1.inverse(2,d)*h_0*(self.number - h_1**2))/d) % d
        b = (h_1 + h_2*d) % a
        if b%2 == 0:
            b = b - a

        self.d_list.append(d)
        self.a_list.append(a)
        self.b_list.append(b)

        # Get solution of  F(x) = 0 (mod p^i)
        solution = []
        i = 0
        for s in self.Nsqrt:
            k = 0
            p_solution = []
            ppow = 1
            while k < len(s):
                ppow *= self.FB[i+2]
                a_inverse = arith1.inverse(2*self.a_list[-1], ppow)
                x_1 = ((-b + s[k][0])*a_inverse) % ppow
                x_2 = ((-b + s[k][1])*a_inverse) % ppow
                p_solution.append([x_1, x_2])
                k += 1
            i += 1
            solution.append(p_solution)
        self.solution = solution
        self.coefficienttime += time.time() - T
Ejemplo n.º 18
0
def prime_mod8(n):
    """
    This is table for choosing multiplier which makes N to have
    factorbase(2,3,5,7,11,13)
    """
    primes = eratosthenes(n)
    PrimeList = {1:[], 3:[], 5:[], 7:[]}
    LegendreList = {1:[], 3:[], 5:[], 7:[]}
    sp = [2, 3, 5, 7, 11, 13]
    for p in primes:
        if p not in sp:
            leg = [arith1.legendre(p, q) for q in sp[1:]]
            if leg not in PrimeList[p % 8]:
                LegendreList[p % 8].append(leg)
                PrimeList[p % 8].append([p, leg])
    return [PrimeList[1], PrimeList[3], PrimeList[5], PrimeList[7]]
Ejemplo n.º 19
0
def _cmm_find_disc(p, absbound=DEFAULT_ABS_BOUND):
    """
    Input : a prime number p (>=3)
    Output : (disc, g, u, v) where:
            - disc: discriminant appropriate for CM method
            - g: quasi primitive element of p
            - u, v: a solution of u**2 + disc * v**2 = 4*p
    """
    for disc in disc_gen(absbound):
        if arith1.legendre(disc, p) == 1:
            try:
                u, v = cornacchiamodify(disc, p)
                g = quasi_primitive(p, disc == -3)
                return disc, g, u, v
            except ValueError:
                continue
    raise ValueError("no discriminant found")
Ejemplo n.º 20
0
def _cmm_find_disc(p, absbound=DEFAULT_ABS_BOUND):
    """
    Input : a prime number p (>=3)
    Output : (disc, g, u, v) where:
            - disc: discriminant appropriate for CM method
            - g: quasi primitive element of p
            - u, v: a solution of u**2 + disc * v**2 = 4*p
    """
    for disc in disc_gen(absbound):
        if arith1.legendre(disc, p) == 1:
            try:
                u, v = cornacchiamodify(disc, p)
                g = quasi_primitive(p, disc == -3)
                return disc, g, u, v
            except ValueError:
                continue
    raise ValueError("no discriminant found")
Ejemplo n.º 21
0
def e2_Fp(x, p):
    """
    p is prime
    f = x[0] + x[1]*t + x[2]*t**2
    """
    c, b, a = [_x % p for _x in x]
    if a == 0:
        return [e1_ZnZ([c, b], p)]
    if p == 2:
        solutions = []
        if x[0] % 2 == 0:
            solutions.append(0)
        if (x[0] + x[1] + x[2]) % 2 == 0:
            solutions.append(1)
        if len(solutions) == 1:
            return solutions * 2
        return solutions
    d = b**2 - 4*a*c
    if arith1.legendre(d, p) == -1:
        return []
    sqrtd = arith1.modsqrt(d, p)
    a = arith1.inverse(2*a, p)
    return [((-b+sqrtd)*a)%p, ((-b-sqrtd)*a)%p]
Ejemplo n.º 22
0
def e2_Fp(x, p):
    """
    p is prime
    f = x[0] + x[1]*t + x[2]*t**2
    """
    c, b, a = [_x % p for _x in x]
    if a == 0:
        return [e1_ZnZ([c, b], p)]
    if p == 2:
        solutions = []
        if x[0] & 1 == 0:
            solutions.append(0)
        if (x[0] + x[1] + x[2]) & 1 == 0:
            solutions.append(1)
        if len(solutions) == 1:
            return solutions * 2
        return solutions
    d = b**2 - 4 * a * c
    if arith1.legendre(d, p) == -1:
        return []
    sqrtd = arith1.modsqrt(d, p)
    a = arith1.inverse(2 * a, p)
    return [((-b + sqrtd) * a) % p, ((-b - sqrtd) * a) % p]
Ejemplo n.º 23
0
def by_primitive_root(n, divisors):
    """
    Return True iff n is prime.

    The method proves the primality of n by existence of a primitive
    root.  It requires a sequence of all prime divisors of n - 1.

    Lehmer,D.H., Tests for primality by the converse of Fermat's
    theorem, Bull.Amer.Math.Soc, Vol.33, pp.327-340, 1927.
    """
    m_order = n - 1
    primes = tuple(p for p in divisors if p > 2)
    for g in bigrange.range(2, n):
        jacobi = arith1.legendre(g, n)
        if jacobi == 0:
            return False
        elif jacobi == 1:
            continue
        if pow(g, m_order, n) != 1:
            return False
        if all(pow(g, m_order // p, n) != 1 for p in primes):
            return True
    return True  # only when n=2, flow reaches this line
Ejemplo n.º 24
0
    def __init__(self, n, sieverange=0, factorbase=0, multiplier=0):
        self.number = n
        _log.info("The number is %d MPQS starting" % n)

        if prime.primeq(self.number):
            raise ValueError("This number is Prime Number")
        for i in [2,3,5,7,11,13]:
            if n % i == 0:
                raise ValueError("This number is divided by %d" % i)

        self.sievingtime = 0
        self.coefficienttime = 0
        self.d_list = []
        self.a_list = []
        self.b_list = []

        #Decide prameters for each digits
        self.digit = arith1.log(self.number, 10) + 1

        if sieverange != 0:
            self.Srange = sieverange
            if factorbase != 0:
                self.FBN = factorbase
            elif self.digit < 9:
                self.FBN = parameters_for_mpqs[0][1]
            else:
                self.FBN = parameters_for_mpqs[self.digit-9][1]
        elif factorbase != 0:
            self.FBN = factorbase
            if self.digit < 9:
                self.Srange = parameters_for_mpqs[0][0]
            else:
                self.Srange = parameters_for_mpqs[self.digit-9][0]
        elif self.digit < 9:
            self.Srange = parameters_for_mpqs[0][0]
            self.FBN = parameters_for_mpqs[0][1]
        elif self.digit > 53:
            self.Srange = parameters_for_mpqs[44][0]
            self.FBN = parameters_for_mpqs[44][1]
        else:
            self.Srange = parameters_for_mpqs[self.digit-9][0]
            self.FBN = parameters_for_mpqs[self.digit-9][1]

        self.move_range = range(-self.Srange, self.Srange+1)

        # Decide k such that k*n = 1 (mod4) and k*n has many factor base
        if multiplier == 0:
            self.sqrt_state = []
            for i in [3,5,7,11,13]:
                s = arith1.legendre(self.number, i)
                self.sqrt_state.append(s)
            index8 = (self.number % 8) // 2
            j = 0
            while self.sqrt_state != prime_8[index8][j][1]:
                j += 1
            k = prime_8[index8][j][0]
        else:
            if n % 4 == 1:
                k = 1
            else:
                if multiplier == 1:
                    raise ValueError("This number is 3 mod 4 ")
                else:
                    k = multiplier
        self.number = k*self.number
        self.multiplier = k

        _log.info("%d - digits Number" % self.digit)
        _log.info("Multiplier is %d" % self.multiplier)

        # Table of (log p) , p in FB
        i = 0
        k = 0
        factor_base = [-1]
        FB_log = [0]
        while k < self.FBN:
            ii = primes_table[i]
            if arith1.legendre(self.number,ii) == 1:
                factor_base.append(ii)
                FB_log.append(primes_log_table[i])
                k += 1
            i += 1

        self.FB = factor_base
        self.FB_log = FB_log
        self.maxFB = factor_base[-1]

        # Solve x^2 = n (mod p^e)
        N_sqrt_list = []
        for i in self.FB:
            if i != 2 and i != -1:
                e = int(math.log(2*self.Srange, i))
                N_sqrt_modp = sqroot_power(self.number, i, e)
                N_sqrt_list.append(N_sqrt_modp)
        self.Nsqrt = N_sqrt_list
Ejemplo n.º 25
0
 def testLegendre(self):
     self.assertEqual(1, arith1.legendre(4, 13))
     self.assertEqual(1, arith1.legendre(396685310, 2**31 - 1))
     self.assertEqual(-1, arith1.legendre(2, 11**1293))
     self.assertEqual(1, arith1.legendre(1, 3))
     self.assertEqual(0, arith1.legendre(13 * (2**107 - 1), 2**107 - 1))