lucas_restricted_domain_primality_test.sf 1.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
  1. #!/usr/bin/ruby
  2. # A Restricted Domain Lucas Probable Prime Test.
  3. # Algorithm due to Paul Underwood:
  4. # https://mersenneforum.org/showpost.php?p=592064&postcount=1
  5. # https://mersenneforum.org/attachment.php?s=079f9f78729772b2ca6812afe23864f6&attachmentid=26368&d=1645276338
  6. func RDPRP(n) {
  7. if (n==2 || n==3 || n==7) {
  8. return true
  9. }
  10. if (n<2 || n.is_even || n.is_div(3) || n.is_div(7) || n.is_square) {
  11. return false
  12. }
  13. var k = kronecker(2, n)
  14. if (Mod(2, n)**((n-1)/2) != k) {
  15. return false
  16. }
  17. var r = 0
  18. var t = Mod(4, n)**r
  19. while ((kronecker(t.lift - 8, n) != -1) || (gcd((r-1)*(2*r - 1), n-1) > 3)) {
  20. ++r
  21. t *= 4
  22. }
  23. static z = Poly(1)
  24. Mod(Mod(z, n), z**2 - (t/2 - 2)*z + 1)**((n+1)/2) == k
  25. }
  26. say RDPRP(1e100.random_prime) #=> true
  27. say RDPRP(1e100.irand.next_composite) #=> false
  28. assert(!RDPRP(341))
  29. assert(!RDPRP(561))
  30. assert(RDPRP(541))
  31. assert(!RDPRP(530881))
  32. assert(!RDPRP(2**256 + 1))
  33. assert(RDPRP(2**127 - 1))
  34. assert(!RDPRP(1e100.irand.next_composite))
  35. assert(RDPRP(1e100.random_prime))