Skip to content

Commit 0bfd8ff

Browse files
delivranceLonami
authored andcommitted
Add much faster integer factorization (#403 related to #199)
1 parent 9a12738 commit 0bfd8ff

File tree

1 file changed

+35
-61
lines changed

1 file changed

+35
-61
lines changed

telethon/crypto/factorization.py

Lines changed: 35 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,71 +1,45 @@
11
from random import randint
2-
try:
3-
import sympy.ntheory
4-
except ImportError:
5-
sympy = None
62

73

84
class Factorization:
9-
@staticmethod
10-
def find_small_multiplier_lopatin(what):
11-
"""Finds the small multiplier by using Lopatin's method"""
12-
g = 0
13-
for i in range(3):
14-
q = (randint(0, 127) & 15) + 17
15-
x = randint(0, 1000000000) + 1
16-
y = x
17-
lim = 1 << (i + 18)
18-
for j in range(1, lim):
19-
a, b, c = x, x, q
20-
while b != 0:
21-
if (b & 1) != 0:
22-
c += a
23-
if c >= what:
24-
c -= what
25-
a += a
26-
if a >= what:
27-
a -= what
28-
b >>= 1
29-
30-
x = c
31-
z = y - x if x < y else x - y
32-
g = Factorization.gcd(z, what)
33-
if g != 1:
5+
@classmethod
6+
def factorize(cls, pq):
7+
if pq % 2 == 0:
8+
return 2, pq // 2
9+
10+
y, c, m = randint(1, pq - 1), randint(1, pq - 1), randint(1, pq - 1)
11+
g = r = q = 1
12+
x = ys = 0
13+
14+
while g == 1:
15+
x = y
16+
for i in range(r):
17+
y = (pow(y, 2, pq) + c) % pq
18+
19+
k = 0
20+
while k < r and g == 1:
21+
ys = y
22+
for i in range(min(m, r - k)):
23+
y = (pow(y, 2, pq) + c) % pq
24+
q = q * (abs(x - y)) % pq
25+
26+
g = cls.gcd(q, pq)
27+
k += m
28+
29+
r *= 2
30+
31+
if g == pq:
32+
while True:
33+
ys = (pow(ys, 2, pq) + c) % pq
34+
g = cls.gcd(abs(x - ys), pq)
35+
if g > 1:
3436
break
3537

36-
if (j & (j - 1)) == 0:
37-
y = x
38-
39-
if g > 1:
40-
break
41-
42-
p = what // g
43-
return min(p, g)
38+
return g, pq // g
4439

4540
@staticmethod
4641
def gcd(a, b):
47-
"""Calculates the greatest common divisor"""
48-
while a != 0 and b != 0:
49-
while b & 1 == 0:
50-
b >>= 1
42+
while b:
43+
a, b = b, a % b
5144

52-
while a & 1 == 0:
53-
a >>= 1
54-
55-
if a > b:
56-
a -= b
57-
else:
58-
b -= a
59-
60-
return a if b == 0 else b
61-
62-
@staticmethod
63-
def factorize(pq):
64-
"""Factorizes the given number and returns both
65-
the divisor and the number divided by the divisor
66-
"""
67-
if sympy:
68-
return tuple(sympy.ntheory.factorint(pq).keys())
69-
else:
70-
divisor = Factorization.find_small_multiplier_lopatin(pq)
71-
return divisor, pq // divisor
45+
return a

0 commit comments

Comments
 (0)