congruence_of_powers_factorization_method.sf 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. #!/usr/bin/ruby
  2. # Daniel "Trizen" Șuteu
  3. # Date: 05 July 2019
  4. # https://github.com/trizen
  5. # A simple factorization method, based on congruences of powers.
  6. # Given a composite integer `n`, if we find:
  7. #
  8. # a^k == b^k (mod n)
  9. #
  10. # for some k >= 2, then gcd(a-b, n) may be a non-trivial factor of n.
  11. # See also:
  12. # https://trizenx.blogspot.com/2019/08/special-purpose-factorization-algorithms.html
  13. define MIN_FACTOR = 1e6 # ignore small factors
  14. func cgpow_factor (n) {
  15. var params = []
  16. var orig = n
  17. var range = (2 .. min(n.ilog2, 15) -> flip)
  18. func process_congruence(root, e) {
  19. for j in (-1, 0, 1) {
  20. var k = (root + j)
  21. var u = powmod(k, e, n)
  22. for z in (u, n-u) {
  23. if (is_power(z)) {
  24. var t = perfect_power(z)
  25. var r1 = z.iroot(t)
  26. var r2 = z.iroot(e)
  27. params << [r1, t, k, e]
  28. params << [r2, e, k, e]
  29. }
  30. }
  31. }
  32. }
  33. range.each {|e|
  34. var root = n.iroot(e)
  35. process_congruence(root, e)
  36. }
  37. range.each {|root|
  38. var e = n.ilog(root)
  39. process_congruence(root, e)
  40. }
  41. var f = func (r, e1, k, e2) {
  42. var factors = Set()
  43. var d1 = e1.divisors.map {|d| r**d }
  44. var d2 = e2.divisors.map {|d| k**d }
  45. for x in (d1), y in (d2) {
  46. for j in (-1, 1) {
  47. var t = (x - j*y)
  48. var g = gcd(t, n)
  49. if (g>MIN_FACTOR && g<n) {
  50. factors << g
  51. }
  52. }
  53. }
  54. factors.to_a
  55. }
  56. var factors = []
  57. var divisors = params.uniq.map { f(_...) }.flat.sort.uniq
  58. divisors.each {|d|
  59. var g = gcd(n, d)
  60. if (g>MIN_FACTOR && g<n) {
  61. while (n%g == 0) {
  62. n /= g
  63. factors << g
  64. }
  65. }
  66. }
  67. factors << (orig / factors.prod)
  68. factors.sort
  69. }
  70. if (ARGV) {
  71. say cgpow_factor(Num(ARGV[0]))
  72. return 1
  73. }
  74. say cgpow_factor(ipow(2, 256) - 1)
  75. say cgpow_factor(ipow(10, 120) + 1)
  76. say cgpow_factor(ipow(10, 120) - 1)
  77. say cgpow_factor(ipow(10, 120) - 25)
  78. say cgpow_factor(ipow(10, 105) - 1)
  79. say cgpow_factor(ipow(10, 105) + 1)
  80. say cgpow_factor(ipow(10, 120) - ipow(2134, 2))
  81. say cgpow_factor((ipow(2, 128) - 1) * (ipow(2, 256) - 1))
  82. say cgpow_factor(ipow(ipow(4, 64) - 1, 3) - 1)
  83. say cgpow_factor((2**128 - 1) * (3**128 - 1))
  84. say cgpow_factor((5**48 + 1) * (3**120 + 1))
  85. say cgpow_factor((5**48 + 1) * (3**120 - 1))
  86. say cgpow_factor((5**48 - 1) * (3**120 + 1))
  87. say cgpow_factor((45**120 + 35**420))
  88. __END__
  89. [4294967295, 4294967297, 18446744073709551617, 340282366920938463463374607431768211457]
  90. [100000001, 9999999900000001, 99999999000000009999999900000001, 10000000099999999999999989999999899999999000000000000000100000001]
  91. [1000001, 1202981, 1587789, 2906161, 99009901, 1000000000001, 10989010989011, 165573604901641, 9999000099990001, 100009999999899989999000000010001]
  92. [999999999999999999999999999999999999999999999999999999999995, 1000000000000000000000000000000000000000000000000000000000005]
  93. [1111111, 8392599, 119152601, 900900990991, 900009090090909909099991, 1109988789001111109989898989900111110998878900111]
  94. [1478477, 4734601891, 156985855573, 999990000099999000009999900001, 910009191000909089989898989899909091000919100091]
  95. [999999999999999999999999999999999999999999999999999999997866, 1000000000000000000000000000000000000000000000000000000002134]
  96. [4294836225, 4294967297, 4294967297, 4295098369, 18446744073709551617, 18446744073709551617, 340282366920938463463374607431768211457]
  97. [340282366920938463463374607431768211454, 115792089237316195423570985008687907852929702298719625575994209400481361428481]
  98. [41, 1048560, 1979408, 5570645, 6700417, 43046722, 926510094425921, 18446744073709551617, 1716841910146256242328924544641]
  99. [1273028, 43040161, 76293945313, 1852737802355521, 240031591394168814433, 3434207167913380326433387290241]
  100. [1013824, 1801025, 2828617, 16068403, 47763361, 1743392201, 76293945313, 50446744628921761, 240031591394168814433]
  101. [1889856, 3390842, 43040161, 61132969, 1852737802355521, 59509277587890001, 3434207167913380326433387290241]