@@ -164,27 +164,72 @@ true
164
164
```
165
165
"""
166
166
function isprime (n:: Integer )
167
- n < 2 && return false
168
167
n ≤ typemax (Int64) && return isprime (Int64 (n))
169
168
return isprime (BigInt (n))
170
169
end
171
170
172
- function isprime (n:: T ) where {T<: Signed }
173
- # Small precomputed primes + Baillie–PSW for primality testing:
174
- # https://en.wikipedia.org/wiki/Baillie%E2%80%93PSW_primality_test
175
- # https://mathworld.wolfram.com/LucasSequence.html
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 )
176
182
if n < N_SMALL_FACTORS
177
183
n < 2 && return false
178
184
return _min_factor (n) == n
179
185
end
180
- iseven (n) && return false
186
+ iseven (n) && return n == 2
181
187
for m in (3 , 5 , 7 , 11 , 13 , 17 , 19 , 23 )
182
188
n % m == 0 && return false
183
189
end
184
- # miller-raben
190
+ if n< 2 ^ 32
191
+ return miller_rabbin_test (_witnesses (UInt64 (n)), n)
192
+ end
193
+ miller_rabbin_test (2 , n) || return false
194
+ return lucas_test (widen (n))
195
+ end
196
+
197
+ const bases = UInt16[
198
+ 15591 , 2018 , 166 , 7429 , 8064 , 16045 , 10503 , 4399 , 1949 , 1295 , 2776 , 3620 ,
199
+ 560 , 3128 , 5212 , 2657 , 2300 , 2021 , 4652 , 1471 , 9336 , 4018 , 2398 , 20462 ,
200
+ 10277 , 8028 , 2213 , 6219 , 620 , 3763 , 4852 , 5012 , 3185 , 1333 , 6227 , 5298 ,
201
+ 1074 , 2391 , 5113 , 7061 , 803 , 1269 , 3875 , 422 , 751 , 580 , 4729 , 10239 ,
202
+ 746 , 2951 , 556 , 2206 , 3778 , 481 , 1522 , 3476 , 481 , 2487 , 3266 , 5633 ,
203
+ 488 , 3373 , 6441 , 3344 , 17 , 15105 , 1490 , 4154 , 2036 , 1882 , 1813 , 467 ,
204
+ 3307 , 14042 , 6371 , 658 , 1005 , 903 , 737 , 1887 , 7447 , 1888 , 2848 , 1784 ,
205
+ 7559 , 3400 , 951 , 13969 , 4304 , 177 , 41 , 19875 , 3110 , 13221 , 8726 , 571 ,
206
+ 7043 , 6943 , 1199 , 352 , 6435 , 165 , 1169 , 3315 , 978 , 233 , 3003 , 2562 ,
207
+ 2994 , 10587 , 10030 , 2377 , 1902 , 5354 , 4447 , 1555 , 263 , 27027 , 2283 , 305 ,
208
+ 669 , 1912 , 601 , 6186 , 429 , 1930 , 14873 , 1784 , 1661 , 524 , 3577 , 236 ,
209
+ 2360 , 6146 , 2850 , 55637 , 1753 , 4178 , 8466 , 222 , 2579 , 2743 , 2031 , 2226 ,
210
+ 2276 , 374 , 2132 , 813 , 23788 , 1610 , 4422 , 5159 , 1725 , 3597 , 3366 , 14336 ,
211
+ 579 , 165 , 1375 , 10018 , 12616 , 9816 , 1371 , 536 , 1867 , 10864 , 857 , 2206 ,
212
+ 5788 , 434 , 8085 , 17618 , 727 , 3639 , 1595 , 4944 , 2129 , 2029 , 8195 , 8344 ,
213
+ 6232 , 9183 , 8126 , 1870 , 3296 , 7455 , 8947 , 25017 , 541 , 19115 , 368 , 566 ,
214
+ 5674 , 411 , 522 , 1027 , 8215 , 2050 , 6544 , 10049 , 614 , 774 , 2333 , 3007 ,
215
+ 35201 , 4706 , 1152 , 1785 , 1028 , 1540 , 3743 , 493 , 4474 , 2521 , 26845 , 8354 ,
216
+ 864 , 18915 , 5465 , 2447 , 42 , 4511 , 1660 , 166 , 1249 , 6259 , 2553 , 304 ,
217
+ 272 , 7286 , 73 , 6554 , 899 , 2816 , 5197 , 13330 , 7054 , 2818 , 3199 , 811 ,
218
+ 922 , 350 , 7514 , 4452 , 3449 , 2663 , 4708 , 418 , 1621 , 1171 , 3471 , 88 ,
219
+ 11345 , 412 , 1559 , 194
220
+ ]
221
+
222
+ function _witnesses (n:: UInt64 )
223
+ i = xor ((n >> 16 ), n) * 0x45d9f3b
224
+ i = xor ((i >> 16 ), i) * 0x45d9f3b
225
+ i = xor ((i >> 16 ), i) & 255 + 1
226
+ @inbounds return Int (bases[i])
227
+ end
228
+
229
+ function miller_rabbin_test (a, n:: T ) where T<: Signed
185
230
s = trailing_zeros (n - 1 )
186
231
d = (n - 1 ) >>> s
187
- x:: T = powermod (2 , d, n)
232
+ x:: T = powermod (a , d, n)
188
233
if x != 1
189
234
t = s
190
235
while x != n - 1
@@ -193,40 +238,52 @@ function isprime(n::T) where {T<:Signed}
193
238
x == 1 && return false
194
239
end
195
240
end
241
+ return true
242
+ end
196
243
197
- isqrt (n)^ 2 == n && return false
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
198
248
# find Lucas test params
199
249
D:: T = 5
200
250
for (s, d) in zip (Iterators. cycle ((1 ,- 1 )), 5 : 2 : n)
201
251
D = s* d
202
- kronecker (D, n) == - 1 && break
252
+ k = kronecker (D, n)
253
+ k != 1 && break
203
254
end
255
+ k == 0 && return false
204
256
# Lucas test with P=1
205
257
Q:: T = (1 - D) >> 2
206
- U:: T , V:: T , Qk:: T = 1 , 1 , Q # assert types for conversion
207
- k:: T = (n + 1 )# >> trailing_zeros(n + 1)
208
- b = Base. top_set_bit (k)
209
- while b > 0
210
- U = widemul (U, V) % n
211
- V = (widemul (V, V) - Qk - Qk) % n
212
- Qk = widemul (Qk, Qk) % n
213
- b -= 1
214
- if isodd (k >> (b - 1 ))
215
- Qk = widemul (Qk, Q) % n
216
- Utmp, Vtmp = widen (U) + V, V + widemul (U, D)
217
- if isodd (Utmp)
218
- Utmp += n
219
- end
220
- if isodd (Vtmp)
221
- Vtmp += n
222
- end
223
- U = (Utmp >> 1 ) % n
224
- V = (Vtmp >> 1 ) % n
258
+ U:: T , V:: T , Qk:: T = 1 , 1 , Q
259
+ k:: T = (n + 1 )
260
+ trail = trailing_zeros (k)
261
+ k >>= trail
262
+ for b in digits (k, base= 2 )[end - 1 : - 1 : 1 ]
263
+ U = mod (U* V, n)
264
+ V = mod (V * V - Qk - Qk, n)
265
+ Qk = mod (Qk* Qk, n)
266
+ if b == 1
267
+ Qk = mod (Qk* Q, n)
268
+ U, V = U + V, V + U* D
269
+ # adding n makes them even
270
+ # so we can divide by 2 without causing problems
271
+ isodd (U) && (U += n)
272
+ isodd (V) && (V += n)
273
+ U = mod (U >> 1 , n)
274
+ V = mod (V >> 1 , n)
225
275
end
226
276
end
227
- return U == 0
277
+ if U in 0
278
+ return true
279
+ end
280
+ for _ in 1 : trail
281
+ V == 0 && return true
282
+ V = mod (V* V - Qk - Qk, n)
283
+ Qk = mod (Qk * Qk, n)
284
+ end
285
+ return false
228
286
end
229
-
230
287
"""
231
288
isprime(x::BigInt, [reps = 25]) -> Bool
232
289
Probabilistic primality test. Returns `true` if `x` is prime with high probability (pseudoprime);
0 commit comments