primality_testing_fermat_fourier.sf 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
  1. #!/usr/bin/ruby
  2. # A non-practical (but interesting) implementation of Fermat's pseudo-primality testing method, using a closed-form of the Fourier series for the floor function.
  3. # Fermat's little theorem:
  4. # a^(p-1) = 1 mod p
  5. # Floor function Fourier closed-form:
  6. # floor(x) = (π * (2*x - 1) - i*log(1 - exp(-2*i*π*x)) + i*log(1 - exp(2*i*π*x)))/(2*π)
  7. # Remainder in terms of the floor(x) function:
  8. # x mod y = x - y*floor(x/y)
  9. # See also:
  10. # https://en.wikipedia.org/wiki/Fermat's_little_theorem
  11. # https://en.wikipedia.org/wiki/Floor_and_ceiling_functions#Continuity_and_series_expansions
  12. local Number!PREC = 1000.numify
  13. const π = Num.pi
  14. const i = Num.i
  15. func is_fermat_prime_1(n) {
  16. return 0 if (n == 1)
  17. return 1 if (n == 2)
  18. 2**(n - 1) - n*(2**(n - 1) / n + (i*(log(1 - exp((i*π * 2**n)/n)) - log(exp(-(i*π * 2**n)/n) * (-1 + exp((i * π * 2**n)/n)))))/(2*π) - 1/2)
  19. }
  20. func is_fermat_prime_2(n) {
  21. return 0 if (n == 1)
  22. return 1 if (n == 2)
  23. (n * (i*log(1 - exp(-(i*π * 2**n)/n)) - i*log(1 - exp((i*π * 2**n)/n)) + π))/(2*π)
  24. }
  25. func is_fermat_prime_3(n) {
  26. return 0 if (n == 1)
  27. return 1 if (n == 2)
  28. (i*n*acoth(tanh((log(1 - exp(-((i*π*exp(log(2)*n))/n))) - log(1 - exp((i*π*exp(log(2)*n))/n)))/2)))/π
  29. }
  30. # Display the primes below 100
  31. say (1..100 -> grep { is_fermat_prime_1(_) =~= 1 })
  32. say (1..100 -> grep { is_fermat_prime_2(_) =~= 1 })
  33. say (1..100 -> grep { is_fermat_prime_3(_) =~= 1 })