miller-rabin_primality_test.sf 1.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
  1. #!/usr/bin/ruby
  2. # A simple implementation of the Miller-Rabin primality test.
  3. # See aslo:
  4. # https://en.wikipedia.org/wiki/Miller%E2%80%93Rabin_primality_test
  5. # https://rosettacode.org/wiki/Miller%E2%80%93Rabin_primality_test
  6. func miller_rabin(n, k=10) {
  7. return false if (n <= 1)
  8. return true if (n == 2)
  9. return false if (n.is_even)
  10. var t = n-1
  11. var s = t.valuation(2)
  12. var d = t>>s
  13. k.times {
  14. var a = irand(2, t)
  15. var x = powmod(a, d, n)
  16. next if (x ~~ [1, t])
  17. (s-1).times {
  18. x.powmod!(2, n)
  19. return false if (x == 1)
  20. break if (x == t)
  21. }
  22. return false if (x != t)
  23. }
  24. return true
  25. }
  26. var numbers = [
  27. 61_794_479,
  28. 2867561004669023153611,
  29. 803_086_491,
  30. 171_659_461_843,
  31. 902_802_468_593,
  32. 3_539_679_283_117,
  33. 12_905_496_217_051,
  34. 103_497_586_783_721,
  35. ]
  36. numbers.each { |n|
  37. var p = miller_rabin(n, 12)
  38. say ("#{n} is" + (p ? ' ' : ' NOT ') + 'prime')
  39. assert_eq(p, n.is_prime)
  40. }