super_poulet_pseudoprimes.pl 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  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 ntheory qw(forcomb forprimes divisors powmod znorder);
  8. use Math::Prime::Util::GMP;
  9. sub super_poulet_pseudoprimes ($limit, $callback) {
  10. my %common_divisors;
  11. warn ":: Sieving...\n";
  12. forprimes {
  13. my $p = $_;
  14. #if ($p % 24 == 1 or $p % 24 == 13) {
  15. #if ($p % 24 == 1) {
  16. my $z = znorder(2, $p);
  17. if (2*$z < $limit) {
  18. foreach my $d (divisors($p - 1)) {
  19. #if (powmod(2, $d, $p) == 1) {
  20. if ($d % $z == 0) {
  21. if ($p > 1e8) {
  22. if (exists $common_divisors{$d}) {
  23. push @{$common_divisors{$d}}, $p;
  24. }
  25. }
  26. else {
  27. push @{$common_divisors{$d}}, $p;
  28. }
  29. }
  30. #}
  31. }
  32. }
  33. } 3, $limit;
  34. warn ":: Creating combinations...\n";
  35. #foreach my $arr (values %common_divisors) {
  36. while (my ($key, $arr) = each %common_divisors) {
  37. my $nf = 5; # minimum number of prime factors
  38. #next if @$arr < $nf;
  39. my $l = scalar(@$arr);
  40. foreach my $k ($nf .. $l) {
  41. forcomb {
  42. my $n = Math::Prime::Util::GMP::vecprod(@{$arr}[@_]);
  43. $callback->($n);
  44. } $l, $k;
  45. }
  46. }
  47. }
  48. open my $fh, '>', 'super_poulet_numbers.txt';
  49. #$fh->autoflush(1);
  50. super_poulet_pseudoprimes(
  51. 2e9, # limit of the largest prime factor
  52. sub ($n) {
  53. if ($n > ~0) { # report only numbers greater than 2^64
  54. #warn "$n\n";
  55. say $fh $n;
  56. }
  57. }
  58. );
  59. close $fh;