@@ -233,10 +233,9 @@ isprime(n::Int128) = n < 2 ? false :
233
233
234
234
235
235
# Trial division of small (< 2^16) precomputed primes +
236
- # Pollard rho's algorithm with Richard P. Brent optimizations
236
+ # Lenstra elliptic curve algorithm
237
237
# 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
240
239
#
241
240
function factor! (n:: T , h:: AbstractDict{K,Int} ) where {T<: Integer ,K<: Integer }
242
241
# check for special cases
@@ -271,7 +270,7 @@ function factor!(n::T, h::AbstractDict{K,Int}) where {T<:Integer,K<:Integer}
271
270
end
272
271
end
273
272
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)
275
274
end
276
275
277
276
@@ -389,52 +388,80 @@ julia> radical(2*2*3)
389
388
"""
390
389
radical (n) = prod (factor (Set, n))
391
390
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)
404
405
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
410
418
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
419
447
end
420
- G = gcd (q, n)
421
- k += m
422
448
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
436
461
end
462
+ x, y = xn, yn
437
463
end
464
+ return T (1 )
438
465
end
439
466
440
467
"""
0 commit comments