@@ -164,51 +164,36 @@ true
164
164
```
165
165
"""
166
166
function 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
172
183
if n < N_SMALL_FACTORS
184
+ n < 2 && return false
173
185
return _min_factor (n) == n
174
186
end
175
187
for m in (3 , 5 , 7 , 11 , 13 , 17 , 19 , 23 )
176
188
n % m == 0 && return false
177
189
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)
189
192
end
190
- return true
193
+ miller_rabbin_test (2 , n) || return false
194
+ return lucas_test (widen (n))
191
195
end
192
196
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)
212
197
const bases = UInt16[
213
198
15591 , 2018 , 166 , 7429 , 8064 , 16045 , 10503 , 4399 , 1949 , 1295 , 2776 , 3620 ,
214
199
560 , 3128 , 5212 , 2657 , 2300 , 2021 , 4652 , 1471 , 9336 , 4018 , 2398 , 20462 ,
@@ -238,18 +223,79 @@ function _witnesses(n::UInt64)
238
223
i = xor ((n >> 16 ), n) * 0x45d9f3b
239
224
i = xor ((i >> 16 ), i) * 0x45d9f3b
240
225
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
242
242
end
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 )
248
243
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)
253
299
254
300
struct FactorIterator{T<: Integer }
255
301
n:: T
963
1009
"""
964
1010
divisors(f::Factorization) -> Vector
965
1011
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`.
967
1013
Divisors are sorted lexicographically, rather than numerically.
968
1014
"""
969
1015
function divisors (f:: Factorization{T} ) where T
0 commit comments