@@ -387,8 +387,20 @@ function iterate(f::FactorIterator{T}, state=(f.n, T(3))) where T
387
387
if n <= 2 ^ 32 || isprime (n)
388
388
return (n, 1 ), (T (1 ), n)
389
389
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
+
390
402
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))
392
404
num_p = 0
393
405
while true
394
406
q, r = divrem (n, p)
@@ -520,55 +532,65 @@ julia> radical(2*2*3)
520
532
"""
521
533
radical (n) = n== 1 ? one (n) : prod (p for (p, num_p) in eachfactor (n))
522
534
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)
553
548
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)
561
549
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
568
577
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
570
590
end
591
+ x, y = xn, yn
571
592
end
593
+ return T (1 )
572
594
end
573
595
574
596
"""
0 commit comments