pyecm Namespace Reference


Classes

class  ts

Functions

def gcd
def invert
def next_prime
def mpz
def root
def sqrt
def add
def add_sub_x_only
def atdn
def copy
def could_be_prime
def double
def fastprime
def greatest_n
def inv_const
def naf
def parallel_invert
def prod
def rho_ev
def rho_ts
def sub_sub_sure_factors
def sub_sure_factors
def subtract
def congrats
def sure_factors
def to_tuple
def mainloop
def fast_multiply
def get_points
def isprime
def multiply
def ecm
def factors
def is_switch
def parse_switch
def valid_input
def help
def command_line
def interactive
def main

Variables

 PSYCO_EXISTS = True
 GMPY_EXISTS = True
tuple PRIMES = (5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 167)
float INV_C = 1.4
tuple LOG_2 = math.log(2)
tuple LOG_4 = math.log(4)
tuple LOG_3_MINUS_LOG_LOG_2 = math.log(3)
int LOG_4_OVER_9 = 9
int _3_OVER_LOG_2 = 3
int _5_LOG_10 = 5
int _7_OVER_LOG_2 = 7
float BIG = 2.0
int BILLION = 10
tuple MULT = math.log(3)
tuple ONE = mpz(1)
float SMALL = 2.0
int SMALLEST_COUNTEREXAMPLE_FASTPRIME = 2047
tuple T = (type(mpz(1)), type(1), type(1L))
string DUMMY = 'dummy'
string VERSION = '2.0'
int _12_LOG_2_OVER_49 = 12
int RECORD = 1162795072109807846655696105569042240239

Function Documentation

def pyecm::add (   p1,
  p2,
  n 
)

Adds first argument to second (second argument is not preserved). The arguments are points on an elliptic curve. The first argument may be a tuple instead of a list. The addition is thus done pointwise. This function has bizzare input/output because there are fast algorithms for inverting a bunch of numbers at once.

Returns a list of the addition results.

Definition at line 324 of file pyecm.py.

00324                    :
00325         '''Adds first argument to second (second argument is not preserved). The arguments are points on an elliptic curve. The first argument may be a tuple instead of a list. The addition is thus done pointwise. This function has bizzare input/output because there are fast algorithms for inverting a bunch of numbers at once.
00326 
00327 Returns a list of the addition results.'''
00328         inv = range(len(p1))
00329 
00330         for i in xrange(len(p1)):
00331                 inv[i] = p1[i][0] - p2[i][0]
00332 
00333         inv = parallel_invert(inv, n)
00334 
00335         if not isinstance(inv, list):
00336                 return inv
00337         
00338         for i in xrange(len(p1)):
00339                 m = ((p1[i][1] - p2[i][1]) * inv[i]) % n
00340                 p2[i][0] = (m * m - p1[i][0] - p2[i][0]) % n
00341                 p2[i][1] = (m * (p1[i][0] - p2[i][0]) - p1[i][1]) % n
00342 
00343         return p2
00344 
def add_sub_x_only(p1, p2,  n):

def pyecm::add_sub_x_only (   p1,
  p2,
  n 
)

Given a pair of lists of points p1 and p2, computes the x-coordinates of
p1[i] + p2[i] and p1[i] - p2[i] for each i.

Returns two lists, the first being the sums and the second the differences.

Definition at line 345 of file pyecm.py.

00345                               :
00346         '''Given a pair of lists of points p1 and p2, computes the x-coordinates of
00347 p1[i] + p2[i] and p1[i] - p2[i] for each i.
00348 
00349 Returns two lists, the first being the sums and the second the differences.'''
00350         sums = range(len(p1))
00351         difs = range(len(p1))
00352         
00353         for i in xrange(len(p1)):
00354                 sums[i] = p2[i][0] - p1[i][0]
00355 
00356         sums = parallel_invert(sums, n)
00357 
00358         if not isinstance(sums, list):
00359                 return (sums, None)
00360         
00361         for i in xrange(len(p1)):
00362                 ms = ((p2[i][1] - p1[i][1]) * sums[i]) % n
00363                 md = ((p2[i][1] + p1[i][1]) * sums[i]) % n
00364                 sums[i] = (ms * ms - p1[i][0] - p2[i][0]) % n
00365                 difs[i] = (md * md - p1[i][0] - p2[i][0]) % n
00366 
00367         sums = tuple(sums)
00368         difs = tuple(difs)
00369 
00370         return (sums, difs)
00371 
def atdn(a, d, n):

def pyecm::atdn (   a,
  d,
  n 
)

Calculates a to the dth power modulo n.

Returns the calculation's result.

Definition at line 372 of file pyecm.py.

00372                  :
00373         '''Calculates a to the dth power modulo n.
00374 
00375 Returns the calculation's result.'''
00376         x = 1
00377         pos = int(math.log(d) / LOG_2)
00378 
00379         while pos >= 0:
00380                 x = (x * x) % n
00381                 if (d >> pos) & 1:
00382                         x *= a
00383                 pos -= 1
00384 
00385         return x % n
00386 
def copy(p):

def pyecm::command_line (   veb,
  ra,
  ov,
  pr 
)

Definition at line 1354 of file pyecm.py.

01354                                  :
01355         l = len(sys.argv)
01356         for i in xrange(1, l):
01357                 if not is_switch(sys.argv[i]):
01358                         break
01359 
01360         for j in xrange(i, l): # Start with the first non-switch
01361                 if j != i: # Pretty printing
01362                         print
01363                 response = sys.argv[j]
01364                 if valid_input(response):
01365                         response = response.replace('^', '**')
01366                         try:
01367                                 n = eval(response)
01368                                 int(n)
01369                         except (SyntaxError, TypeError, ValueError):
01370                                 help()
01371                 else:
01372                         help()
01373 
01374                 print   'Factoring %d:' % n
01375                 if n < 0:
01376                         print   -1
01377                         n = -n
01378                         continue
01379                 if n == 0:
01380                         print   '0 does not have a well-defined factorization.'
01381                         continue
01382                 elif n == 1:
01383                         print   1
01384                         continue
01385 
01386                 if ov == DUMMY:
01387                         ov = 2*math.log(math.log(n))
01388                 for factor in factors(n, veb, ra, ov, pr):
01389                         print factor
01390 
def interactive(veb, ra, ov, pr):

def pyecm::congrats (   f,
  veb 
)

Prints a congratulations message when a record factor is found. This only happens if the second parameter (verbosity) is set to True.

Returns nothing.

Definition at line 772 of file pyecm.py.

00772                     :
00773         '''Prints a congratulations message when a record factor is found. This only happens if the second parameter (verbosity) is set to True.
00774 
00775 Returns nothing.'''
00776 
00777         if veb and f > RECORD:
00778                 print 'Congratulations! You may have found a record factor via pyecm!'
00779                 print 'Please email the Mainloop call to Eric Larson <elarson3@uoregon.edu>'
00780 
00781         return
00782 
def sure_factors(n, u, curve_params, veb, ra, ov, tdb, pr):

def pyecm::copy (   p  ) 

Copies a list using only deep copies.

Returns a copy of p.

Definition at line 387 of file pyecm.py.

00387            :
00388         '''Copies a list using only deep copies.
00389 
00390 Returns a copy of p.'''
00391         answer = []
00392         for i in p:
00393                 answer.append(i[:])
00394 
00395         return answer
00396 
def could_be_prime(n):

def pyecm::could_be_prime (   n  ) 

Performs some trials to compute whether n could be prime. Run time is O(N^3 / (log N)^2) for N bits.

Returns whether it is possible for n to be prime (True or False).

Definition at line 397 of file pyecm.py.

00397                      :
00398         '''Performs some trials to compute whether n could be prime. Run time is O(N^3 / (log N)^2) for N bits.
00399 
00400 Returns whether it is possible for n to be prime (True or False).
00401 '''
00402         if n < 2:
00403                 return False
00404         if n == 2:
00405                 return True
00406         if not n & 1:
00407                 return False
00408 
00409         product = ONE
00410         log_n = int(math.log(n)) + 1
00411         bound = int(math.log(n) / (LOG_2 * math.log(math.log(n))**2)) + 1
00412         if bound * log_n >= n:
00413                 bound = 1
00414                 log_n = int(sqrt(n))
00415         prime_bound = 0
00416         prime = 3
00417 
00418         for _ in xrange(bound):
00419                 p = []
00420                 prime_bound += log_n
00421                 while prime <= prime_bound:
00422                         p.append(prime)
00423                         prime = next_prime(prime)
00424                 if p != []:
00425                         p = prod(p)
00426                         product = (product * p) % n
00427 
00428         return gcd(n, product) == 1
00429 
def double(p, n):

def pyecm::double (   p,
  n 
)

Doubles each point in the input list. Much like the add function, we take advantage of fast inversion.

Returns the doubled list.

Definition at line 430 of file pyecm.py.

00430                 :
00431         '''Doubles each point in the input list. Much like the add function, we take advantage of fast inversion.
00432 
00433 Returns the doubled list.'''
00434         inv = range(len(p))
00435 
00436         for i in xrange(len(p)):
00437                 inv[i] = p[i][1] << 1
00438 
00439         inv = parallel_invert(inv, n)
00440 
00441         if not isinstance(inv, list):
00442                 return inv
00443 
00444         for i in xrange(len(p)):
00445                 x = p[i][0]
00446                 m = (x * x) % n
00447                 m = ((m + m + m + p[i][2]) * inv[i]) % n
00448                 p[i][0] = (m * m - x - x) % n
00449                 p[i][1] = (m * (x - p[i][0]) - p[i][1]) % n
00450 
00451         return p
00452 
def fastprime(n): 

def pyecm::ecm (   n,
  ra,
  ov,
  veb,
  tdb,
  pr 
)

Input:
n   -- An integer to factor
veb -- If True, be verbose
ra  -- If True, select sigma values randomly
ov  -- How asymptotically fast the calculation is
pr  -- What portion of the total processing power this run gets

Output: Factors of n, via a generator.

Notes:
1. A good value of ov for typical numbers is somewhere around 10. If this parameter is too high, overhead and memory usage grow.
2. If ra is set to False and veb is set to True, then results are reproducible. If ra is set to True, then one number may be done in parallel on disconnected machines (at only a small loss of efficiency, which is less if pr is set correctly).

Definition at line 1134 of file pyecm.py.

01134                                 : # DOCUMENTATION
01135         '''Input:
01136         n   -- An integer to factor
01137         veb -- If True, be verbose
01138         ra  -- If True, select sigma values randomly
01139         ov  -- How asymptotically fast the calculation is
01140         pr  -- What portion of the total processing power this run gets
01141 
01142 Output: Factors of n, via a generator.
01143 
01144 Notes:
01145 1. A good value of ov for typical numbers is somewhere around 10. If this parameter is too high, overhead and memory usage grow.
01146 2. If ra is set to False and veb is set to True, then results are reproducible. If ra is set to True, then one number may be done in parallel on disconnected machines (at only a small loss of efficiency, which is less if pr is set correctly).'''
01147 
01148         if veb:
01149                 looking_for = 0
01150         k = inv_const(n)
01151 
01152         if ra:
01153                 sigma = 6 + random.randrange(BILLION)
01154         else:
01155                 sigma = 6
01156 
01157         for factor in sure_factors(n, k, range(sigma, sigma + k), veb, ra, ov, tdb, pr):
01158                 yield factor
01159                 n /= factor
01160 
01161         if n == 1:
01162                 return
01163 
01164         if ra:
01165                 sigma += k + random.randrange(BILLION)
01166         else:
01167                 sigma += k
01168 
01169         x_max = 0.5 * math.log(n) / math.log(k)
01170         t = rho_ts(int(x_max))
01171         prime_probs = []
01172         nc = 1 + int(_12_LOG_2_OVER_49 * ov * ov * k)
01173         eff_nc = nc / pr
01174 
01175         for i in xrange(1 + (int(math.log(n)) >> 1)):
01176                 if i < math.log(tdb):
01177                         prime_probs.append(0)
01178                 else:
01179                         prime_probs.append(1.0/i)
01180 
01181         for i in xrange(len(prime_probs)):
01182                 p_success = rho_ev((i - 2.65) / math.log(k), t)
01183                 p_fail = max(0, (1 - p_success * math.log(math.log(k)))) ** (k / pr)
01184                 prime_probs[i] = p_fail * prime_probs[i] / (p_fail * prime_probs[i] + 1 - prime_probs[i])
01185 
01186         while n != 1:
01187                 low = int(k)
01188                 high = n
01189                 while high > low + 1:
01190                         u = (high + low) >> 1
01191                         sum = 0
01192                         log_u = math.log(u)
01193                         for i in xrange(len(prime_probs)):
01194                                 log_p = i - 2.65
01195                                 log_u = math.log(u)
01196                                 quot = log_p / log_u
01197                                 sum += prime_probs[i] * (rho_ev(quot - 1, t) - rho_ev(quot, t) * log_u)
01198                         if sum < 0:
01199                                 high = u
01200                         else:
01201                                 low = u
01202 
01203                 if ra:
01204                         sigma += nc + random.randrange(BILLION)
01205                 else:
01206                         sigma += nc
01207 
01208                 for factor in sure_factors(n, u, range(sigma, sigma + nc), veb, ra, ov, tdb, pr):
01209                         yield factor
01210                         n /= factor
01211 
01212                 for i in xrange(len(prime_probs)):
01213                         p_success = rho_ev((i - 2.65) / math.log(u), t)
01214                         p_fail = max(0, (1 - p_success * math.log(math.log(u)))) ** eff_nc
01215                         prime_probs[i] = p_fail * prime_probs[i] / (p_fail * prime_probs[i] + 1 - prime_probs[i])
01216                 prime_probs = prime_probs[:1 + (int(math.log(n)) >> 1)]
01217 
01218                 if veb and n != 1:
01219                         m = max(prime_probs)
01220                         for i in xrange(len(prime_probs)):
01221                                 if prime_probs[i] == m:
01222                                         break
01223 
01224                         new_looking_for = (int(i / _5_LOG_10) + 1)
01225                         new_looking_for += new_looking_for << 2
01226                         if new_looking_for != looking_for:
01227                                 looking_for = new_looking_for
01228                                 print 'Searching for primes around', looking_for, 'digits'
01229 
01230         return
01231 

def pyecm::factors (   n,
  veb,
  ra,
  ov,
  pr 
)

Generates factors of n.
Strips small primes, then feeds to ecm function.

Input:
n   -- An integer to factor
veb -- If True, be verbose
ra  -- If True, select sigma values randomly
ov  -- How asymptotically fast the calculation is
pr  -- What portion of the total processing power this run gets

Output: Factors of n, via a generator.

Notes:
1. A good value of ov for typical numbers is somewhere around 10. If this parameter is too high, overhead and memory usage grow.
2. If ra is set to False and veb is set to True, then results are reproducible. If ra is set to True, then one number may be done in parallel on disconnected machines (at only a small loss of efficiency, which is less if pr is set correctly).

Definition at line 1232 of file pyecm.py.

01232                                :
01233         '''Generates factors of n.
01234 Strips small primes, then feeds to ecm function.
01235 
01236 Input:
01237         n   -- An integer to factor
01238         veb -- If True, be verbose
01239         ra  -- If True, select sigma values randomly
01240         ov  -- How asymptotically fast the calculation is
01241         pr  -- What portion of the total processing power this run gets
01242 
01243 Output: Factors of n, via a generator.
01244 
01245 Notes:
01246 1. A good value of ov for typical numbers is somewhere around 10. If this parameter is too high, overhead and memory usage grow.
01247 2. If ra is set to False and veb is set to True, then results are reproducible. If ra is set to True, then one number may be done in parallel on disconnected machines (at only a small loss of efficiency, which is less if pr is set correctly).'''
01248 
01249 
01250         if type(n) not in T:
01251                 raise ValueError, 'Number given must be integer or long.'
01252 
01253         if not 0 < pr <= 1:
01254                 yield 'Error: pr must be between 0 and 1'
01255                 return
01256 
01257         while not n & 1:
01258                 n >>= 1
01259                 yield 2
01260 
01261         n = mpz(n)
01262         k = inv_const(n)
01263         prime = 2
01264         trial_division_bound = max(10 * k**2, 100)
01265 
01266         while prime < trial_division_bound:
01267                 prime = next_prime(prime)
01268                 while not n % prime:
01269                         n /= prime
01270                         yield prime
01271 
01272         if isprime(n):
01273                 yield n
01274                 return
01275 
01276         if n == 1:
01277                 return
01278 
01279         for factor in ecm(n, ra, ov, veb, trial_division_bound, pr):
01280                 yield factor
01281 
### End of algorithm code; beginning of interface code ##

def pyecm::fast_multiply (   p,
  d,
  n,
  w 
)

Multiplies each element of p by d. Multiplication is on
an elliptic curve. Both d and <p> must be odd. Also, <p> may not be divisible by anything less than or equal to 2 * (2**w + (-1)**w) / 3 + 1.

Returns the list p multiplied by d.

Definition at line 991 of file pyecm.py.

00991                              :
00992         '''Multiplies each element of p by d. Multiplication is on
00993 an elliptic curve. Both d and <p> must be odd. Also, <p> may not be divisible by anything less than or equal to 2 * (2**w + (-1)**w) / 3 + 1.
00994 
00995 Returns the list p multiplied by d.'''
00996 
00997         mask = (1 << (w << 1)) - 1
00998         flop = mask / 3
00999         g = naf(d) >> 4
01000         precomp = {}
01001         m = copy(p)
01002         p = double(p, n)
01003 
01004         for i in xrange((flop >> w) + (w & 1)):
01005                 key = naf((i << 1) + 1)
01006                 precomp[key] = to_tuple(m)
01007                 precomp[((key & flop) << 1) ^ key] = precomp[key]
01008                 m = add(p, m, n)
01009         
01010         while g > 0:
01011                 if g & 1:
01012                         t = g & mask
01013                         sh = 1 + int(math.log(t) / LOG_4)
01014                         for _ in xrange(sh):
01015                                 p = double(p, n)
01016 
01017                         if g & 2:
01018                                 p = subtract(precomp[t], p, n)
01019                         else:
01020                                 p = add(precomp[t], p,  n)
01021 
01022                         g >>= (sh << 1)
01023                         if not isinstance(p, list):
01024                                 return p
01025                 else:
01026                         p = double(p, n)
01027                         g >>= 2
01028 
01029         return p 
01030 
def get_points(p1, n):

def pyecm::fastprime (   n  ) 

Tests for primality of n using an algorithm that is very fast, O(N**3 / log(N)) (assuming quadratic multiplication) where n has N digits, but ocasionally inaccurate for n >= 2047.

Returns the primality of n (True or False).

Definition at line 453 of file pyecm.py.

00453                 : 
00454         '''Tests for primality of n using an algorithm that is very fast, O(N**3 / log(N)) (assuming quadratic multiplication) where n has N digits, but ocasionally inaccurate for n >= 2047.
00455 
00456 Returns the primality of n (True or False).'''
00457         if not could_be_prime(n):
00458                 return False
00459         if n == 2:
00460                 return True
00461 
00462         j = 1 
00463         d = n >> 1 
00464 
00465         while not d & 1: 
00466                 d >>= 1 
00467                 j += 1 
00468 
00469         p = 1
00470         pos = int(math.log(d) / LOG_2)
00471 
00472         while pos >= 0:
00473                 p = (p * p) % n
00474                 p <<= (d >> pos) & 1
00475                 pos -= 1
00476 
00477         if p in (n - 1, n + 1): 
00478                 return True 
00479 
00480         for _ in xrange(j): 
00481                 p = (p * p) % n  
00482 
00483                 if p == 1: 
00484                         return False 
00485                 elif p == n - 1: 
00486                         return True 
00487 
00488         return False
00489 

def pyecm::gcd (   a,
  b 
)

Computes the Greatest Common Divisor of a and b using the standard quadratic time improvement to the Euclidean Algorithm.

	Returns the GCD of a and b.

Definition at line 36 of file pyecm.py.

00036                      :
00037                 '''Computes the Greatest Common Divisor of a and b using the standard quadratic time improvement to the Euclidean Algorithm.
00038 
00039         Returns the GCD of a and b.'''
00040                 if b == 0:
00041                         return a
00042                 elif a == 0:
00043                         return b
00044 
00045                 count = 0
00046 
00047                 if a < 0:
00048                         a = -a
00049                 if b < 0:
00050                         b = -b
00051 
00052                 while not ((a & 1) | (b & 1)):
00053                         count += 1
00054                         a >>= 1
00055                         b >>= 1
00056 
00057                 while not a & 1:
00058                         a >>= 1
00059 
00060                 while not b & 1:
00061                         b >>= 1
00062 
00063                 if b > a:
00064                         b,a = a,b
00065 
00066                 while b != 0 and a != b:
00067                         a -= b
00068                         while not (a & 1):
00069                                 a >>= 1
00070 
00071                         if b > a:
00072                                 b, a = a, b
00073 
00074                 return a << count
00075 
        def invert(a, b):

def pyecm::get_points (   p1,
  n 
)

Outputs points in Weierstrass form, given input in Suyama
parametrization.

Returns the points.

Definition at line 1031 of file pyecm.py.

01031                      :
01032         '''Outputs points in Weierstrass form, given input in Suyama
01033 parametrization.
01034 
01035 Returns the points.'''
01036         p1 = list(p1)
01037         invs = p1[:]
01038         ncurves = len(p1)
01039 
01040         for j in xrange(ncurves):
01041                 sigma = mpz(p1[j])
01042                 u = (sigma**2 - 5) % n
01043                 v = sigma << 2
01044                 i = (((u * u) % n) * ((v * u << 2) % n)) % n
01045                 p1[j] = [u, v, i]
01046                 invs[j] = (i * v) % n
01047 
01048         invs = parallel_invert(invs, n)
01049         if not isinstance(invs, list):
01050                 return invs
01051 
01052         for j in xrange(ncurves):
01053                 u, v, i = p1[j]
01054                 inv = invs[j]
01055 
01056                 a = (((((((v - u)**3 % n) * v) % n) * (u + u + u + v)) % n) * inv - 2) % n # <-- This line is a thing of beauty
01057                 x_0 = (((((u * i) % n) * inv) % n) ** 3) % n # And this one gets second place
01058                 b = ((((x_0 + a) * x_0 + 1) % n) * x_0) % n
01059                 x_0 = (b * x_0) % n
01060                 y_0 = (b**2) % n
01061 
01062                 while a % 3:
01063                         a += n
01064 
01065                 x_0 = (x_0 + a * b / 3) % n
01066                 c = (y_0 * ((1 - a**2 / 3) % n)) % n
01067 
01068                 p1[j] = [x_0, y_0, c]
01069 
01070         return p1
01071 
def isprime(n): 

def pyecm::greatest_n (   phi_max  ) 

Finds the greatest n such that phi(n) < phi_max.

Returns the greatest n such that phi(n) < phi_max.

Definition at line 490 of file pyecm.py.

00490                        :
00491         '''Finds the greatest n such that phi(n) < phi_max.
00492 
00493 Returns the greatest n such that phi(n) < phi_max.'''
00494         phi_product = 1
00495         product = 1
00496         prime = 1
00497         while phi_product <= phi_max:
00498                 prime = next_prime(prime)
00499                 phi_product *= prime - 1
00500                 product *= prime
00501 
00502         n_max = (phi_max * product) / phi_product
00503 
00504         phi_values = range(n_max)
00505 
00506         prime = 2
00507         while prime <= n_max:
00508                 for i in xrange(0, n_max, prime):
00509                         phi_values[i] -= phi_values[i] / prime
00510 
00511                 prime = next_prime(prime)
00512 
00513         for i in xrange(n_max - 1, 0, -1):
00514                 if phi_values[i] <= phi_max:
00515                         return i
00516 
def inv_const(n):

def pyecm::help (  ) 

Definition at line 1325 of file pyecm.py.

01325           :
01326         print   '''\
01327 Usage: pyecm [OPTION] [expression to factor]
01328 Factor numbers using the Elliptic Curve Method.
01329 
01330    --portion=num     Does only part of the work for factoring, corresponding to
01331 what fraction of the total work the machine is doing. Useful for working in
01332 parallel. For example, if there are three machines: 1GHz, 1GHz, and 2GHz, print
01333 should be set to 0.25 for the 1GHz machines and 0.5 for the 2GHz machine.
01334 Implies -r and -v. -r is needed to avoid duplicating work and -v is needed to
01335 report results.
01336    --ov=num          Sets the value of the internal parameter ov, which
01337 determines the trade-off between memory and time usage. Do not touch if you do
01338 not know what you are doing. Please read all the documentation and understand
01339 the full implications of the parameter before using this switch.
01340    -n, --noverbose   Terse. On by default. Needed to cancel the -v from the
01341 --portion or --random switches. If both -n and -v are specified, the one
01342 specified last takes precedence.
01343    -r, --random      Chooses random values for sigma, an internal parameter in
01344 the calculation. Implies -v; if you're doing something random, you want to know
01345 what's happening.
01346    -v, --verbose     Explains what is being done with intermediate calculations
01347 and results.
01348 
01349 With no integers to factor given via command-line, read standard input.
01350 
01351 Please report bugs to Eric Larson <elarson3@uoregon.edu>.'''
01352         sys.exit()
01353 
def command_line(veb, ra, ov, pr):

def pyecm::interactive (   veb,
  ra,
  ov,
  pr 
)

Definition at line 1391 of file pyecm.py.

01391                                 :
01392         print   'pyecm v. %s (interactive mode):' % VERSION
01393         print   'Type "exit" at any time to quit.'
01394         print
01395 
01396         try:
01397                 response = raw_input()
01398                 while response != 'exit' and response != 'quit':
01399                         if valid_input(response):
01400                                 response = response.replace('^', '**')
01401                                 try:
01402                                         n = eval(response)
01403                                         int(n)
01404                                 except (SyntaxError, TypeError, ValueError):
01405                                         help()
01406                         else:
01407                                 help()
01408 
01409                         print   'Factoring number %d:' % n
01410                         if n < 0:
01411                                 print   -1
01412                                 n = -n
01413                         if n == 0:
01414                                 print   '0 does not have a well-defined factorization.'
01415                                 print
01416                                 response = raw_input()
01417                                 continue
01418                         elif n == 1:
01419                                 print   1
01420                                 print
01421                                 response = raw_input()
01422                                 continue
01423 
01424                         if ov == DUMMY:
01425                                 ov = 2*math.log(math.log(n))
01426                         for factor in factors(n, veb, ra, ov, pr):
01427                                 print   factor
01428                         print
01429                         response = raw_input()
01430         except (EOFError, KeyboardInterrupt):
01431                 sys.exit()
01432 
def main():

def pyecm::inv_const (   n  ) 

Finds a constant relating the complexity of multiplication to that of modular inversion.

Returns the constant for a given n.

Definition at line 517 of file pyecm.py.

00517                 :
00518         '''Finds a constant relating the complexity of multiplication to that of modular inversion.
00519 
00520 Returns the constant for a given n.'''
00521         return int(INV_C * math.log(n)**0.42)
00522 
def naf(d):

def pyecm::invert (   a,
  b 
)

Computes the inverse of a modulo b. b must be odd.

Returns the inverse of a (mod b).

Definition at line 76 of file pyecm.py.

00076                         :
00077                 '''Computes the inverse of a modulo b. b must be odd.
00078 
00079 Returns the inverse of a (mod b).'''
00080                 if a == 0 or b == 0:
00081                         return 0
00082 
00083                 truth = False
00084                 if a < 0:
00085                         truth = True
00086                         a = -a
00087 
00088                 b_orig = b
00089                 alpha = 1
00090                 beta = 0
00091 
00092                 while not a & 1:
00093                         if alpha & 1:
00094                                 alpha += b_orig
00095                         alpha >>= 1
00096                         a >>= 1
00097 
00098                 if b > a:
00099                         a, b = b, a
00100                         alpha, beta = beta, alpha
00101 
00102                 while b != 0 and a != b:
00103                         a -= b
00104                         alpha -= beta
00105 
00106                         while not a & 1:
00107                                 if alpha & 1:
00108                                         alpha += b_orig
00109                                 alpha >>= 1
00110                                 a >>= 1
00111                         
00112                         if b > a:
00113                                 a,b = b,a
00114                                 alpha, beta = beta, alpha
00115 
00116                 if a == b:
00117                         a -= b
00118                         alpha -= beta
00119                         a, b = b, a
00120                         alpha, beta = beta, alpha
00121 
00122                 if a != 1:
00123                         return 0
00124 
00125                 if truth:
00126                         alpha = b_orig - alpha
00127                 
00128                 return alpha
00129 
        def next_prime(n):

def pyecm::is_switch (   s  ) 

Tests whether the input string is a switch (e.g. "-v" or "--help").

Returns True or False.

Definition at line 1284 of file pyecm.py.

01284                 :
01285         '''Tests whether the input string is a switch (e.g. "-v" or "--help").
01286 
01287 Returns True or False.'''
01288 
01289         for i in xrange(len(s)):
01290                 if s[i] != '-':
01291                         break
01292 
01293         if i == 0: # s not begin with "-"
01294                 return False
01295         for char in s[i:]:
01296                 if not char.isalpha():
01297                         if char == '=': # Switches like "--portion=" are acceptable
01298                                 return True
01299                         else:
01300                                 return False
01301         return True
01302 
def parse_switch(s, switch):

def pyecm::isprime (   n  ) 

Tests for primality of n trying first fastprime and then a slower but accurate algorithm. Time complexity is O(N**3) (assuming quadratic multiplication), where n has N digits.

Returns the primality of n (True or False).

Definition at line 1072 of file pyecm.py.

01072               : 
01073         ''' Tests for primality of n trying first fastprime and then a slower but accurate algorithm. Time complexity is O(N**3) (assuming quadratic multiplication), where n has N digits.
01074 
01075 Returns the primality of n (True or False).'''
01076         if not fastprime(n):
01077                 return False
01078         elif n < SMALLEST_COUNTEREXAMPLE_FASTPRIME:
01079                 return True
01080 
01081         do_loop = False
01082         j = 1
01083         d = n >> 1
01084         a = 2
01085         bound = int(0.75 * math.log(math.log(n)) * math.log(n)) + 1
01086 
01087         while not d & 1:
01088                 d >>= 1
01089                 j += 1
01090 
01091         while a < bound:
01092                 a = next_prime(a)
01093                 p = atdn(a, d, n) 
01094 
01095                 if p == 1 or p == n - 1: 
01096                         continue 
01097 
01098                 for _ in xrange(j): 
01099                         p = (p * p) % n 
01100 
01101                         if p == 1: 
01102                                 return False 
01103                         elif p == n - 1: 
01104                                 do_loop = True
01105                                 break
01106 
01107                 if do_loop:
01108                         do_loop = False
01109                         continue
01110 
01111                 return False
01112 
01113         return True
01114 

def pyecm::main (  ) 

Definition at line 1433 of file pyecm.py.

01433           :
01434         ra = veb = False
01435         pr = 1.0
01436         ov = DUMMY
01437         for item in sys.argv[1:]:
01438                 if item == '--help':
01439                         help()
01440                 elif item == '--noverbose':
01441                         veb = False
01442                 elif item == '--random':
01443                         ra = veb = True
01444                 elif item == '--verbose':
01445                         veb = True
01446                 elif item == 'sgmftr':
01447                         test_sgmftr( )
01448                 elif item[:10] == '--portion=':
01449                         pr = parse_switch(item, 'portion')
01450                         ra = veb = True
01451                 elif item[:5] == '--ov=':
01452                         ov = parse_switch(item, 'ov')
01453                 elif len(item) >= 2 and item[0] == '-' and item[1] != '-': # Short switch
01454                         for char in item:
01455                                 if char == 'h':
01456                                         help()
01457                                 elif char == 'n':
01458                                         veb = False
01459                                 elif char == 'r':
01460                                         ra = veb = True
01461                                 elif char == 'v':
01462                                         veb = True
01463                 else:
01464                         if not valid_input(item):
01465                                 print   'I am confused about the following: "%s". Here\'s the help page:' % item
01466                                 print
01467                                 help()
01468 
01469         if len(sys.argv) > 1 and not is_switch(sys.argv[-1]):
01470                 command_line(veb, ra, ov, pr)
01471         else:
01472                 interactive(veb, ra, ov, pr)
01473 
if __name__ == '__main__':

def pyecm::mainloop (   n,
  u,
  p1 
)

Input:	n  -- an integer to (try) to factor.
                u  -- the phase 1 smoothness bound
                p1 -- a list of sigma parameters to try

Output:	A factor of n. (1 is returned on faliure).

Notes: 
        1. Other parameters, such as the phase 2 smoothness bound are selected by the mainloop function.
        2. This function uses batch algorithms, so if p1 is not long enough, there will be a loss in efficiency.
        3. Of course, if p1 is too long, then the mainloop will have to use more memory.
              [The memory is polynomial in the length of p1, log u, and log n].

Definition at line 834 of file pyecm.py.

00834                       :
00835         ''' Input:      n  -- an integer to (try) to factor.
00836                         u  -- the phase 1 smoothness bound
00837                         p1 -- a list of sigma parameters to try
00838 
00839         Output: A factor of n. (1 is returned on faliure).
00840 
00841         Notes: 
00842                 1. Other parameters, such as the phase 2 smoothness bound are selected by the mainloop function.
00843                 2. This function uses batch algorithms, so if p1 is not long enough, there will be a loss in efficiency.
00844                 3. Of course, if p1 is too long, then the mainloop will have to use more memory.
00845                       [The memory is polynomial in the length of p1, log u, and log n].'''
00846         k = inv_const(n)
00847         log_u = math.log(u)
00848         log_log_u = math.log(log_u)
00849         log_n = math.log(n)
00850         u2 = int(_7_OVER_LOG_2 * u * log_u / log_log_u)
00851         ncurves = len(p1)
00852         w = int(math.sqrt(_3_OVER_LOG_2 * ncurves / k) - 0.5)
00853         number_of_primes = int((ncurves << w) * math.sqrt(LOG_4_OVER_9 * log_n / k) / log_u) # Lagrange multipliers!
00854         number_of_primes = min(number_of_primes, int((log_n / math.log(log_n))**2 * ncurves / log_u), int(u / log_u))
00855         number_of_primes = max(number_of_primes, 1)
00856         m = math.log(number_of_primes) + log_log_u
00857         w = min(w, int((m - 2 * math.log(m) + LOG_3_MINUS_LOG_LOG_2) / LOG_2))
00858         w = max(w, 1)
00859         max_order = n + sqrt(n << 2) + 1 # By Hasse's theorem.
00860         det_bound = ((1 << w) - 1 + ((w & 1) << 1)) / 3
00861         log_mo = math.log(max_order)
00862         p = range(number_of_primes)
00863         prime = mpz(2)
00864 
00865         p1 = get_points(p1, n)
00866         if not isinstance(p1, list):
00867                 return p1
00868 
00869         for _ in xrange(int(log_mo / LOG_2)):
00870                 p1 = double(p1, n)
00871                 if not isinstance(p1, list):
00872                         return p1
00873         
00874         for i in xrange(1, det_bound):
00875                 prime  = (i << 1) + 1
00876                 if isprime(prime):
00877                         for _ in xrange(int(log_mo / math.log(prime))):
00878                                 p1 = multiply(p1, prime, n)
00879                                 if not isinstance(p1, list):
00880                                         return p1
00881 
00882         while prime < sqrt(u) and isinstance(p1, list):
00883                 for i in xrange(number_of_primes):
00884                         prime = next_prime(prime)
00885                         p[i] = prime ** max(1, int(log_u / math.log(prime)))
00886                 p1 = fast_multiply(p1, prod(p),  n, w)
00887 
00888         if not isinstance(p1, list):
00889                 return p1
00890 
00891         while prime < u and isinstance(p1, list):
00892                 for i in xrange(number_of_primes):
00893                         prime = next_prime(prime)
00894                         p[i] = prime
00895                 p1 = fast_multiply(p1, prod(p),  n, w)
00896 
00897         if not isinstance(p1, list):
00898                 return p1
00899 
00900         del p
00901 
00902         small_jump = int(greatest_n((1 << (w + 2)) / 3))
00903         small_jump = max(120, small_jump)
00904         big_jump = 1 + (int(sqrt((5 << w) / 21)) << 1)
00905         total_jump = small_jump * big_jump
00906         big_multiple = max(total_jump << 1, ((int(next_prime(prime)) - (total_jump >> 1)) / total_jump) * total_jump)
00907         big_jump_2 = big_jump >> 1
00908         small_jump_2 = small_jump >> 1
00909         product = ONE
00910 
00911         psmall_jump = multiply(p1, small_jump, n)
00912         if not isinstance(psmall_jump, list):
00913                 return psmall_jump
00914 
00915         ptotal_jump = multiply(psmall_jump, big_jump, n)
00916         if not isinstance(ptotal_jump, list):
00917                 return ptotal_jump
00918 
00919         pgiant_step = multiply(p1, big_multiple, n)
00920         if not isinstance(pgiant_step, list):
00921                 return pgiant_step
00922 
00923         small_multiples = [None]
00924         for i in xrange(1, small_jump >> 1):
00925                 if gcd(i, small_jump) == 1:
00926                         tmp = multiply(p1, i, n)
00927                         if not isinstance(tmp, list):
00928                                 return tmp
00929                         for i in xrange(len(tmp)):
00930                                 tmp[i] = tmp[i][0]
00931                         small_multiples.append(tuple(tmp))
00932                 else:
00933                         small_multiples.append(None)
00934         small_multiples = tuple(small_multiples)
00935 
00936         big_multiples = [None]
00937         for i in xrange(1, (big_jump + 1) >> 1):
00938                 tmp = multiply(psmall_jump, i, n)
00939                 if not isinstance(tmp, list):
00940                         return tmp
00941                 big_multiples.append(to_tuple(tmp))
00942         big_multiples = tuple(big_multiples)
00943 
00944         psmall_jump = to_tuple(psmall_jump)
00945         ptotal_jump = to_tuple(ptotal_jump)
00946         
00947         while big_multiple < u2:
00948                 big_multiple += total_jump
00949                 center_up = big_multiple
00950                 center_down = big_multiple
00951                 pgiant_step = add(ptotal_jump, pgiant_step, n)
00952                 if not isinstance(pgiant_step, list):
00953                         return pgiant_step
00954 
00955                 prime_up = next_prime(big_multiple - small_jump_2)
00956                 while prime_up < big_multiple + small_jump_2:
00957                         s = small_multiples[abs(int(prime_up) - big_multiple)]
00958                         for j in xrange(ncurves):
00959                                 product *= pgiant_step[j][0] - s[j]
00960                                 product %= n
00961                         prime_up = next_prime(prime_up)
00962                 
00963                 for i in xrange(1, big_jump_2 + 1):
00964                         center_up += small_jump
00965                         center_down -= small_jump
00966                         
00967                         pmed_step_up, pmed_step_down = add_sub_x_only(big_multiples[i], pgiant_step, n)
00968                         if pmed_step_down == None:
00969                                 return pmed_step_up
00970 
00971                         while prime_up < center_up + small_jump_2:
00972                                 s = small_multiples[abs(int(prime_up) - center_up)]
00973                                 for j in xrange(ncurves):
00974                                         product *= pmed_step_up[j] - s[j]
00975                                         product %= n
00976                                 prime_up = next_prime(prime_up)
00977 
00978                         prime_down = next_prime(center_down - small_jump_2)
00979                         while prime_down < center_down + small_jump_2:
00980                                 s = small_multiples[abs(int(prime_down) - center_down)]
00981                                 for j in xrange(ncurves):
00982                                         product *= pmed_step_down[j] - s[j]
00983                                         product %= n
00984                                 prime_down = next_prime(prime_down)
00985 
00986         if gcd(product, n) != 1:
00987                 return gcd(product, n)
00988 
00989         return 1
00990 
def fast_multiply(p, d, n, w):

def pyecm::mpz (   n  ) 

A dummy function to ensure compatibility with those that do not have gmpy.

Returns n.

Definition at line 181 of file pyecm.py.

00181                   :
00182                 '''A dummy function to ensure compatibility with those that do not have gmpy.
00183 
00184 Returns n.'''
00185                 return n
00186 
        def root(n, k):

def pyecm::multiply (   p1,
  d,
  n 
)

Multiplies each element of a list by a number, without using too much overhead.

Returns a list p multiplied through by d.

Definition at line 1115 of file pyecm.py.

01115                       :
01116         '''Multiplies each element of a list by a number, without using too much overhead.
01117 
01118 Returns a list p multiplied through by d.'''
01119         pos = int(math.log(d) / LOG_2) - 1
01120         p = copy(p1)
01121 
01122         while pos >= 0:
01123                 p = double(p, n)
01124                 if not isinstance(p, list):
01125                         return p
01126                 if (d >> pos) & 1:
01127                         p = add(p1, p,  n)
01128                         if not isinstance(p, list):
01129                                 return p
01130                 pos -= 1
01131 
01132         return p
01133 
def ecm(n, ra, ov, veb, tdb, pr): # DOCUMENTATION

def pyecm::naf (   d  ) 

Finds a number's non-adjacent form, reverses the bits, replaces the
-1's with 3's, and interprets the result base 4.

Returns the result interpreted as if in base 4.

Definition at line 523 of file pyecm.py.

00523           :
00524         '''Finds a number's non-adjacent form, reverses the bits, replaces the
00525 -1's with 3's, and interprets the result base 4.
00526 
00527 Returns the result interpreted as if in base 4.'''
00528         g = 0L
00529         while d:
00530                 g <<= 2
00531                 g ^= ((d & 2) & (d << 1)) ^ (d & 1)
00532                 d += (d & 2) >> 1
00533                 d >>= 1
00534         return g
00535 
def parallel_invert(l, n):

def pyecm::next_prime (   n  ) 

Finds the next prime after n.

Returns the next prime after n.

Definition at line 130 of file pyecm.py.

00130                          :
00131                 '''Finds the next prime after n.
00132 
00133 Returns the next prime after n.'''
00134                 n += 1
00135                 if n <= 167:
00136                         if n <= 23:
00137                                 if n <= 3:
00138                                         return 3 - (n <= 2)
00139                                 n += (n & 1) ^ 1
00140                                 return n + (((4 - (n % 3)) >> 1) & 2)
00141 
00142                         n += (n & 1) ^ 1
00143                         inc = n % 3
00144                         n += ((4 - inc) >> 1) & 2
00145                         inc = 6 - ((inc + ((2 - inc) & 2)) << 1)
00146 
00147                         while 0 in (n % 5, n % 7, n % 11):
00148                                 n += inc
00149                                 inc = 6 - inc
00150                         return n
00151 
00152                 n += (n & 1) ^ 1
00153                 inc = n % 3
00154                 n += ((4 - inc) >> 1) & 2
00155                 inc = 6 - ((inc + ((2 - inc) & 2)) << 1)
00156                 should_break = False
00157 
00158                 while 1:
00159                         for prime in PRIMES:
00160                                 if not n % prime:
00161                                         should_break = True
00162                                         break
00163 
00164                         if should_break:
00165                                 should_break = False
00166                                 n += inc
00167                                 inc = 6 - inc
00168                                 continue
00169 
00170                         p = 1
00171                         for i in xrange(int(math.log(n) / LOG_2), 0, -1):
00172                                 p <<= (n >> i) & 1
00173                                 p = (p * p) % n
00174 
00175                         if p == 1:
00176                                 return n
00177                 
00178                         n += inc
00179                         inc = 6 - inc
00180 
        def mpz(n):

def pyecm::parallel_invert (   l,
  n 
)

Inverts all elements of a list modulo some number, using 3(n-1) modular multiplications and one inversion.

Returns the list with all elements inverted modulo 3(n-1).

Definition at line 536 of file pyecm.py.

00536                          :
00537         '''Inverts all elements of a list modulo some number, using 3(n-1) modular multiplications and one inversion.
00538 
00539 Returns the list with all elements inverted modulo 3(n-1).'''
00540         l_ = l[:]
00541         for i in xrange(len(l)-1):
00542                 l[i+1] = (l[i] * l[i+1]) % n
00543         
00544         inv = invert(l[-1], n)
00545         if inv == 0:
00546                 return gcd(l[-1], n)
00547 
00548         for i in xrange(len(l)-1, 0, -1):
00549                 l[i] = (inv * l[i-1]) % n
00550                 inv = (inv * l_[i]) % n
00551         l[0] = inv
00552 
00553         return l
00554 
def prod(p):

def pyecm::parse_switch (   s,
  switch 
)

Parses a switch in the form '--string=num' and returns num or calls help() if the string is invalid.

Returns the num in '--string=num'.

Definition at line 1303 of file pyecm.py.

01303                            :
01304         '''Parses a switch in the form '--string=num' and returns num or calls help() if the string is invalid.
01305 
01306 Returns the num in '--string=num'.'''
01307 
01308         try:
01309                 return float(s[len(switch) + 3:])
01310         except ValueError:
01311                 help()
01312 
def valid_input(s):

def pyecm::prod (   p  ) 

Multiplies all elements of a list together. The order in which the
elements are multiplied is chosen to take advantage of Python's Karatsuba
Multiplication

Returns the product of everything in p.

Definition at line 555 of file pyecm.py.

00555            :
00556         '''Multiplies all elements of a list together. The order in which the
00557 elements are multiplied is chosen to take advantage of Python's Karatsuba
00558 Multiplication
00559 
00560 Returns the product of everything in p.'''
00561         jump = 1
00562 
00563         while jump < len(p):
00564                 for i in xrange(0, len(p) - jump, jump << 1):
00565                         p[i] *= p[i + jump]
00566                         p[i + jump] = None
00567 
00568                 jump <<= 1
00569 
00570         return p[0]
00571 
def rho_ev(x, ts):

def pyecm::rho_ev (   x,
  ts 
)

Evaluates Dickman's rho function, which calculates the asymptotic
probability as N approaches infinity (for a given x) that all of N's factors
are bounded by N^(1/x).

Definition at line 572 of file pyecm.py.

00572                  :
00573         '''Evaluates Dickman's rho function, which calculates the asymptotic
00574 probability as N approaches infinity (for a given x) that all of N's factors
00575 are bounded by N^(1/x).'''
00576         return ts[int(x)].ev(x - int(x) - 0.5)
00577 
def rho_ts(n):

def pyecm::rho_ts (   n  ) 

Makes a list of Taylor series for the rho function centered at 0.5, 1.5, 2.5 ... n + 0.5. The reason this is necessary is that the radius of convergence of rho is small, so we need lots of Taylor series centered at different places to correctly evaluate it.

Returns a list of Taylor series.

Definition at line 578 of file pyecm.py.

00578              :
00579         '''Makes a list of Taylor series for the rho function centered at 0.5, 1.5, 2.5 ... n + 0.5. The reason this is necessary is that the radius of convergence of rho is small, so we need lots of Taylor series centered at different places to correctly evaluate it.
00580 
00581 Returns a list of Taylor series.'''
00582         f = ts(10, 10, [])
00583         answer = [ts(10, 10, [1])]
00584         for _ in xrange(n):
00585                 answer.append(ts(10, 10, [1]))
00586         deg = 5
00587         acc = 50 + n * int(1 + math.log(1 + n) + math.log(math.log(3 + n)))
00588         r = 1
00589         rho_series = ts(1, 10, [0])
00590         while r != rho_series.coefficients[0]:
00591                 deg = (deg + (deg << 2)) / 3
00592                 r = rho_series.coefficients[0]
00593                 rho_series = ts(deg, acc, [(1L) << acc])
00594                 center = 0.5
00595                 for i in xrange(1, n+1):
00596                         f.set(rho_series)
00597                         center += 1
00598                         f.lindiv(int(2*center))
00599                         f.int()
00600                         f.neg()
00601                         d = ts(deg, acc, [rho_series.evh() - f.evmh()])
00602                         f.add(f, d)
00603                         rho_series.set(f)
00604                         f.simp()
00605                         answer[i].set(f)
00606                 rho_series.simp()
00607 
00608         return answer
00609 
def sub_sub_sure_factors(f, u, curve_parameter):

def pyecm::root (   n,
  k 
)

Finds the floor of the kth root of n. This is a duplicate of gmpy's root function.

Returns a tuple. The first item is the floor of the kth root of n. The second is 1 if the root is exact (as in, sqrt(16)) and 0 if it is not.

Definition at line 187 of file pyecm.py.

00187                       :
00188                 '''Finds the floor of the kth root of n. This is a duplicate of gmpy's root function.
00189 
00190 Returns a tuple. The first item is the floor of the kth root of n. The second is 1 if the root is exact (as in, sqrt(16)) and 0 if it is not.'''
00191                 low = 0
00192                 high = n + 1
00193                 while high > low + 1:
00194                         mid = (low + high) >> 1
00195                         mr = mid**k
00196                         if mr == n:
00197                                 return (mid, 1)
00198                         if mr < n:
00199                                 low = mid
00200                         if mr > n:
00201                                 high = mid
00202                 return (low, 0)
00203 
        def sqrt(n):

def pyecm::sqrt (   n  ) 

Definition at line 204 of file pyecm.py.

00204                    :
00205                 return root(n, 2)[0]
00206 
00207 # We're done importing. Now for some constants.
if GMPY_EXISTS:

def pyecm::sub_sub_sure_factors (   f,
  u,
  curve_parameter 
)

Finds all factors that can be found using ECM with a smoothness bound of u and sigma and give curve parameters. If that fails, checks for being a prime power and does Fermat factoring as well.

Yields factors.

Definition at line 610 of file pyecm.py.

00610                                                :
00611         '''Finds all factors that can be found using ECM with a smoothness bound of u and sigma and give curve parameters. If that fails, checks for being a prime power and does Fermat factoring as well.
00612         
00613 Yields factors.'''
00614         while not (f & 1):
00615                 yield 2
00616                 f >>= 1
00617         
00618         while not (f % 3):
00619                 yield 3
00620                 f /= 3
00621 
00622         if isprime(f):
00623                 yield f
00624                 return
00625 
00626         log_u = math.log(u)
00627         u2 = int(_7_OVER_LOG_2 * u * log_u / math.log(log_u))
00628         primes = []
00629         still_a_chance = True
00630         log_mo = math.log(f + 1 + sqrt(f << 2))
00631 
00632         g = gcd(curve_parameter, f)
00633         if g not in (1, f):
00634                 for factor in sub_sub_sure_factors(g, u, curve_parameter):
00635                         yield factor
00636                 for factor in sub_sub_sure_factors(f/g, u, curve_parameter):
00637                         yield factor
00638                 return
00639 
00640         g2 = gcd(curve_parameter**2 - 5, f)
00641         if g2 not in (1, f):
00642                 for factor in sub_sub_sure_factors(g2, u, curve_parameter):
00643                         yield factor
00644                 for factor in sub_sub_sure_factors(f / g2, u, curve_parameter):
00645                         yield factor
00646                 return
00647 
00648         if f in (g, g2):
00649                 yield f
00650 
00651         while still_a_chance:
00652                 p1 = get_points([curve_parameter], f)
00653                 for prime in primes:
00654                         p1 = multiply(p1, prime, f)
00655                         if not isinstance(p1, list):
00656                                 if p1 != f:
00657                                         for factor in sub_sub_sure_factors(p1, u, curve_parameter):
00658                                                 yield factor
00659                                         for factor in sub_sub_sure_factors(f/p1, u, curve_parameter):
00660                                                 yield factor
00661                                         return
00662                                 else:
00663                                         still_a_chance = False
00664                                         break
00665 
00666                 if not still_a_chance:
00667                         break
00668 
00669                 prime = 1
00670                 still_a_chance = False
00671                 while prime < u2:
00672                         prime = next_prime(prime)
00673                         should_break = False
00674                         for _ in xrange(int(log_mo / math.log(prime))):
00675                                 p1 = multiply(p1, prime, f)
00676                                 if not isinstance(p1, list):
00677                                         if p1 != f:
00678                                                 for factor in sub_sub_sure_factors(p1, u, curve_parameter):
00679                                                         yield factor
00680                                                 for factor in sub_sub_sure_factors(f/p1, u, curve_parameter):
00681                                                         yield factor
00682                                                 return
00683 
00684                                         else:
00685                                                 still_a_chance = True
00686                                                 primes.append(prime)
00687                                                 should_break = True
00688                                                 break
00689                         if should_break:
00690                                 break
00691 
00692         for i in xrange(2, int(math.log(f) / LOG_2) + 2):
00693                 r = root(f, i)
00694                 if r[1]:
00695                         for factor in sub_sub_sure_factors(r[0], u, curve_parameter):
00696                                 for _ in xrange(i):
00697                                         yield factor
00698                         return
00699         
00700         a = 1 + sqrt(f)
00701         bsq = a * a - f
00702         iter = 0
00703 
00704         while bsq != sqrt(bsq)**2 and iter < 3:
00705                 a += 1
00706                 iter += 1
00707                 bsq += a + a - 1
00708 
00709         if bsq == sqrt(bsq)**2:
00710                 b = sqrt(bsq)
00711                 for factor in sub_sub_sure_factors(a - b, u, curve_parameter):
00712                         yield factor
00713                 for factor in sub_sub_sure_factors(a + b, u, curve_parameter):
00714                         yield factor
00715                 return
00716 
00717         yield f
00718         return
00719 
def sub_sure_factors(f, u, curve_params):

def pyecm::sub_sure_factors (   f,
  u,
  curve_params 
)

Factors n as far as possible using the fact that f came from a mainloop call.

Yields factors of n.

Definition at line 720 of file pyecm.py.

00720                                         :
00721         '''Factors n as far as possible using the fact that f came from a mainloop call.
00722         
00723 Yields factors of n.'''
00724         if len(curve_params) == 1:
00725                 for factor in sub_sub_sure_factors(f, u, curve_params[0]):
00726                         yield factor
00727                 return
00728 
00729         c1 = curve_params[:len(curve_params) >> 1]
00730         c2 = curve_params[len(curve_params) >> 1:]
00731 
00732         if mainloop(f, u, c1) == 1:
00733                 for factor in sub_sure_factors(f, u, c2):
00734                         yield factor
00735                 return
00736 
00737         if mainloop(f, u, c2) == 1:
00738                 for factor in sub_sure_factors(f, u, c1):
00739                         yield factor
00740                 return
00741 
00742         for factor in sub_sure_factors(f, u, c1):
00743                 if isprime(factor):
00744                         yield factor
00745                 else:
00746                         for factor_of_factor in sub_sure_factors(factor, u, c2):
00747                                 yield factor_of_factor
00748 
00749         return
00750 
def subtract(p1, p2,  n):

def pyecm::subtract (   p1,
  p2,
  n 
)

Given two points on an elliptic curve, subtract them pointwise.

Returns the resulting point.

Definition at line 751 of file pyecm.py.

00751                         :
00752         '''Given two points on an elliptic curve, subtract them pointwise.
00753         
00754 Returns the resulting point.'''
00755         inv = range(len(p1))
00756 
00757         for i in xrange(len(p1)):
00758                 inv[i] = p2[i][0] - p1[i][0]
00759 
00760         inv = parallel_invert(inv, n)
00761 
00762         if not isinstance(inv, list):
00763                 return inv
00764         
00765         for i in xrange(len(p1)):
00766                 m = ((p1[i][1] + p2[i][1]) * inv[i]) % n
00767                 p2[i][0] = (m * m - p1[i][0] - p2[i][0]) % n
00768                 p2[i][1] = (m * (p1[i][0] - p2[i][0]) + p1[i][1]) % n
00769 
00770         return p2
00771 
def congrats(f, veb):

def pyecm::sure_factors (   n,
  u,
  curve_params,
  veb,
  ra,
  ov,
  tdb,
  pr 
)

Factor n as far as possible with given smoothness bound and curve parameters, including possibly (but very rarely) calling ecm again.

Yields factors of n.

Definition at line 783 of file pyecm.py.

00783                                                           :
00784         '''Factor n as far as possible with given smoothness bound and curve parameters, including possibly (but very rarely) calling ecm again.
00785 
00786 Yields factors of n.'''
00787         f = mainloop(n, u, curve_params)
00788 
00789         if f == 1:
00790                 return 
00791 
00792         if veb:
00793                 print 'Found factor:', f
00794                 print 'Mainloop call was:', n, u, curve_params
00795 
00796         if isprime(f):
00797                 congrats(f, veb)
00798                 yield f
00799                 n /= f
00800                 if isprime(n):
00801                         yield n
00802                 if veb:
00803                         print '(factor processed)'
00804                 return
00805 
00806         for factor in sub_sure_factors(f, u, curve_params):
00807                 if isprime(factor):
00808                         congrats(f, veb)
00809                         yield factor
00810                 else:
00811                         if veb:
00812                                 print 'entering new ecm loop to deal with stubborn factor:', factor
00813                         for factor_of_factor in ecm(factor, True, ov, veb, tdb, pr):
00814                                 yield factor_of_factor
00815                 n /= factor
00816         
00817         if isprime(n):
00818                 yield n
00819 
00820         if veb:
00821                 print '(factor processed)'
00822         return
00823 
def to_tuple(p):

def pyecm::to_tuple (   p  ) 

Converts a list of two-element lists into a list of two-element tuples.

Returns a list.

Definition at line 824 of file pyecm.py.

00824                :
00825         '''Converts a list of two-element lists into a list of two-element tuples.
00826 
00827 Returns a list.'''
00828         answer = []
00829         for i in p:
00830                 answer.append((i[0], i[1]))
00831 
00832         return tuple(answer)
00833 
def mainloop(n, u, p1):

def pyecm::valid_input (   s  ) 

Tests the input string for validity as a mathematical expressions.

Returns True or False.

Definition at line 1313 of file pyecm.py.

01313                   :
01314         '''Tests the input string for validity as a mathematical expressions.
01315 
01316 Returns True or False.'''
01317         valid = ('(', ')', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '-', '*', '/', '^', ' ', '\t')
01318 
01319         for char in s:
01320                 if char not in valid:
01321                         return False
01322 
01323         return True
01324 
def help():


Variable Documentation

Definition at line 231 of file pyecm.py.

Definition at line 219 of file pyecm.py.

Definition at line 220 of file pyecm.py.

Definition at line 221 of file pyecm.py.

float pyecm::BIG = 2.0

Definition at line 222 of file pyecm.py.

int pyecm::BILLION = 10

Definition at line 223 of file pyecm.py.

string pyecm::DUMMY = 'dummy'

Definition at line 229 of file pyecm.py.

Definition at line 30 of file pyecm.py.

float pyecm::INV_C = 1.4

Definition at line 209 of file pyecm.py.

tuple pyecm::LOG_2 = math.log(2)

Definition at line 215 of file pyecm.py.

tuple pyecm::LOG_3_MINUS_LOG_LOG_2 = math.log(3)

Definition at line 217 of file pyecm.py.

tuple pyecm::LOG_4 = math.log(4)

Definition at line 216 of file pyecm.py.

Definition at line 218 of file pyecm.py.

tuple pyecm::MULT = math.log(3)

Definition at line 224 of file pyecm.py.

tuple pyecm::ONE = mpz(1)

Definition at line 225 of file pyecm.py.

tuple pyecm::PRIMES = (5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 167)

Definition at line 33 of file pyecm.py.

Definition at line 24 of file pyecm.py.

int pyecm::RECORD = 1162795072109807846655696105569042240239

Definition at line 232 of file pyecm.py.

float pyecm::SMALL = 2.0

Definition at line 226 of file pyecm.py.

Definition at line 227 of file pyecm.py.

tuple pyecm::T = (type(mpz(1)), type(1), type(1L))

Definition at line 228 of file pyecm.py.

string pyecm::VERSION = '2.0'

Definition at line 230 of file pyecm.py.


Generated on Sun Mar 22 09:59:14 2009 for Multiperfect Number Generator by  doxygen 1.5.8