carmichael_numbers_in_range.jl 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. #!/usr/bin/julia
  2. # Daniel "Trizen" Șuteu
  3. # Date: 06 September 2022
  4. # Edit: 23 February 2023
  5. # https://github.com/trizen
  6. # Generate all the Carmichael numbers with n prime factors in a given range [a,b]. (not in sorted order)
  7. # See also:
  8. # https://en.wikipedia.org/wiki/Almost_prime
  9. # https://trizenx.blogspot.com/2020/08/pseudoprimes-construction-methods-and.html
  10. # PARI/GP program (in range):
  11. # carmichael(A, B, k) = A=max(A, vecprod(primes(k+1))\2); (f(m, l, p, k, u=0, v=0) = my(list=List()); if(k==1, forprime(p=u, v, my(t=m*p); if((t-1)%l == 0 && (t-1)%(p-1) == 0, listput(list, t))), forprime(q = p, sqrtnint(B\m, k), my(t = m*q); my(L=lcm(l, q-1)); 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, 3, k)));
  12. using Primes
  13. const BIG = false # true to use big integers
  14. function big_prod(arr)
  15. BIG || return prod(arr)
  16. r = big(1)
  17. for n in (arr)
  18. r *= n
  19. end
  20. return r
  21. end
  22. function carmichael_numbers_in_range(A, B, k)
  23. A = max(A, fld(big_prod(primes(prime(k+1))), 2))
  24. # Largest possible prime factor of Carmichael numbers <= B
  25. # Proof: By the Chinese Remainder Theorem, if n is a Carmichael number, then:
  26. # n == p (mod p*(p-1)), where p is a prime factor of n
  27. # therefore `n = p + j*p*(p-1)`, for some j >= 2. (j=1 gives p^2)
  28. # With j=2, we have `2*p^2 - p <= n`, hence `p <= (1 + sqrt(8*n + 1))/4`.
  29. max_p = (1 + isqrt(8*B + 1))>>2
  30. terms = []
  31. F = function(m, L, lo, k)
  32. hi = round(Int64, fld(B, m)^(1/k))
  33. if (lo > hi)
  34. return nothing
  35. end
  36. if (k == 1)
  37. hi = min(hi, max_p)
  38. lo = round(Int64, max(lo, cld(A, m)))
  39. lo > hi && return nothing
  40. t = invmod(m, L)
  41. t > hi && return nothing
  42. if (t < lo)
  43. t += L*cld(lo - t, L)
  44. end
  45. t > hi && return nothing
  46. for p in t:L:hi
  47. if ((m*p - 1) % (p-1) == 0 && isprime(p))
  48. push!(terms, m*p)
  49. end
  50. end
  51. return nothing
  52. end
  53. for p in primes(lo, hi)
  54. if (gcd(m, p-1) == 1)
  55. F(m*p, lcm(L, p-1), p+1, k-1)
  56. end
  57. end
  58. end
  59. F((BIG ? big(1) : 1), (BIG ? big(1) : 1), 3, k)
  60. return sort(terms)
  61. end
  62. # Generate all the Carmichael numbers in range [A,B]
  63. function carmichael(A, B)
  64. k = 3
  65. terms = []
  66. while true
  67. # Stop when the lower-bound (`primorial(prime(k+1))/2`) is greater than the upper-limit
  68. if (big_prod(primes(prime(k+1)))/2 > B)
  69. break
  70. end
  71. append!(terms, carmichael_numbers_in_range(A, B, k))
  72. k += 1
  73. end
  74. return sort(terms)
  75. end
  76. println("=> Carmichael numbers <= 10^6:")
  77. println(carmichael(1, 10^6));
  78. # Generate all the 6-Carmichael numbers in the range [100, 10^10]
  79. k = 6
  80. from = 100
  81. upto = 10^10
  82. arr = carmichael_numbers_in_range(from, upto, k)
  83. println("\n=> Carmichael numbers with $k prime factors in range [$from, $upto]:")
  84. println(arr)