squarefree_fermat_pseudoprimes_in_range.jl 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. #!/usr/bin/julia
  2. # Daniel "Trizen" Șuteu
  3. # Date: 06 September 2022
  4. # https://github.com/trizen
  5. # Generate all the squarefree Fermat pseudoprimes to given a base with n prime factors in a given range [A,B]. (not in sorted order)
  6. # See also:
  7. # https://en.wikipedia.org/wiki/Almost_prime
  8. # https://trizenx.blogspot.com/2020/08/pseudoprimes-construction-methods-and.html
  9. # PARI/GP program (in range [A, B]):
  10. # squarefree_fermat(A, B, k, base=2) = A=max(A, vecprod(primes(k))); (f(m, l, p, k, u=0, v=0) = my(list=List()); if(k==1, forprime(p=u, v, if(base%p != 0, my(t=m*p); if((t-1)%l == 0 && (t-1)%znorder(Mod(base, p)) == 0, listput(list, t)))), forprime(q = p, sqrtnint(B\m, k), my(t = m*q); if (base%q != 0, my(L=lcm(l, znorder(Mod(base, q)))); if(gcd(L, t) == 1, my(u=ceil(A/t), v=B\t); if(u <= v, my(r=nextprime(q+1)); if(k==2 && r>u, u=r); list=concat(list, f(t, L, r, k-1, u, v))))))); list); vecsort(Vec(f(1, 1, 2, k)));
  11. using Primes
  12. const BIG = false # true to use big integers
  13. function divisors(n)
  14. d = Int64[1]
  15. for (p,e) in factor(n)
  16. t = Int64[]
  17. r = 1
  18. for i in 1:e
  19. r *= p
  20. for u in d
  21. push!(t, u*r)
  22. end
  23. end
  24. append!(d, t)
  25. end
  26. sort!(d)
  27. return d
  28. end
  29. function prime_znorder(a, n)
  30. for d in divisors(n-1)
  31. if (powermod(a, d, n) == 1)
  32. return d
  33. end
  34. end
  35. end
  36. function big_prod(arr)
  37. BIG || return prod(arr)
  38. r = big"1"
  39. for n in (arr)
  40. r *= n
  41. end
  42. return r
  43. end
  44. function squarefree_fermat_pseudoprimes_in_range(A, B, k, base, callback)
  45. A = max(A, big_prod(primes(prime(k))))
  46. F = function(m, L, lo::Int64, k::Int64)
  47. hi = round(Int64, fld(B, m)^(1/k))
  48. if (lo > hi)
  49. return nothing
  50. end
  51. if (k == 1)
  52. lo = round(Int64, max(lo, cld(A, m)))
  53. lo > hi && return nothing
  54. t = invmod(m, L)
  55. t > hi && return nothing
  56. if (t < lo)
  57. t += L*cld(lo - t, L)
  58. end
  59. t > hi && return nothing
  60. for p in t:L:hi
  61. if (isprime(p) && base%p != 0)
  62. if ((m*p - 1) % prime_znorder(base, p) == 0)
  63. callback(m*p)
  64. end
  65. end
  66. end
  67. return nothing
  68. end
  69. for p in primes(lo, hi)
  70. if (base % p != 0)
  71. z = prime_znorder(base, p)
  72. if (gcd(m, z) == 1)
  73. F(m*p, lcm(L, z), p+1, k-1)
  74. end
  75. end
  76. end
  77. end
  78. F((BIG ? big"1" : 1), (BIG ? big"1" : 1), 2, k)
  79. end
  80. # Generate all the 6-Fermat pseudoprimes to base 2 in the range [100, 10^9]
  81. k = 6
  82. base = 2
  83. from = 100
  84. upto = 10^9
  85. arr = []
  86. squarefree_fermat_pseudoprimes_in_range(from, upto, k, base, function (n) push!(arr, n) end)
  87. sort!(arr)
  88. println(arr)