@@ -164,51 +164,36 @@ true
164164```
165165"""
166166function isprime (n:: Integer )
167- # Small precomputed primes + Miller-Rabin for primality testing:
168- # https://en.wikipedia.org/wiki/Miller–Rabin_primality_test
169- # https://github.com/JuliaLang/julia/issues/11594
170- n < 2 && return false
171- trailing_zeros (n) > 0 && return n== 2
167+ n ≤ typemax (Int64) && return isprime (Int64 (n))
168+ return isprime (BigInt (n))
169+ end
170+
171+ # Uses a polyalgorithm depending on the size of n.
172+ # n < 2^16: lookup table (we already have this table because it helps factor also)
173+ # n < 2^32: trial division + Miller-Rabbin test with base chosen by
174+ # Forišek and Jančina, "Fast Primality Testing for Integers That Fit into a Machine Word", 2015
175+ # (in particular, see function FJ32_256, from which the hash and bases were taken)
176+ # n < 2^64: Baillie–PSW for primality testing.
177+ # Specifically, this consists of a Miller-Rabbin test and a Lucas test
178+ # For more background on fast primality testing, see:
179+ # http://ntheory.org/pseudoprimes.html
180+ # http://ntheory.org/pseudoprimes.html
181+ function isprime (n:: Int64 )
182+ iseven (n) && return n == 2
172183 if n < N_SMALL_FACTORS
184+ n < 2 && return false
173185 return _min_factor (n) == n
174186 end
175187 for m in (3 , 5 , 7 , 11 , 13 , 17 , 19 , 23 )
176188 n % m == 0 && return false
177189 end
178- s = trailing_zeros (n - 1 )
179- d = (n - 1 ) >>> s
180- for a in witnesses (n):: Tuple{Vararg{Int}}
181- x = powermod (a, d, n)
182- x == 1 && continue
183- t = s
184- while x != n - 1
185- (t -= 1 ) ≤ 0 && return false
186- x = oftype (n, widemul (x, x) % n)
187- x == 1 && return false
188- end
190+ if n< 2 ^ 32
191+ return miller_rabbin_test (_witnesses (UInt64 (n)), n)
189192 end
190- return true
193+ miller_rabbin_test (2 , n) || return false
194+ return lucas_test (widen (n))
191195end
192196
193- """
194- isprime(x::BigInt, [reps = 25]) -> Bool
195- Probabilistic primality test. Returns `true` if `x` is prime with high probability (pseudoprime);
196- and `false` if `x` is composite (not prime). The false positive rate is about `0.25^reps`.
197- `reps = 25` is considered safe for cryptographic applications (Knuth, Seminumerical Algorithms).
198- ```julia
199- julia> isprime(big(3))
200- true
201- ```
202- """
203- isprime (x:: BigInt , reps= 25 ) = is_probably_prime (x; reps= reps)
204-
205- # Miller-Rabin witness choices based on:
206- # http://mathoverflow.net/questions/101922/smallest-collection-of-bases-for-prime-testing-of-64-bit-numbers
207- # http://primes.utm.edu/prove/merged.html
208- # http://miller-rabin.appspot.com
209- # https://github.com/JuliaLang/julia/issues/11594
210- # Forišek and Jančina, "Fast Primality Testing for Integers That Fit into a Machine Word", 2015
211- # (in particular, see function FJ32_256, from which the hash and bases were taken)
212197const bases = UInt16[
213198 15591 , 2018 , 166 , 7429 , 8064 , 16045 , 10503 , 4399 , 1949 , 1295 , 2776 , 3620 ,
214199 560 , 3128 , 5212 , 2657 , 2300 , 2021 , 4652 , 1471 , 9336 , 4018 , 2398 , 20462 ,
@@ -238,18 +223,79 @@ function _witnesses(n::UInt64)
238223 i = xor ((n >> 16 ), n) * 0x45d9f3b
239224 i = xor ((i >> 16 ), i) * 0x45d9f3b
240225 i = xor ((i >> 16 ), i) & 255 + 1
241- @inbounds return (Int (bases[i]),)
226+ @inbounds return Int (bases[i])
227+ end
228+
229+ function miller_rabbin_test (a, n:: T ) where T<: Signed
230+ s = trailing_zeros (n - 1 )
231+ d = (n - 1 ) >>> s
232+ x:: T = powermod (a, d, n)
233+ if x != 1
234+ t = s
235+ while x != n - 1
236+ (t -= 1 ) ≤ 0 && return false
237+ x = widemul (x, x) % n
238+ x == 1 && return false
239+ end
240+ end
241+ return true
242242end
243- witnesses (n:: Integer ) =
244- n < 4294967296 ? _witnesses (UInt64 (n)) :
245- n < 2152302898747 ? (2 , 3 , 5 , 7 , 11 ) :
246- n < 3474749660383 ? (2 , 3 , 5 , 7 , 11 , 13 ) :
247- (2 , 325 , 9375 , 28178 , 450775 , 9780504 , 1795265022 )
248243
249- isprime (n:: UInt128 ) =
250- n ≤ typemax (UInt64) ? isprime (UInt64 (n)) : isprime (BigInt (n))
251- isprime (n:: Int128 ) = n < 2 ? false :
252- n ≤ typemax (UInt64) ? isprime (UInt64 (n)) : isprime (BigInt (n))
244+ function lucas_test (n:: T ) where T<: Signed
245+ s = isqrt (n)
246+ @assert s <= typemax (T) # to prevent overflow
247+ s^ 2 == n && return false
248+ # find Lucas test params
249+ D:: T = 5
250+ for (s, d) in zip (Iterators. cycle ((1 ,- 1 )), 5 : 2 : n)
251+ D = s* d
252+ k = kronecker (D, n)
253+ k != 1 && break
254+ end
255+ k == 0 && return false
256+ # Lucas test with P=1
257+ Q:: T = (1 - D) >> 2
258+ U:: T , V:: T , Qk:: T = 1 , 1 , Q
259+ k:: T = (n + 1 )
260+ trail = trailing_zeros (k)
261+ k >>= trail
262+ # get digits 1 at a time since digits allocates
263+ for b in ndigits (k,base= 2 )- 2 : - 1 : 0
264+ U = mod (U* V, n)
265+ V = mod (V * V - Qk - Qk, n)
266+ Qk = mod (Qk* Qk, n)
267+ if isodd (k>> b) == 1
268+ Qk = mod (Qk* Q, n)
269+ U, V = U + V, V + U* D
270+ # adding n makes them even
271+ # so we can divide by 2 without causing problems
272+ isodd (U) && (U += n)
273+ isodd (V) && (V += n)
274+ U = mod (U >> 1 , n)
275+ V = mod (V >> 1 , n)
276+ end
277+ end
278+ if U in 0
279+ return true
280+ end
281+ for _ in 1 : trail
282+ V == 0 && return true
283+ V = mod (V* V - Qk - Qk, n)
284+ Qk = mod (Qk * Qk, n)
285+ end
286+ return false
287+ end
288+ """
289+ isprime(x::BigInt, [reps = 25]) -> Bool
290+ Probabilistic primality test. Returns `true` if `x` is prime with high probability (pseudoprime);
291+ and `false` if `x` is composite (not prime). The false positive rate is about `0.25^reps`.
292+ `reps = 25` is considered safe for cryptographic applications (Knuth, Seminumerical Algorithms).
293+ ```julia
294+ julia> isprime(big(3))
295+ true
296+ ```
297+ """
298+ isprime (x:: BigInt , reps= 25 ) = x> 1 && is_probably_prime (x; reps= reps)
253299
254300struct FactorIterator{T<: Integer }
255301 n:: T
9631009"""
9641010 divisors(f::Factorization) -> Vector
9651011
966- Return a vector with the positive divisors of the number whose factorization is `f`.
1012+ Return a vector with the positive divisors of the number whose factorization is `f`.
9671013Divisors are sorted lexicographically, rather than numerically.
9681014"""
9691015function divisors (f:: Factorization{T} ) where {T<: Integer }
0 commit comments