factorize_pseudoprimes.pl 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. #!/usr/bin/perl
  2. # Try to factorize a given list of pseudoprimes.
  3. use 5.020;
  4. use strict;
  5. use warnings;
  6. use Math::GMPz;
  7. use ntheory qw(:all);
  8. use Math::Prime::Util::GMP;
  9. use experimental qw(signatures);
  10. eval { require GDBM_File };
  11. my $cache_db = "cache/factors.db";
  12. my %seen;
  13. my @numbers;
  14. while (<>) {
  15. next if /^\h*#/;
  16. /\S/ or next;
  17. my $n = (split(' ', $_))[-1];
  18. $n || next;
  19. if (!$seen{$n}++) {
  20. push @numbers, $n;
  21. }
  22. }
  23. @numbers || die "Found no valid numbers to factors!";
  24. dbmopen(my %db, $cache_db, 0444)
  25. or die "Can't create/access database <<$cache_db>>: $!";
  26. my @numbers_to_factor;
  27. foreach my $n (@numbers) {
  28. my $z = Math::GMPz->new($n);
  29. if (exists $db{$z}) {
  30. my $value = $db{$z};
  31. say "$n = ", join(" * ", split(' ', $value));
  32. next;
  33. }
  34. if (is_prime($z)) {
  35. say "$n = $z\n";
  36. next;
  37. }
  38. if ($z <= Math::GMPz->new(2)**64) {
  39. say "$n = ", join(" * ", factor($z));
  40. next;
  41. }
  42. push @numbers_to_factor, [$n, $z];
  43. }
  44. @numbers_to_factor || do {
  45. say ":: Done!";
  46. exit;
  47. };
  48. my %factors;
  49. my $g = Math::GMPz::Rmpz_init();
  50. my $t = Math::GMPz::Rmpz_init();
  51. while (my ($key, $value) = each %db) {
  52. length($key) >= 40 or next;
  53. Math::GMPz::Rmpz_set_str($t, $key, 10);
  54. foreach my $pair (@numbers_to_factor) {
  55. my ($n, $z) = @$pair;
  56. Math::GMPz::Rmpz_gcd($g, $t, $z);
  57. if (Math::GMPz::Rmpz_cmp_ui($g, 1) > 0) {
  58. my @list = map { Math::GMPz::Rmpz_init_set_str($_, 10) } split(' ', $value);
  59. foreach my $p (@list) {
  60. while (Math::GMPz::Rmpz_divisible_p($z, $p)) {
  61. Math::GMPz::Rmpz_divexact($z, $z, $p);
  62. push @{$factors{$n}}, $p;
  63. say "$n = ", join(" * ", @{$factors{$n}});
  64. }
  65. }
  66. }
  67. }
  68. }
  69. dbmclose(%db);
  70. say "\nFinal results:";
  71. foreach my $n (keys %factors) {
  72. say "$n = ", join(' * ', @{$factors{$n}});
  73. }