generate_pseudoprimes_from_factors_cached.pl 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. #!/usr/bin/perl
  2. # Generate pseudoprimes using the prime factors of other pseudoprimes.
  3. use 5.020;
  4. use strict;
  5. use warnings;
  6. use Storable;
  7. use ntheory qw(:all);
  8. use Math::Prime::Util::GMP;
  9. use experimental qw(signatures);
  10. my $storable_file = "cache/factors-carmichael.storable";
  11. #my $storable_file = "cache/factors-superpsp.storable";
  12. #my $storable_file = "cache/factors-fermat.storable";
  13. #my $storable_file = "cache/factors-lucas-carmichael.storable";
  14. my $carmichael = retrieve($storable_file);
  15. warn ":: Sieving primes...\n";
  16. my @list;
  17. my %seen;
  18. while (my ($n, $value) = each %$carmichael) {
  19. my $len = length($n);
  20. # next if $len > 100;
  21. my @factors = split(' ', $value);
  22. push @list, grep { !$seen{$_}++ } grep {
  23. length($_) < 40
  24. and modint($_, 8) == 3
  25. and kronecker(5, $_) == -1
  26. #and is_square_free(subint($_, 1) >> 1)
  27. #and is_square_free(addint($_, 1) >> 2)
  28. #and (vecall { modint($_, 4) == 1 } factor(subint($_, 1) >> 1))
  29. #and (vecall { modint($_, 4) == 3 } factor(addint($_, 1) >> 2))
  30. } @factors;
  31. last if (@list > 1e6);
  32. }
  33. warn ":: Found ", scalar(@list), " primes...\n";
  34. warn ":: Generating fibonacci pseudoprimes...\n";
  35. sub fibonacci_pseudoprimes ($list, $callback) {
  36. my %common_divisors;
  37. foreach my $p (@$list) {
  38. my $k = kronecker(5, $p);
  39. if (1) {
  40. foreach my $d (divisors(subint($p, $k))) {
  41. if (lucasumod(1, -1, $d, $p) == 0) {
  42. push @{$common_divisors{$d}}, $p;
  43. }
  44. #if (($k == 1) ? (powmod(5, $d, $p) == 1) : (powmod(5, $d, $p) == $d-1)) {
  45. # push @{$common_divisors{$d}}, $p;
  46. #}
  47. }
  48. }
  49. }
  50. foreach my $arr (values %common_divisors) {
  51. my $l = $#{$arr} + 1;
  52. for (my $k = 3 ; $k <= $l ; $k += 2) {
  53. forcomb {
  54. my $n = Math::Prime::Util::GMP::vecprod(@{$arr}[@_]);
  55. $callback->($n);
  56. }
  57. $l, $k;
  58. }
  59. }
  60. }
  61. sub is_fibonacci_pseudoprime ($n) {
  62. Math::Prime::Util::GMP::lucasumod(1, -1, $n, $n) eq Math::Prime::Util::GMP::subint($n, 1);
  63. }
  64. fibonacci_pseudoprimes(
  65. \@list,
  66. sub ($n) {
  67. if (is_fibonacci_pseudoprime($n)) {
  68. say $n;
  69. warn "Fib: $n\n";
  70. if (is_euler_pseudoprime($n, 5)) {
  71. die "Found counter-example: $n";
  72. }
  73. if (kronecker(5, $n) == -1) {
  74. if (is_pseudoprime($n, 2)) {
  75. die "Found a special pseudoprime: $n";
  76. }
  77. }
  78. }
  79. }
  80. );