multiplicative_order.jl 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. #!/usr/bin/julia
  2. # Trizen
  3. # 15 November 2021
  4. # https://github.com/trizen
  5. # Compute the multiplicative order of `a` modulo `n`: znorder(a, n).
  6. # This is the smallest positive integer k such that a^k == 1 (mod n).
  7. using Primes
  8. function divisors(n)
  9. d = Int64[1]
  10. for (p,e) in factor(n)
  11. t = Int64[]
  12. r = 1
  13. for i in 1:e
  14. r *= p
  15. for u in d
  16. push!(t, u*r)
  17. end
  18. end
  19. append!(d, t)
  20. end
  21. return sort(d)
  22. end
  23. function znorder(a, n)
  24. if isprime(n)
  25. for d in divisors(n-1)
  26. if (powermod(a, d, n) == 1)
  27. return d
  28. end
  29. end
  30. end
  31. f = factor(n)
  32. if (length(f) == 1) # is prime power
  33. p = first(first(f))
  34. z = znorder(a, p)
  35. while (powermod(a, z, n) != 1)
  36. z *= p
  37. end
  38. return z
  39. end
  40. pp_orders = Int64[]
  41. for (p,e) in f
  42. push!(pp_orders, znorder(a, p^e))
  43. end
  44. return lcm(pp_orders)
  45. end
  46. isequal(znorder(97, factorial(14)), 25920) || print("error")
  47. isequal(znorder(53, factorial(15)), 2419200) || print("error")
  48. isequal(znorder(37, factorial(16)), 116121600) || print("error")
  49. isequal(znorder(31, factorial(17)), 6220800) || print("error")
  50. isequal(znorder(89, factorial(18)), 1045094400) || print("error")
  51. isequal(znorder(101,factorial(19)), 1254113280) || print("error")
  52. isequal(znorder(97, factorial(20)), 2239488000) || print("error")
  53. println(znorder(2, 341)) #> 10
  54. println(znorder(97, 5040)) #> 12