fermat_superpseudoprimes_from_prime_factors.pl 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. #!/usr/bin/perl
  2. # Author: Daniel "Trizen" Șuteu
  3. # Date: 28 January 2019
  4. # https://github.com/trizen
  5. # A new algorithm for generating Fermat superpseudoprimes to any given base.
  6. # See also:
  7. # https://trizenx.blogspot.com/2020/08/pseudoprimes-construction-methods-and.html
  8. use 5.020;
  9. use warnings;
  10. use experimental qw(signatures);
  11. use Math::AnyNum qw(prod);
  12. use ntheory qw(:all);
  13. sub fermat_superpseudoprimes ($base, $callback) {
  14. my %common_divisors;
  15. #for (my $p = 2; $p <= $prime_limit; $p = next_prime($p)) {
  16. say "# :: Sieving...";
  17. my %seen_p;
  18. while (<>) {
  19. my $p = (split(' ', $_))[-1];
  20. $p || next;
  21. next if /^#/;
  22. $p =~ /^[0-9]+\z/ or next;
  23. $p > 2 or next;
  24. is_prime($p) || next;
  25. next if $seen_p{$p}++;
  26. my $z = znorder($base, $p) // next;
  27. $z < ~0 or next;
  28. #push @{$common_divisors{$z}}, $p; # overpseudoprimes
  29. foreach my $d (divisors(subint($p, 1))) {
  30. #if ($d % $z == 0) {
  31. if ($d >= $z and modint($d, $z) == 0) {
  32. push @{$common_divisors{$d}}, $p;
  33. }
  34. }
  35. }
  36. say "# :: Creating combinations...";
  37. my %seen;
  38. foreach my $arr (values %common_divisors) {
  39. my $l = scalar(@$arr);
  40. foreach my $k (2 .. $l) {
  41. forcomb {
  42. my $n = Math::Prime::Util::GMP::vecprod(@{$arr}[@_]);
  43. $callback->($n) if !$seen{$n}++;
  44. } $l, $k;
  45. }
  46. }
  47. }
  48. my $base = 2;
  49. fermat_superpseudoprimes(
  50. $base, # base
  51. sub ($n) {
  52. Math::Prime::Util::GMP::is_pseudoprime($n, $base) || die "error for n=$n";
  53. if ($n > ~0) {
  54. say $n;
  55. }
  56. }
  57. );