@@ -233,10 +233,9 @@ isprime(n::Int128) = n < 2 ? false :
233233
234234
235235# Trial division of small (< 2^16) precomputed primes +
236- # Pollard rho's algorithm with Richard P. Brent optimizations
236+ # Lenstra elliptic curve algorithm
237237# https://en.wikipedia.org/wiki/Trial_division
238- # https://en.wikipedia.org/wiki/Pollard%27s_rho_algorithm
239- # http://maths-people.anu.edu.au/~brent/pub/pub051.html
238+ # https://en.wikipedia.org/wiki/Lenstra_elliptic-curve_factorization
240239#
241240function factor! (n:: T , h:: AbstractDict{K,Int} ) where {T<: Integer ,K<: Integer }
242241 # check for special cases
@@ -271,7 +270,7 @@ function factor!(n::T, h::AbstractDict{K,Int}) where {T<:Integer,K<:Integer}
271270 end
272271 end
273272 isprime (n) && (h[n]= 1 ; return h)
274- T <: BigInt || widemul (n - 1 , n - 1 ) ≤ typemax (n) ? pollardfactors ! (n, h) : pollardfactors ! (widen (n), h)
273+ T <: BigInt || widemul (n - 1 , n - 1 ) ≤ typemax (n) ? lenstrafactors ! (n, h) : lenstrafactors ! (widen (n), h)
275274end
276275
277276
@@ -389,52 +388,80 @@ julia> radical(2*2*3)
389388"""
390389radical (n) = prod (factor (Set, n))
391390
392- function pollardfactors! (n:: T , h:: AbstractDict{K,Int} ) where {T<: Integer ,K<: Integer }
393- while true
394- c:: T = rand (1 : (n - 1 ))
395- G:: T = 1
396- r:: K = 1
397- y:: T = rand (0 : (n - 1 ))
398- m:: K = 1900
399- ys:: T = 0
400- q:: T = 1
401- x:: T = 0
402- while c == n - 2
403- c = rand (1 : (n - 1 ))
391+ function inthroot (n:: Integer , r:: Int )
392+ ans = BigInt ()
393+ ccall ((:__gmpz_root , :libgmp ), Cvoid, (Ref{BigInt}, Ref{BigInt}, Culong), ans, BigInt (n), r)
394+ return ans
395+ end
396+
397+ function lenstrafactors! (n:: T , h:: AbstractDict{K,Int} , plimit= 10000 ) where {T<: Integer ,K<: Integer }
398+ isprime (n) && (h[n] = get (h, n, 0 )+ 1 ; return h)
399+ r = ceil (Int, inv (log (n, Primes. PRIMES[end ])))+ 1
400+ root = inthroot (n, r)
401+ while r >= 2
402+ if root^ r == n
403+ isprime (root) ? h[root] = get (h, root, 0 ) + 1 : lenstrafactors! (root, h)
404+ return lenstrafactors! (div (n, root), h)
404405 end
405- while G == 1
406- x = y
407- for i in 1 : r
408- y = y^ 2 % n
409- y = (y + c) % n
406+ r -= 1
407+ root = inthroot (n, r)
408+ end
409+ small_primes = primes (plimit)
410+ for a in zero (T): (n>> 1 )
411+ for p in (- 1 , 1 )
412+ res = lenstra_get_factor (n, p* a, small_primes, plimit)
413+ if res != 1
414+ isprime (res) ? h[res] = get (h, res, 0 ) + 1 : lenstrafactors! (res, h)
415+ res2 = div (n,res)
416+ isprime (res2) ? h[res2] = get (h, res2, 0 ) + 1 : lenstrafactors! (res2, h)
417+ return h
410418 end
411- k:: K = 0
412- G = 1
413- while k < r && G == 1
414- for i in 1 : (m > (r - k) ? (r - k) : m)
415- ys = y
416- y = y^ 2 % n
417- y = (y + c) % n
418- q = (q * (x > y ? x - y : y - x)) % n
419+ end
420+ end
421+ end
422+
423+ function lenstra_get_factor (N:: T , a, small_primes, plimit) where T <: Integer
424+ x = T (0 )
425+ y = T (1 )
426+
427+ for B in small_primes
428+ t = B^ trunc (Int64, log (B, plimit))
429+ xn, yn = T (0 ), T (0 )
430+ sx, sy = x, y
431+
432+ first = true
433+ while t > 0
434+ if isodd (t)
435+ if first
436+ xn, yn = sx, sy
437+ first = false
438+ else
439+ g, u, _ = gcdx (sx- xn, N)
440+ g > 1 && (g == N ? break : return g)
441+ u += N
442+ L = (u* (sy- yn)) % N
443+ xs = (L* L - xn - sx) % N
444+
445+ yn = (L* (xn - xs) - yn) % N
446+ xn = xs
419447 end
420- G = gcd (q, n)
421- k += m
422448 end
423- r *= 2
424- end
425- G == n && (G = 1 )
426- while G == 1
427- ys = ys^ 2 % n
428- ys = (ys + c) % n
429- G = gcd (x > ys ? x - ys : ys - x, n)
430- end
431- if G != n
432- isprime (G) ? h[G] = get (h, G, 0 ) + 1 : pollardfactors! (G, h)
433- G2 = div (n,G)
434- isprime (G2) ? h[G2] = get (h, G2, 0 ) + 1 : pollardfactors! (G2, h)
435- return h
449+ g, u, _ = gcdx (2 * sy, N)
450+ g > 1 && (g == N ? break : return g)
451+ u += N
452+
453+ L = (u* (3 * sx* sx + a)) % N
454+ x2 = (L* L - 2 * sx) % N
455+
456+ sy = (L* (sx - x2) - sy) % N
457+ sx = x2
458+
459+ sy == 0 && return T (1 )
460+ t >>= 1
436461 end
462+ x, y = xn, yn
437463 end
464+ return T (1 )
438465end
439466
440467"""
0 commit comments