lucas-miller_factorization_method.pl 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. #!/usr/bin/perl
  2. # Daniel "Trizen" Șuteu
  3. # Date: 07 January 2020
  4. # https://github.com/trizen
  5. # A simple factorization method, using the Lucas `U_n(P,Q)` sequences.
  6. # Inspired by the Miller-Rabin factorization method.
  7. # Works best on Lucas pseudoprimes.
  8. # See also:
  9. # https://en.wikipedia.org/wiki/Lucas_pseudoprime
  10. # https://en.wikipedia.org/wiki/Miller-Rabin_primality_test
  11. use 5.020;
  12. use warnings;
  13. use Math::GMPz;
  14. use ntheory qw(:all);
  15. use experimental qw(signatures);
  16. sub lucas_miller_factor ($n, $j = 1, $k = 100) {
  17. if (ref($n) ne 'Math::GMPz') {
  18. $n = Math::GMPz->new("$n");
  19. }
  20. my $D = $n + $j;
  21. my $s = valuation($D, 2);
  22. my $r = $s - 1;
  23. my $d = $D >> $s;
  24. foreach my $i (1 .. $k) {
  25. my $P = vecmin(1 + int(rand(1e6)), urandomm($n));
  26. my $Q = vecmin(1 + int(rand(1e6)), urandomm($n));
  27. $Q *= -1 if (rand(1) < 0.5);
  28. next if is_square($P * $P - 4 * $Q);
  29. my ($U, $V, $T) = lucas_sequence($n, $P, $Q, $d);
  30. foreach my $z (0 .. $r) {
  31. foreach my $g (gcd($U, $n), gcd($V, $n), gcd(subint($V, $P), $n)) {
  32. if ($g > 1 and $g < $n) {
  33. return $g;
  34. }
  35. }
  36. $U = mulmod($U, $V, $n);
  37. $V = mulmod($V, $V, $n);
  38. $V = submod($V, addint($T, $T), $n);
  39. $T = mulmod($T, $T, $n);
  40. }
  41. }
  42. return 1;
  43. }
  44. say lucas_miller_factor("16641689036184776955112478816668559");
  45. say lucas_miller_factor("17350074279723825442829581112345759");
  46. say lucas_miller_factor("61881629277526932459093227009982733523969186747");
  47. say lucas_miller_factor("122738580838512721992324860157572874494433031849", -1);
  48. say lucas_miller_factor("181490268975016506576033519670430436718066889008242598463521");
  49. say lucas_miller_factor("173315617708997561998574166143524347111328490824959334367069087");
  50. say lucas_miller_factor("57981220983721718930050466285761618141354457135475808219583649146881");
  51. say lucas_miller_factor("2425361208749736840354501506901183117777758034612345610725789878400467");
  52. say lucas_miller_factor("131754870930495356465893439278330079857810087607720627102926770417203664110488210785830750894645370240615968198960237761");