Skip to content

Commit 63fe1a0

Browse files
committed
faster and more modular
1 parent adcdbec commit 63fe1a0

File tree

1 file changed

+26
-17
lines changed

1 file changed

+26
-17
lines changed

src/Primes.jl

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,7 @@ function factor!(n::T, h::AbstractDict{K,Int}) where {T<:Integer,K<:Integer}
270270
end
271271
end
272272
isprime(n) && (h[n]=1; return h)
273-
T <: BigInt || widemul(n - 1, n - 1) typemax(n) ? lenstrafactors!(n, h) : lenstrafactors!(widen(n), h)
273+
lenstrafactors!(widen(n), h)
274274
end
275275

276276

@@ -394,36 +394,46 @@ function inthroot(n::Integer, r::Int)
394394
return ans
395395
end
396396

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)
397+
function primepowerfactor!(n::T, h::AbstractDict{K,Int}) where{T<:Integer,K<:Integer}
399398
r = ceil(Int, inv(log(n, Primes.PRIMES[end])))+1
400399
root = inthroot(n, r)
401400
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)
401+
if root^r == n && isprime(root)
402+
h[root] = get(h, root, 0) + r
403+
return true
405404
end
406405
r -= 1
407406
root = inthroot(n, r)
408407
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)
408+
return false
409+
end
410+
411+
function lenstrafactors!(n::T, h::AbstractDict{K,Int}) where{T<:Integer,K<:Integer}
412+
isprime(n) && (h[n] = get(h, n, 0)+1; return h)
413+
primepowerfactor!(n::T, h) && return h
414+
# bounds and runs per bound taken from
415+
# https://www.rieselprime.de/ziki/Elliptic_curve_method
416+
B1s = Int[2e3, 11e3, 5e4, 25e4, 1e6, 3e6, 11e6,
417+
43e6, 11e7, 26e7, 85e7, 29e8, 76e8, 25e9]
418+
runs = (74, 221, 453, 984, 2541, 4949, 8266, 20158,
419+
47173, 77666, 42057, 69471, 102212, 188056, 265557)
420+
for (B1, run) in zip(B1s, runs)
421+
small_primes = primes(B1)
422+
for a in -run:run
423+
res = lenstra_get_factor(n, a, small_primes, B1)
413424
if res != 1
414425
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
426+
n = div(n,res)
427+
primepowerfactor!(n::T, h) && return h
428+
isprime(n) && (h[n] = get(h, n, 0) + 1; return h)
418429
end
419430
end
420431
end
432+
throw(ArgumentError("This number is too big to be factored with this algorith effectively"))
421433
end
422434

423435
function lenstra_get_factor(N::T, a, small_primes, plimit) where T <: Integer
424-
x = T(0)
425-
y = T(1)
426-
436+
x, y = T(0), T(1)
427437
for B in small_primes
428438
t = B^trunc(Int64, log(B, plimit))
429439
xn, yn = T(0), T(0)
@@ -463,7 +473,6 @@ function lenstra_get_factor(N::T, a, small_primes, plimit) where T <: Integer
463473
end
464474
return T(1)
465475
end
466-
467476
"""
468477
ismersenneprime(M::Integer; [check::Bool = true]) -> Bool
469478

0 commit comments

Comments
 (0)