@@ -130,7 +130,26 @@ 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
+ function _generate_min_factors (limit)
134
+ function min_factor (n)
135
+ n < 4 && return n
136
+ for i in 3 : 2 : isqrt (n)
137
+ n% i == 0 && return i
138
+ end
139
+ return n
140
+ end
141
+ res = Int[]
142
+ for i in 3 : 2 : limit
143
+ m = min_factor (i)
144
+ push! (res, m== i ? 1 : m)
145
+ end
146
+ return res
147
+ end
148
+
149
+ const N_SMALL_FACTORS = 2 ^ 16
150
+ const _MIN_FACTOR = UInt8 .(_generate_min_factors (N_SMALL_FACTORS))
151
+ # _min_factor(n) = 1 if n is prime, otherwise the minimum factor of n
152
+ _min_factor (n) = _MIN_FACTOR[n>> 1 ]
134
153
135
154
"""
136
155
isprime(n::Integer) -> Bool
@@ -146,10 +165,14 @@ function isprime(n::Integer)
146
165
# Small precomputed primes + Miller-Rabin for primality testing:
147
166
# https://en.wikipedia.org/wiki/Miller–Rabin_primality_test
148
167
# https://github.com/JuliaLang/julia/issues/11594
149
- for m in (2 , 3 , 5 , 7 , 11 , 13 , 17 , 19 , 23 )
150
- n % m == 0 && return n == m
168
+ n < 2 && return false
169
+ trailing_zeros (n) > 0 && return n== 2
170
+ if n < N_SMALL_FACTORS
171
+ return _min_factor (n) == 1
172
+ end
173
+ for m in (3 , 5 , 7 , 11 , 13 , 17 , 19 , 23 )
174
+ n % m == 0 && return false
151
175
end
152
- n < 841 && return n > 1
153
176
s = trailing_zeros (n - 1 )
154
177
d = (n - 1 ) >>> s
155
178
for a in witnesses (n):: Tuple{Vararg{Int}}
@@ -226,10 +249,10 @@ witnesses(n::Integer) =
226
249
isprime (n:: UInt128 ) =
227
250
n ≤ typemax (UInt64) ? isprime (UInt64 (n)) : isprime (BigInt (n))
228
251
isprime (n:: Int128 ) = n < 2 ? false :
229
- n ≤ typemax (Int64) ? isprime (Int64 (n)) : isprime (BigInt (n))
230
-
252
+ n ≤ typemax (UInt64) ? isprime (UInt64 (n)) : isprime (BigInt (n))
231
253
232
- # Trial division of small (< 2^16) precomputed primes +
254
+ # Cache of small factors for tiny numbers (n < 2^16)
255
+ # Trial division of small (< 2^16) precomputed primes
233
256
# Pollard rho's algorithm with Richard P. Brent optimizations
234
257
# https://en.wikipedia.org/wiki/Trial_division
235
258
# https://en.wikipedia.org/wiki/Pollard%27s_rho_algorithm
@@ -238,22 +261,37 @@ isprime(n::Int128) = n < 2 ? false :
238
261
function factor! (n:: T , h:: AbstractDict{K,Int} ) where {T<: Integer ,K<: Integer }
239
262
# check for special cases
240
263
if n < 0
241
- h[- 1 ] = 1
264
+ h[- 1 ] = 1 - h[ - 1 ]
242
265
if isa (n, BitSigned) && n == typemin (T)
243
- h[2 ] = 8 * sizeof (T) - 1
266
+ h[2 ] + = 8 * sizeof (T) - 1
244
267
return h
245
268
else
246
269
return factor! (checked_neg (n), h)
247
270
end
248
- elseif n == 1
249
- return h
250
- elseif n == 0 || isprime (n)
271
+ elseif n == 0
251
272
h[n] = 1
252
273
return h
274
+ elseif trailing_zeros (n) > 0
275
+ tz = trailing_zeros (n)
276
+ increment! (h, tz, 2 )
277
+ n >>= tz
278
+ end
279
+ if n <= N_SMALL_FACTORS
280
+ while true
281
+ n == 1 && return h
282
+ if _min_factor (n)== 1
283
+ return increment! (h, 1 , n)
284
+ else
285
+ increment! (h, 1 , _min_factor (n))
286
+ n = div (n, _min_factor (n))
287
+ end
288
+ end
289
+ elseif isprime (n)
290
+ return increment! (h, 1 , n)
253
291
end
254
-
255
292
local p:: T
256
- for p in PRIMES
293
+ for p in 3 : 2 : N_SMALL_FACTORS
294
+ _min_factor (p) == 1 || continue
257
295
num_p = 0
258
296
while true
259
297
q, r = divrem (n, T (p)) # T(p) so julia <1.9 uses fast divrem for `BigInt`
@@ -262,11 +300,15 @@ function factor!(n::T, h::AbstractDict{K,Int}) where {T<:Integer,K<:Integer}
262
300
n = q
263
301
end
264
302
# h[p] += num_p (about 2x faster, but the speed only matters for small numbers)
265
- num_p > 0 && increment! (h, num_p, p)
303
+ if num_p > 0
304
+ increment! (h, num_p, p)
305
+ # if n is small, then recursing will hit the fast path.
306
+ n < N_SMALL_FACTORS && return factor! (n, h)
307
+ end
266
308
p* p > n && break
267
309
end
268
310
n == 1 && return h
269
- isprime (n) && (h[n] = 1 ; return h )
311
+ isprime (n) && return increment! (h, 1 , n )
270
312
T <: BigInt || widemul (n - 1 , n - 1 ) ≤ typemax (n) ? pollardfactors! (n, h) : pollardfactors! (widen (n), h)
271
313
end
272
314
0 commit comments