@@ -387,8 +387,20 @@ function iterate(f::FactorIterator{T}, state=(f.n, T(3))) where T
387387 if n <= 2 ^ 32 || isprime (n)
388388 return (n, 1 ), (T (1 ), n)
389389 end
390+ # check for n=root^r
391+ r = cld (ndigits (n, base= 2 ), ndigits (Primes. PRIMES[end ], base= 2 ))
392+ root = inthroot (n, r)
393+ while r >= 2
394+ if root^ r == n
395+ isprime (root) && return (root, r), (n, root+ 2 )
396+
397+ end
398+ r -= 1
399+ root = inthroot (n, r)
400+ end
401+
390402 should_widen = T <: BigInt || widemul (n - 1 , n - 1 ) ≤ typemax (n)
391- p = should_widen ? pollardfactor (n) : pollardfactor (widen (n))
403+ p = should_widen ? lenstrafactor (n) : lenstrafactor (widen (n))
392404 num_p = 0
393405 while true
394406 q, r = divrem (n, p)
@@ -520,55 +532,65 @@ julia> radical(2*2*3)
520532"""
521533radical (n) = n== 1 ? one (n) : prod (p for (p, num_p) in eachfactor (n))
522534
523- function pollardfactor (n:: T ) where {T<: Integer }
524- while true
525- c:: T = rand (1 : (n - 1 ))
526- G:: T = 1
527- r:: T = 1
528- y:: T = rand (0 : (n - 1 ))
529- m:: T = 100
530- ys:: T = 0
531- q:: T = 1
532- x:: T = 0
533- while c == n - 2
534- c = rand (1 : (n - 1 ))
535- end
536- while G == 1
537- x = y
538- for i in 1 : r
539- y = y^ 2 % n
540- y = (y + c) % n
541- end
542- k:: T = 0
543- G = 1
544- while k < r && G == 1
545- ys = y
546- for i in 1 : (m > (r - k) ? (r - k) : m)
547- y = y^ 2 % n
548- y = (y + c) % n
549- q = (q * (x > y ? x - y : y - x)) % n
550- end
551- G = gcd (q, n)
552- k += m
535+ function lenstrafactor (n:: T ) where {T<: Integer }
536+ # bounds and runs per bound taken from
537+ # https://www.rieselprime.de/ziki/Elliptic_curve_method
538+ B1s = Int[2e3 , 11e3 , 5e4 , 25e4 , 1e6 , 3e6 , 11e6 ,
539+ 43e6 , 11e7 , 26e7 , 85e7 , 29e8 , 76e8 , 25e9 ]
540+ runs = (74 , 221 , 453 , 984 , 2541 , 4949 , 8266 , 20158 ,
541+ 47173 , 77666 , 42057 , 69471 , 102212 , 188056 , 265557 )
542+ for (B1, run) in zip (B1s, runs)
543+ small_primes = primes (B1)
544+ for a in - run: run
545+ res = lenstra_get_factor (n, a, small_primes, B1)
546+ if res != 1
547+ return isprime (res) ? res : lenstrafactor (res)
553548 end
554- r *= 2
555- end
556- G == n && (G = 1 )
557- while G == 1
558- ys = ys^ 2 % n
559- ys = (ys + c) % n
560- G = gcd (x > ys ? x - ys : ys - x, n)
561549 end
562- if G != n
563- G2 = div (n,G)
564- f = min (G, G2)
565- _gcd = gcd (G, G2)
566- if _gcd != 1
567- f = _gcd
550+ end
551+ throw (ArgumentError (" This number is too big to be factored with this algorith effectively" ))
552+ end
553+
554+ function lenstra_get_factor (N:: T , a, small_primes, plimit) where T <: Integer
555+ x, y = T (0 ), T (1 )
556+ for B in small_primes
557+ t = B^ trunc (Int64, log (B, plimit))
558+ xn, yn = T (0 ), T (0 )
559+ sx, sy = x, y
560+
561+ first = true
562+ while t > 0
563+ if isodd (t)
564+ if first
565+ xn, yn = sx, sy
566+ first = false
567+ else
568+ g, u, _ = gcdx (sx- xn, N)
569+ g > 1 && (g == N ? break : return g)
570+ u += N
571+ L = (u* (sy- yn)) % N
572+ xs = (L* L - xn - sx) % N
573+
574+ yn = (L* (xn - xs) - yn) % N
575+ xn = xs
576+ end
568577 end
569- return isprime (f) ? f : pollardfactor (f)
578+ g, u, _ = gcdx (2 * sy, N)
579+ g > 1 && (g == N ? break : return g)
580+ u += N
581+
582+ L = (u* (3 * sx* sx + a)) % N
583+ x2 = (L* L - 2 * sx) % N
584+
585+ sy = (L* (sx - x2) - sy) % N
586+ sx = x2
587+
588+ sy == 0 && return T (1 )
589+ t >>= 1
570590 end
591+ x, y = xn, yn
571592 end
593+ return T (1 )
572594end
573595
574596"""
0 commit comments