def primePowerTest(n): """ This program using Algo. 1.7.5 in Cohen's book judges whether n is of the form p**k with prime p or not. If it is True, then (p,k) will be returned, otherwise (n,0). """ if n % 2 == 1: q = n while True: if not prime.primeq(q): a = 2 while prime.spsp(n, a): a += 1 d = gcd.gcd(pow(a,q,q) - a, q) if d == 1 or d == q: return (n, 0) else: q = d else: p = q break else: p = 2 k, q = arith1.vp(n, p) if q == 1: return (p, k) else: return (n, 0)
def osada(target): """ Return True if target is irreducible, False if reducible or None if undecidable. Osada's criterion is the following. Let f = \sum a_i X^i be a monic integer coefficient polynomial whose constant term is a prime number p or -p. Then, if one of the following conditions holds, f is irreducible. (1) p > 1 + \sum_{i=1}^{n-1} |ai|, (2) p >= 1 + \sum_{i=1}^{n-1} |ai| and f has no root with absolute value 1. Note that the second case is not implemented. """ # precondition if target.leading_coefficient() != 1: return None if not prime.primeq(abs(target[0])): return None # the criterion degree = target.degree() rhs = 1 + sum(abs(c) for (d, c) in target if 0 < d < degree - 1) # (1) if abs(target[0]) > rhs: return True # undecided return None
def primePowerTest(n): """ This program using Algo. 1.7.5 in Cohen's book judges whether n is of the form p**k with prime p or not. If it is True, then (p,k) will be returned, otherwise (n,0). """ if n & 1: q = n while True: if not prime.primeq(q): a = 2 while prime.spsp(n, a): a += 1 d = gcd.gcd(pow(a,q,q) - a, q) if d == 1 or d == q: return (n, 0) q = d else: p = q break else: p = 2 k, q = arith1.vp(n, p) if q == 1: return (p, k) else: return (n, 0)
def qs(n, s, f): """ This is main function of QS Arguments are (composite_number, sieve_range, factorbase_size) You must input these 3 arguments. """ a = time.time() Q = QS(n, s, f) _log.info("Sieve range is [ %d , %d ] , Factorbase size = %d , Max Factorbase %d" % (Q.move_range[0], Q.move_range[-1], len(Q.FB), Q.maxFB)) Q.run_sieve() V = Elimination(Q.smooth) A = V.gaussian() _log.info("Found %d linearly dependent relations" % len(A)) answerX_Y = [] N_factors = [] for i in A: B = V.history[i].keys() X = 1 Y = 1 for j in B: X *= Q.smooth[j][1][0] Y *= Q.smooth[j][1][1] Y = Y % Q.number X = sqrt_modn(X, Q.number) answerX_Y.append(X-Y) for k in answerX_Y: if k != 0: factor = gcd.gcd(k, Q.number) if factor not in N_factors and factor != 1 and \ factor != Q.number and prime.primeq(factor) == 1: N_factors.append(factor) N_factors.sort() _log.info("Total time = %f sec" % (time.time()-a)) _log.info(str(N_factors))
def testRegular(self): f = uniutil.polynomial(enumerate([12, 7, 1]), Z) r = zassenhaus.padic_factorization(f) self.assertTrue(isinstance(r, tuple)) self.assertEqual(2, len(r)) self.assertTrue(prime.primeq(r[0])) self.assertTrue(isinstance(r[1], list)) self.assertEqual(2, len(r[1]))
def ecm(n, curve_type=A1, incs=3, trials=20, **options): """ Find a factor of n with Elliptic Curve Method. An unsuccessful factorization returns 1. There are a few optional arguments. By 'curve_type', the function choose a family of curves. Please use a module constant to specify the curve_type. The second optional argument 'incs' specifies the number of times for changing bounds. The function repeats factorization trials several times changing curves with a fixed bounds. The last optional argument 'trials' can control how quickly move on to the next higher bounds. """ # verbosity verbose = options.get('verbose', False) if verbose: _log.setLevel(logging.DEBUG) _log.debug("verbose") else: _log.setLevel(logging.NOTSET) # trivial checks if _prime.primeq(n): _log.info("%d is prime!" % n) return n if _gcd.gcd(n, 6) != 1: _log.info("%d is not coprime to 6!" % n) if n % 2 == 0: return 2 if n % 3 == 0: return 3 # main loop bounds = Bounds(n) for inc in range(incs): _log.info("bounds increment %d times" % inc) _log.debug("Bounds B1, B2 = %s" % (bounds, )) for trial in range(trials): _log.info("Trial #: %d" % (trial + 1)) curve, point = Curve.get_random_curve_with_point( curve_type, n, bounds) _log.debug("Curve param: %d" % curve.c) g = stage1(n, bounds, curve, point) if 1 < g < n: return g g = stage2(n, bounds, curve, point) if 1 < g < n: return g bounds.increment() _log.info("ECM 2 step test failed!") if not verbose: _log.setLevel(logging.DEBUG) return 1
def ecm(n, curve_type=A1, incs=3, trials=20, **options): """ Find a factor of n with Elliptic Curve Method. An unsuccessful factorization returns 1. There are a few optional arguments. By 'curve_type', the function choose a family of curves. Please use a module constant to specify the curve_type. The second optional argument 'incs' specifies the number of times for changing bounds. The function repeats factorization trials several times changing curves with a fixed bounds. The last optional argument 'trials' can control how quickly move on to the next higher bounds. """ # verbosity verbose = options.get('verbose', False) if verbose: _log.setLevel(logging.DEBUG) _log.debug("verbose") else: _log.setLevel(logging.NOTSET) # trivial checks if _prime.primeq(n): _log.info("%d is prime!" % n) return n if _gcd.gcd(n, 6) != 1: _log.info("%d is not coprime to 6!" % n) if n % 2 == 0: return 2 if n % 3 == 0: return 3 # main loop bounds = Bounds(n) for inc in range(incs): _log.info("bounds increment %d times" % inc) _log.debug("Bounds B1, B2 = %s" % (bounds,)) for trial in range(trials): _log.info("Trial #: %d" % (trial + 1)) curve, point = Curve.get_random_curve_with_point(curve_type, n, bounds) _log.debug("Curve param: %d" % curve.c) g = stage1(n, bounds, curve, point) if 1 < g < n: return g g = stage2(n, bounds, curve, point) if 1 < g < n: return g bounds.increment() _log.info("ECM 2 step test failed!") if not verbose: _log.setLevel(logging.DEBUG) return 1
def __init__(self, representative, modulus, modulus_is_prime=True): if not modulus_is_prime and not prime.primeq(abs(modulus)): raise ValueError("modulus must be a prime.") FiniteFieldElement.__init__(self) intresidue.IntegerResidueClass.__init__(self, representative, modulus) # ring self.ring = None
def isfield(self): """ isfield returns True if the modulus is prime, False if not. Since a finite domain is a field, other ring property tests are merely aliases of isfield. """ if None == self.properties.isfield(): if prime.primeq(self.m): self.properties.setIsfield(True) else: self.properties.setIsdomain(False) return self.properties.isfield()
def isPrime(self): """ determine whether self is prime ideal or not """ if not self.isIntegral(): return False size = self.number_field.degree nrm = self.norm() p = arith1.floorpowerroot(nrm, size) if p ** size != nrm or not prime.primeq(p): return False return None #undefined
def isPrime(self): """ determine whether self is prime ideal or not """ if not self.isIntegral(): return False size = self.number_field.degree nrm = self.norm() p = arith1.floorpowerroot(nrm, size) if p**size != nrm or not prime.primeq(p): return False return None #undefined
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
def testPrimeqComposite(self): self.assertFalse(prime.primeq(1)) self.assertFalse(prime.primeq(2**2)) self.assertFalse(prime.primeq(2 * 7)) self.assertFalse(prime.primeq(3 * 5)) self.assertFalse(prime.primeq(11 * 31)) self.assertFalse( prime.primeq(1111111111111111111 * 11111111111111111111111))
def sigma(m, n): """ Return the sum of m-th powers of the factors of n. """ if n == 1: return 1 if prime.primeq(n): return 1 + n**m s = 1 for p, e in factor_misc.FactoredInteger(n): t = 1 for i in range(1, e + 1): t += (p**i)**m s *= t return s
def euler(n): """ Euler totient function. It returns the number of relatively prime numbers to n smaller than n. """ if n == 1: return 1 if prime.primeq(n): return n - 1 t = 1 for p, e in factor_misc.FactoredInteger(n): if e > 1: t *= pow(p, e - 1) * (p - 1) else: t *= p - 1 return t
def moebius(n): """ Moebius function. It returns: -1 if n has odd distinct prime factors, 1 if n has even distinct prime factors, or 0 if n has a squared prime factor. """ if n == 1: return 1 if prime.primeq(n): return -1 m = 1 for p, e in factor_misc.FactoredInteger(n): if e > 1: return 0 m = -m return m
def testPrimeqPrime(self): self.assertTrue(prime.primeq(2)) self.assertTrue(prime.primeq(3)) self.assertTrue(prime.primeq(23)) self.assertTrue(prime.primeq(1662803)) self.assertTrue(prime.primeq(1111111111111111111))
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
def mpqs(n, s=0, f=0, m=0): """ This is main function of MPQS. Arguments are (composite_number, sieve_range, factorbase_size, multiplier) You must input composite_number at least. """ T = time.time() M = MPQS(n, s, f, m) _log.info("Sieve range is [ %d , %d ] , Factorbase size = %d , Max Factorbase %d" % (M.move_range[0], M.move_range[-1], len(M.FB), M.maxFB)) M.get_vector() N = M.number // M.multiplier V = Elimination(M.smooth) A = V.gaussian() _log.info("Found %d linerly dependent relations" % len(A)) answerX_Y = [] N_prime_factors = [] N_factors = [] output = [] for i in A: B = V.history[i].keys() X = 1 Y = 1 for j in B: X *= M.smooth[j][1][0] Y *= M.smooth[j][1][1] Y = Y % M.number X = sqrt_modn(X, M.number) if X != Y: answerX_Y.append(X-Y) NN = 1 for k in answerX_Y: factor = gcd.gcd(k, N) if factor not in N_factors and factor != 1 and factor != N \ and factor not in N_prime_factors: if prime.primeq(factor): NN = NN*factor N_prime_factors.append(factor) else: N_factors.append(factor) _log.info("Total time = %f sec" % (time.time() - T)) if NN == N: _log.debug("Factored completely!") N_prime_factors.sort() for p in N_prime_factors: N = N // p i = arith1.vp(N, p, 1)[0] output.append((p, i)) return output elif NN != 1: f = N // NN if prime.primeq(f): N_prime_factors.append(f) _log.debug("Factored completely !") N_prime_factors.sort() for p in N_prime_factors: N = N // p i = arith1.vp(N, p, 1)[0] output.append((p, i)) return output for F in N_factors: for FF in N_factors: if F != FF: Q = gcd.gcd(F, FF) if prime.primeq(Q) and Q not in N_prime_factors: N_prime_factors.append(Q) NN = NN*Q N_prime_factors.sort() for P in N_prime_factors: i, N = arith1.vp(N, P) output.append((P, i)) if N == 1: _log.debug("Factored completely!! ") return output for F in N_factors: g = gcd.gcd(N, F) if prime.primeq(g): N_prime_factors.append(g) N = N // g i = arith1.vp(N, g, 1)[0] output.append((g, i)) if N == 1: _log.debug("Factored completely !! ") return output elif prime.primeq(N): output.append((N, 1)) _log.debug("Factored completely!!! ") return output else: N_factors.sort() _log.error("Sorry, not factored completely") return output, N_factors