super_poulet_pseudoprimes_from_prime_file.pl 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. #!/usr/bin/perl
  2. # Generate Super-Poulet pseudoprimes to base 2, using prime factors bellow a certain limit.
  3. use 5.020;
  4. use warnings;
  5. use experimental qw(signatures);
  6. #use IO::Handle;
  7. use List::Util qw(uniq);
  8. use ntheory qw(:all);
  9. use Math::Prime::Util::GMP;
  10. sub super_poulet_pseudoprimes ($primes, $callback) {
  11. my %common_divisors;
  12. warn ":: Sieving...\n";
  13. foreach my $p (@$primes) {
  14. $p < ~0 or next; # ignore too large primes
  15. #if ($p % 24 == 1 or $p % 24 == 13) {
  16. # if ($p % 24 == 1 or $p % 24 == 13) {
  17. my $z = znorder(2, $p);
  18. # if (2*$z < $limit) {
  19. foreach my $d (divisors($p - 1)) {
  20. #if (powmod(2, $d, $p) == 1) {
  21. if ($d % $z == 0) {
  22. #if ($p > 1e8) {
  23. # if (exists $common_divisors{$d}) {
  24. # push @{$common_divisors{$d}}, $p;
  25. # }
  26. #}
  27. #else {
  28. #my $from = int($limit/$d);
  29. #foreach my $k ($from .. $from + 100) {
  30. #foreach my $k(map{$_->[0]**$_->[1]}factor_exp($p-1)) {
  31. #if (exists($common_divisors{$d}) and scalar(@{$common_divisors{$d}}) >= 5) {
  32. if (exists $common_divisors{$d}) {
  33. foreach my $k (divisors($d)) {
  34. #for (my $k = $from;
  35. #foreach my $k (uniq(factor($p+1))) {
  36. #foreach my $j (3..10) {
  37. my $m = addint($k, int rand 100);
  38. if (($d % 2) * ($m % 2) != 0) {
  39. $m = addint($m, 1);
  40. }
  41. my $q = addint(mulint($d,$m),1);
  42. #~ if (is_prime($q) and $d % znorder(2, $q) == 0) {
  43. #~ push @{$common_divisors{$d}}, $q;
  44. #~ }
  45. #if ((($q % 24 == 1) or ($q % 24 == 13)) and is_prime($q)) {
  46. if (is_prime($q)) {
  47. my $z = znorder(2, $q);
  48. #2*$z < $limit or next;
  49. foreach my $d(divisors(subint($q,1))) {
  50. if (modint($d, $z) == 0 and exists $common_divisors{$d}) {
  51. push @{$common_divisors{$d}}, $q;
  52. }
  53. }
  54. }
  55. }
  56. }
  57. #}
  58. # }
  59. push @{$common_divisors{$d}}, $p;
  60. #}
  61. }
  62. # }
  63. }
  64. # }
  65. # }
  66. }
  67. warn ":: Creating combinations...\n";
  68. #foreach my $arr (values %common_divisors) {
  69. while (my ($key, $arr) = each %common_divisors) {
  70. my $nf = 3; # minimum number of prime factors
  71. $arr = [uniq(@$arr)];
  72. next if @$arr < $nf;
  73. my $l = scalar(@$arr);
  74. #foreach my $k ($nf .. $l) {
  75. for(my $k = $nf; $k <= $l; $k += 2) {
  76. forcomb {
  77. my $n = Math::Prime::Util::GMP::vecprod(@{$arr}[@_]);
  78. $callback->($n);
  79. } $l, $k;
  80. }
  81. }
  82. }
  83. my @primes;
  84. while (<>) {
  85. next if /^#/;
  86. /\d/ or next;
  87. chomp;
  88. push @primes, $_;
  89. }
  90. open my $fh, '>', 'super_poulet_numbers.txt';
  91. #$fh->autoflush(1);
  92. super_poulet_pseudoprimes(
  93. \@primes,
  94. sub ($n) {
  95. if ($n > ~0) { # report only numbers greater than 2^64
  96. warn "$n\n";
  97. say $fh $n;
  98. }
  99. }
  100. );
  101. close $fh;