fermat_strong_primality_test.sf 1.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
  1. #!/usr/bin/ruby
  2. # Strong Fermat primality test (Miller–Rabin primality test).
  3. # See also:
  4. # https://oeis.org/A001262 -- Strong pseudoprimes to base 2.
  5. # https://oeis.org/A020229 -- Strong pseudoprimes to base 3.
  6. # https://en.wikipedia.org/wiki/Miller%E2%80%93Rabin_primality_test
  7. func is_strong_fermat_pseudoprime(n, base=2) {
  8. return false if (n <= 1)
  9. return true if (n == 2)
  10. return false if (n.is_even)
  11. var d = n-1
  12. var v = d.valuation(2)
  13. var q = d>>v
  14. var x = powmod(base, q, n)
  15. if (x ~~ [1, n-1]) {
  16. return true
  17. }
  18. (v-1).times {
  19. x = powmod(x, 2, n)
  20. if (x == 1) {
  21. return false
  22. }
  23. if (x == n-1) {
  24. return true
  25. }
  26. }
  27. return false
  28. }
  29. say ("Primes below 100: ", is_strong_fermat_pseudoprime.grep(1..100))
  30. say ("First 5 strong pseudoprimes to base 2: ", { !.is_prime && is_strong_fermat_pseudoprime(_, 2) }.first(5))
  31. __END__
  32. Primes below 100: [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]
  33. First 5 strong pseudoprimes to base 2: [2047, 3277, 4033, 4681, 8321]