@@ -164,30 +164,67 @@ 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 < 2 && return false
168
+ n ≤ typemax (Int64) && return isprime (Int64 (n))
169
+ return isprime (BigInt (n))
170
+ end
171
+
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
172
176
if n < N_SMALL_FACTORS
177
+ n < 2 && return false
173
178
return _min_factor (n) == n
174
179
end
180
+ iseven (n) && return false
175
181
for m in (3 , 5 , 7 , 11 , 13 , 17 , 19 , 23 )
176
182
n % m == 0 && return false
177
183
end
184
+ # miller-raben
178
185
s = trailing_zeros (n - 1 )
179
186
d = (n - 1 ) >>> s
180
- for a in witnesses (n):: Tuple{Vararg{Int}}
181
- x = powermod (a, d, n)
182
- x == 1 && continue
187
+ x:: T = powermod (2 , d, n)
188
+ if x != 1
183
189
t = s
184
190
while x != n - 1
185
191
(t -= 1 ) ≤ 0 && return false
186
- x = oftype (n, widemul (x, x) % n)
192
+ x = widemul (x, x) % n
187
193
x == 1 && return false
188
194
end
189
195
end
190
- return true
196
+
197
+ isqrt (n)^ 2 == n && return false
198
+ # find Lucas test params
199
+ D:: T = 5
200
+ for (s, d) in zip (Iterators. cycle ((1 ,- 1 )), 5 : 2 : n)
201
+ D = s* d
202
+ kronecker (D, n) == - 1 && break
203
+ end
204
+ # Lucas test with P=1
205
+ 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
225
+ end
226
+ end
227
+ return U == 0
191
228
end
192
229
193
230
"""
@@ -200,56 +237,7 @@ julia> isprime(big(3))
200
237
true
201
238
```
202
239
"""
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
- const bases = UInt16[
213
- 15591 , 2018 , 166 , 7429 , 8064 , 16045 , 10503 , 4399 , 1949 , 1295 , 2776 , 3620 ,
214
- 560 , 3128 , 5212 , 2657 , 2300 , 2021 , 4652 , 1471 , 9336 , 4018 , 2398 , 20462 ,
215
- 10277 , 8028 , 2213 , 6219 , 620 , 3763 , 4852 , 5012 , 3185 , 1333 , 6227 , 5298 ,
216
- 1074 , 2391 , 5113 , 7061 , 803 , 1269 , 3875 , 422 , 751 , 580 , 4729 , 10239 ,
217
- 746 , 2951 , 556 , 2206 , 3778 , 481 , 1522 , 3476 , 481 , 2487 , 3266 , 5633 ,
218
- 488 , 3373 , 6441 , 3344 , 17 , 15105 , 1490 , 4154 , 2036 , 1882 , 1813 , 467 ,
219
- 3307 , 14042 , 6371 , 658 , 1005 , 903 , 737 , 1887 , 7447 , 1888 , 2848 , 1784 ,
220
- 7559 , 3400 , 951 , 13969 , 4304 , 177 , 41 , 19875 , 3110 , 13221 , 8726 , 571 ,
221
- 7043 , 6943 , 1199 , 352 , 6435 , 165 , 1169 , 3315 , 978 , 233 , 3003 , 2562 ,
222
- 2994 , 10587 , 10030 , 2377 , 1902 , 5354 , 4447 , 1555 , 263 , 27027 , 2283 , 305 ,
223
- 669 , 1912 , 601 , 6186 , 429 , 1930 , 14873 , 1784 , 1661 , 524 , 3577 , 236 ,
224
- 2360 , 6146 , 2850 , 55637 , 1753 , 4178 , 8466 , 222 , 2579 , 2743 , 2031 , 2226 ,
225
- 2276 , 374 , 2132 , 813 , 23788 , 1610 , 4422 , 5159 , 1725 , 3597 , 3366 , 14336 ,
226
- 579 , 165 , 1375 , 10018 , 12616 , 9816 , 1371 , 536 , 1867 , 10864 , 857 , 2206 ,
227
- 5788 , 434 , 8085 , 17618 , 727 , 3639 , 1595 , 4944 , 2129 , 2029 , 8195 , 8344 ,
228
- 6232 , 9183 , 8126 , 1870 , 3296 , 7455 , 8947 , 25017 , 541 , 19115 , 368 , 566 ,
229
- 5674 , 411 , 522 , 1027 , 8215 , 2050 , 6544 , 10049 , 614 , 774 , 2333 , 3007 ,
230
- 35201 , 4706 , 1152 , 1785 , 1028 , 1540 , 3743 , 493 , 4474 , 2521 , 26845 , 8354 ,
231
- 864 , 18915 , 5465 , 2447 , 42 , 4511 , 1660 , 166 , 1249 , 6259 , 2553 , 304 ,
232
- 272 , 7286 , 73 , 6554 , 899 , 2816 , 5197 , 13330 , 7054 , 2818 , 3199 , 811 ,
233
- 922 , 350 , 7514 , 4452 , 3449 , 2663 , 4708 , 418 , 1621 , 1171 , 3471 , 88 ,
234
- 11345 , 412 , 1559 , 194
235
- ]
236
-
237
- function _witnesses (n:: UInt64 )
238
- i = xor ((n >> 16 ), n) * 0x45d9f3b
239
- i = xor ((i >> 16 ), i) * 0x45d9f3b
240
- i = xor ((i >> 16 ), i) & 255 + 1
241
- @inbounds return (Int (bases[i]),)
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
-
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))
240
+ isprime (x:: BigInt , reps= 25 ) = x> 1 && is_probably_prime (x; reps= reps)
253
241
254
242
struct FactorIterator{T<: Integer }
255
243
n:: T
963
951
"""
964
952
divisors(f::Factorization) -> Vector
965
953
966
- Return a vector with the positive divisors of the number whose factorization is `f`.
954
+ Return a vector with the positive divisors of the number whose factorization is `f`.
967
955
Divisors are sorted lexicographically, rather than numerically.
968
956
"""
969
957
function divisors (f:: Factorization{T} ) where {T<: Integer }
0 commit comments