chebyshev_factorization_method_mpz.pl 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. #!/usr/bin/perl
  2. # Daniel "Trizen" Șuteu
  3. # Date: 22 June 2020
  4. # https://github.com/trizen
  5. # A simple factorization method, using the Chebyshev T_n(x) polynomials, based on the identity:
  6. # T_{m n}(x) = T_m(T_n(x))
  7. # where:
  8. # T_n(x) = (1/2) * V_n(2x, 1)
  9. # where V_n(P, Q) is the Lucas V sequence.
  10. # See also:
  11. # https://oeis.org/A001075
  12. # https://en.wikipedia.org/wiki/Lucas_sequence
  13. # https://en.wikipedia.org/wiki/Iterated_function
  14. # https://en.wikipedia.org/wiki/Chebyshev_polynomials
  15. use 5.020;
  16. use warnings;
  17. use Math::GMPz;
  18. use ntheory qw(:all);
  19. use experimental qw(signatures);
  20. sub fast_lucasVmod ($P, $n, $m) { # assumes Q = 1
  21. my ($V1, $V2) = (Math::GMPz::Rmpz_init_set_ui(2), Math::GMPz::Rmpz_init_set($P));
  22. foreach my $bit (todigits($n, 2)) {
  23. if ($bit) {
  24. Math::GMPz::Rmpz_mul($V1, $V1, $V2);
  25. Math::GMPz::Rmpz_powm_ui($V2, $V2, 2, $m);
  26. Math::GMPz::Rmpz_sub($V1, $V1, $P);
  27. Math::GMPz::Rmpz_sub_ui($V2, $V2, 2);
  28. Math::GMPz::Rmpz_mod($V1, $V1, $m);
  29. }
  30. else {
  31. Math::GMPz::Rmpz_mul($V2, $V2, $V1);
  32. Math::GMPz::Rmpz_powm_ui($V1, $V1, 2, $m);
  33. Math::GMPz::Rmpz_sub($V2, $V2, $P);
  34. Math::GMPz::Rmpz_sub_ui($V1, $V1, 2);
  35. Math::GMPz::Rmpz_mod($V2, $V2, $m);
  36. }
  37. }
  38. Math::GMPz::Rmpz_mod($V1, $V1, $m);
  39. return $V1;
  40. }
  41. sub chebyshev_factorization ($n, $B, $A = 127) {
  42. # The Chebyshev factorization method, taking
  43. # advantage of the smoothness of p-1 or p+1.
  44. if (ref($n) ne 'Math::GMPz') {
  45. $n = Math::GMPz->new("$n");
  46. }
  47. my $x = Math::GMPz::Rmpz_init_set_ui($A);
  48. my $i = Math::GMPz::Rmpz_init_set_ui(2);
  49. Math::GMPz::Rmpz_invert($i, $i, $n);
  50. my sub chebyshevTmod ($A, $x) {
  51. Math::GMPz::Rmpz_mul_2exp($x, $x, 1);
  52. Math::GMPz::Rmpz_set($x, fast_lucasVmod($x, $A, $n));
  53. Math::GMPz::Rmpz_mul($x, $x, $i);
  54. Math::GMPz::Rmpz_mod($x, $x, $n);
  55. }
  56. my $g = Math::GMPz::Rmpz_init();
  57. my $lnB = log($B);
  58. foreach my $p (@{primes(sqrtint($B))}) {
  59. chebyshevTmod($p**int($lnB / log($p)), $x);
  60. }
  61. my $it = prime_iterator(sqrtint($B) + 1);
  62. for (my $p = $it->() ; $p <= $B ; $p = $it->()) {
  63. chebyshevTmod($p, $x); # T_k(x) (mod n)
  64. Math::GMPz::Rmpz_sub_ui($g, $x, 1);
  65. Math::GMPz::Rmpz_gcd($g, $g, $n);
  66. if (Math::GMPz::Rmpz_cmp_ui($g, 1) > 0) {
  67. return 1 if (Math::GMPz::Rmpz_cmp($g, $n) == 0);
  68. return $g;
  69. }
  70. }
  71. return 1;
  72. }
  73. foreach my $n (
  74. #<<<
  75. Math::GMPz->new("4687127904923490705199145598250386612169614860009202665502614423768156352727760127429892667212102542891417456048601608730032271"),
  76. Math::GMPz->new("2593364104508085171532503084981517253915662037671433715309875378319680421662639847819831785007087909697206133969480076353307875655764139224094652151"),
  77. Math::GMPz->new("850794313761232105411847937800407457007819033797145693534409492587965757152430334305470463047097051354064302867874781454865376206137258603646386442018830837206634789761772899105582760694829533973614585552733"),
  78. #>>>
  79. ) {
  80. say "\n:: Factoring: $n";
  81. until (is_prime($n)) {
  82. my $x = int(rand(1e6));
  83. my $p = chebyshev_factorization($n, 500_000, $x);
  84. if ($p > 1) {
  85. say "-> Found factor: $p";
  86. $n /= $p;
  87. }
  88. }
  89. }
  90. __END__
  91. :: Factoring: 4687127904923490705199145598250386612169614860009202665502614423768156352727760127429892667212102542891417456048601608730032271
  92. -> Found factor: 31935028572177122017
  93. -> Found factor: 441214532298715667413
  94. -> Found factor: 515113549791151291993
  95. -> Found factor: 896466791041143516471427
  96. -> Found factor: 12993757635350024510533
  97. :: Factoring: 2593364104508085171532503084981517253915662037671433715309875378319680421662639847819831785007087909697206133969480076353307875655764139224094652151
  98. -> Found factor: 1927199759971282921
  99. -> Found factor: 85625333993726265061
  100. -> Found factor: 2490501032020173490009
  101. -> Found factor: 765996534730183701229
  102. -> Found factor: 58637507352579687279739
  103. -> Found factor: 4393290631695328772611
  104. :: Factoring: 850794313761232105411847937800407457007819033797145693534409492587965757152430334305470463047097051354064302867874781454865376206137258603646386442018830837206634789761772899105582760694829533973614585552733
  105. -> Found factor: 556010720288850785597
  106. -> Found factor: 33311699120128903709
  107. -> Found factor: 341190041753756943379
  108. -> Found factor: 182229202433843943841
  109. -> Found factor: 55554864549706093104640631
  110. -> Found factor: 7672247345452118779313
  111. -> Found factor: 386663601339343857313
  112. -> Found factor: 5658991130760772523
  113. -> Found factor: 1021051300200039481