Skip to content

Commit 1e75bf8

Browse files
authored
switch PRIMES to MIN_FACTOR
1 parent 9067ce1 commit 1e75bf8

File tree

1 file changed

+43
-9
lines changed

1 file changed

+43
-9
lines changed

src/Primes.jl

Lines changed: 43 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,27 @@ function primes(lo::Int, hi::Int)
130130
end
131131
primes(n::Int) = primes(1, n)
132132

133-
const PRIMES = primes(2^16)
133+
# internal function for generating the minimum factor of a relatively small number
134+
funcion _min_factor(n)
135+
n == 1 && return 1
136+
for i in 2:isqrt(n)
137+
n%i == 0 && return i
138+
end
139+
return n
140+
end
141+
142+
function _min_factors(limit)
143+
res = Int[]
144+
for i in 1:limit
145+
m = _min_factor(i)
146+
push!(res, m==i ? 1 : m)
147+
end
148+
return res
149+
end
150+
151+
# `MIN_FACTOR[i]` is `1` if `i` is `1` or prime
152+
# otherwise, `MIN_FACTOR[i]` is the first number which factors `i`
153+
const MIN_FACTOR = UInt8.(_min_factors(MIN_FACTOR_SIZE))
134154

135155
"""
136156
isprime(n::Integer) -> Bool
@@ -146,10 +166,12 @@ function isprime(n::Integer)
146166
# Small precomputed primes + Miller-Rabin for primality testing:
147167
# https://en.wikipedia.org/wiki/Miller–Rabin_primality_test
148168
# https://github.com/JuliaLang/julia/issues/11594
169+
if n < length(MIN_FACTOR)
170+
return n > 1 && MIN_FACTOR[n] == 1
171+
end
149172
for m in (2, 3, 5, 7, 11, 13, 17, 19, 23)
150173
n % m == 0 && return n == m
151174
end
152-
n < 841 && return n > 1
153175
s = trailing_zeros(n - 1)
154176
d = (n - 1) >>> s
155177
for a in witnesses(n)::Tuple{Vararg{Int}}
@@ -226,10 +248,10 @@ witnesses(n::Integer) =
226248
isprime(n::UInt128) =
227249
n typemax(UInt64) ? isprime(UInt64(n)) : isprime(BigInt(n))
228250
isprime(n::Int128) = n < 2 ? false :
229-
n typemax(Int64) ? isprime(Int64(n)) : isprime(BigInt(n))
230-
251+
n typemax(UInt64) ? isprime(UInt64(n)) : isprime(BigInt(n))
231252

232-
# Trial division of small (< 2^16) precomputed primes +
253+
# Cache of small factors for tiny numbers (n < 2^16)
254+
# Trial division of small (< 2^16) precomputed primes
233255
# Pollard rho's algorithm with Richard P. Brent optimizations
234256
# https://en.wikipedia.org/wiki/Trial_division
235257
# https://en.wikipedia.org/wiki/Pollard%27s_rho_algorithm
@@ -245,15 +267,27 @@ function factor!(n::T, h::AbstractDict{K,Int}) where {T<:Integer,K<:Integer}
245267
else
246268
return factor!(checked_neg(n), h)
247269
end
248-
elseif n == 1
270+
elseif n == 0
271+
h[n] = 1
249272
return h
250-
elseif n == 0 || isprime(n)
273+
elseif n <= MIN_FACTOR
274+
while true
275+
n == 1 && return h
276+
if MIN_FACTOR[n]==1
277+
increment!(h, 1, n)
278+
return h
279+
else
280+
increment!(h, 1, MIN_FACTOR[n])
281+
n = div(n, MIN_FACTOR[n])
282+
end
283+
end
284+
elseif isprime(n)
251285
h[n] = 1
252286
return h
253287
end
254-
255288
local p::T
256-
for p in PRIMES
289+
for p in 2:length(MIN_FACTOR)
290+
MIN_FACTOR[p] == 1 || continue
257291
num_p = 0
258292
while true
259293
q, r = divrem(n, T(p)) # T(p) so julia <1.9 uses fast divrem for `BigInt`

0 commit comments

Comments
 (0)