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 |
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 | ) |
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 | ) |
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():
int pyecm::_12_LOG_2_OVER_49 = 12 |
int pyecm::_3_OVER_LOG_2 = 3 |
int pyecm::_5_LOG_10 = 5 |
int pyecm::_7_OVER_LOG_2 = 7 |
float pyecm::BIG = 2.0 |
int pyecm::BILLION = 10 |
string pyecm::DUMMY = 'dummy' |
pyecm::GMPY_EXISTS = True |
float pyecm::INV_C = 1.4 |
tuple pyecm::LOG_2 = math.log(2) |
tuple pyecm::LOG_3_MINUS_LOG_LOG_2 = math.log(3) |
tuple pyecm::LOG_4 = math.log(4) |
int pyecm::LOG_4_OVER_9 = 9 |
tuple pyecm::MULT = math.log(3) |
tuple pyecm::ONE = mpz(1) |
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) |
pyecm::PSYCO_EXISTS = True |
int pyecm::RECORD = 1162795072109807846655696105569042240239 |
float pyecm::SMALL = 2.0 |
int pyecm::SMALLEST_COUNTEREXAMPLE_FASTPRIME = 2047 |
string pyecm::VERSION = '2.0' |