-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathelliptic-curve_factorization_method.sf
80 lines (57 loc) · 1.88 KB
/
elliptic-curve_factorization_method.sf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#!/usr/bin/ruby
# The elliptic-curve factorization method (ECM), due to Hendrik Lenstra.
# Algorithm presented in the YouTube video:
# https://www.youtube.com/watch?v=2JlpeQWtGH8
# See also:
# https://en.wikipedia.org/wiki/Lenstra_elliptic-curve_factorization
func ecm(N, arange=100, plimit=10000) {
return N if N.is_prime
return N.prime_root if N.is_prime_power
var primes = plimit.primes
for a in range(-arange, arange) {
var x = 0
var y = 1
primes.each {|B|
var t = B**plimit.ilog(B)
var (xn, yn)
var (sx, sy) = (x, y)
var first = true
while (t > 0) {
if (t.is_odd) {
if (first) {
(xn, yn) = (sx, sy)
first = false
}
else {
var u = invmod(sx-xn, N)
if (!u) {
var d = gcd(sx-xn, N)
break if (d == N)
return d
}
var L = (u*(sy-yn) % N)
var xs = ((L*L - xn - sx) % N)
yn = ((L*(xn - xs) - yn) % N)
xn = xs
}
}
var u = invmod(2*sy, N)
if (!u) {
var d = gcd(2*sy, N)
break if (d == N)
return d
}
var L = (u*(3*sx*sx + a) % N)
var x2 = ((L*L - 2*sx) % N)
sy = ((L*(sx - x2) - sy) % N)
sx = x2
sy || return N
t >>= 1
}
(x, y) = (xn, yn)
}
}
return N
}
say ecm(14304849576137459)
#say ecm(2**128 + 1) # takes ~11 seconds