order_factorization_method.pl 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. #!/usr/bin/perl
  2. # Author: Daniel "Trizen" Șuteu
  3. # Date: 02 August 2020
  4. # Edit: 07 January 2021
  5. # https://github.com/trizen
  6. # A new factorization method for numbers that have all prime factors close to each other.
  7. # Inpsired by Fermat's Little Theorem (FLT).
  8. use 5.020;
  9. use warnings;
  10. use experimental qw(signatures);
  11. use Math::GMPz;
  12. sub FLT_find_factor ($n, $base = 2, $reps = 1e5) {
  13. $n = Math::GMPz->new("$n");
  14. state $z = Math::GMPz::Rmpz_init_nobless();
  15. state $t = Math::GMPz::Rmpz_init_nobless();
  16. my $g = Math::GMPz::Rmpz_init();
  17. Math::GMPz::Rmpz_set_ui($t, $base);
  18. Math::GMPz::Rmpz_set_ui($z, $base);
  19. Math::GMPz::Rmpz_powm($z, $z, $n, $n);
  20. # Cannot factor Fermat pseudoprimes
  21. if (Math::GMPz::Rmpz_cmp_ui($z, $base) == 0) {
  22. return undef;
  23. }
  24. my $multiplier = $base * $base;
  25. for (my $k = 1 ; $k <= $reps ; ++$k) {
  26. Math::GMPz::Rmpz_mul_ui($t, $t, $multiplier);
  27. Math::GMPz::Rmpz_mod($t, $t, $n) if ($k % 10 == 0);
  28. Math::GMPz::Rmpz_sub($g, $z, $t);
  29. Math::GMPz::Rmpz_gcd($g, $g, $n);
  30. if (Math::GMPz::Rmpz_cmp_ui($g, 1) > 0) {
  31. return undef if (Math::GMPz::Rmpz_cmp($g, $n) == 0);
  32. return $g;
  33. }
  34. }
  35. return undef;
  36. }
  37. say FLT_find_factor("1759590140239532167230871849749630652332178307219845847129"); #=> 12072684186515582507
  38. say FLT_find_factor("28168370236334094367936640078057043313881469151722840306493"); #=> 30426633744568826749
  39. say FLT_find_factor("97967651586822913179896725042136997967830602144506842054615710025444417607092711829309187"); #=> 86762184769343281845479348731
  40. say FLT_find_factor("1129151505892449502375764445221583755878554451745780900429977", 3); #=> 867621847693432818454793487397