@@ -130,7 +130,27 @@ function primes(lo::Int, hi::Int)
130
130
end
131
131
primes (n:: Int ) = primes (1 , n)
132
132
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))
134
154
135
155
"""
136
156
isprime(n::Integer) -> Bool
@@ -146,10 +166,12 @@ function isprime(n::Integer)
146
166
# Small precomputed primes + Miller-Rabin for primality testing:
147
167
# https://en.wikipedia.org/wiki/Miller–Rabin_primality_test
148
168
# https://github.com/JuliaLang/julia/issues/11594
169
+ if n < length (MIN_FACTOR)
170
+ return n > 1 && MIN_FACTOR[n] == 1
171
+ end
149
172
for m in (2 , 3 , 5 , 7 , 11 , 13 , 17 , 19 , 23 )
150
173
n % m == 0 && return n == m
151
174
end
152
- n < 841 && return n > 1
153
175
s = trailing_zeros (n - 1 )
154
176
d = (n - 1 ) >>> s
155
177
for a in witnesses (n):: Tuple{Vararg{Int}}
@@ -226,10 +248,10 @@ witnesses(n::Integer) =
226
248
isprime (n:: UInt128 ) =
227
249
n ≤ typemax (UInt64) ? isprime (UInt64 (n)) : isprime (BigInt (n))
228
250
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))
231
252
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
233
255
# Pollard rho's algorithm with Richard P. Brent optimizations
234
256
# https://en.wikipedia.org/wiki/Trial_division
235
257
# 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}
245
267
else
246
268
return factor! (checked_neg (n), h)
247
269
end
248
- elseif n == 1
270
+ elseif n == 0
271
+ h[n] = 1
249
272
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)
251
285
h[n] = 1
252
286
return h
253
287
end
254
-
255
288
local p:: T
256
- for p in PRIMES
289
+ for p in 2 : length (MIN_FACTOR)
290
+ MIN_FACTOR[p] == 1 || continue
257
291
num_p = 0
258
292
while true
259
293
q, r = divrem (n, T (p)) # T(p) so julia <1.9 uses fast divrem for `BigInt`
0 commit comments