I'm trying to write an optimized algorithm in Julia to find all divisors of an integer. The heavy part, i.e. factoring, is done using Primes.jl and the algorithm seems quite fast. But I'm thinking of making it more faster, specifically, as I'll be iterating over the divisors at the end, I tried to use a generator to save memory allocations.
How can I optimize this function using generators? I tried some alternatives but hit an instability issue in Iterators.Flatten(). For example, Iterators.Flatten(((0 for i in 1:5), (1 for i in 1:5))) will yield eltype Any. I appreciate your suggestions.
using Primes
function divisors(n)
d = Int64[1]
for (p, e) in factor(n)
r = 1
l = length(d)
for i in 1:e
r *= p
for j in 1:l
push!(d, d[j]*r)
end
end
end
return sort(d) # not strictly required
end
Edit: Preallocating the output vector saves another 25% of time.
function divisors2(n)
f = factor(n)
m = prod(e + 1 for (p, e) in f)
d = Vector{Int64}(undef, m)
k = 1
d[k] = 1
for (p, e) in f
r = 1
l = k
for i in 1:e
r *= p
for j in 1:l
d[k+=1] = d[j]*r
end
end
end
return sort(d) # not strictly required
end
For the given example you could achieve type stability where
flattening iterators created using theIteratorspackage.Hence this is type stable (no more
Anyin the returned list):