generate_pseudoprimes_from_factors.pl 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  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 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. dbmopen(my %db, $cache_db, 0444)
  13. or die "Can't create/access database <<$cache_db>>: $!";
  14. warn ":: Sieving primes...\n";
  15. my @list;
  16. my %seen;
  17. while (my ($key, $value) = each %db) {
  18. my @factors = split(' ', $value);
  19. push @list, grep { !$seen{$_}++ } grep {
  20. #length($_) < 30
  21. ($_ > 1e8) and ($_ < 1e15)
  22. #and modint($_, 8) == 3
  23. #and modint($_, 8) == 1
  24. and kronecker(5, $_) == -1
  25. #and is_square_free(subint($_, 1) >> 1)
  26. #and is_square_free(addint($_, 1) >> 2)
  27. #and (vecall { modint($_, 4) == 1 } factor(subint($_, 1) >> 1))
  28. #and (vecall { modint($_, 4) == 3 } factor(addint($_, 1) >> 2))
  29. } @factors;
  30. last if (@list > 2e6);
  31. }
  32. dbmclose(%db);
  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 ($k == -1) {
  40. if (1) {
  41. foreach my $d (divisors(subint($p, $k))) {
  42. if (lucasumod(1, -1, $d, $p) == 0) {
  43. push @{$common_divisors{$d}}, $p;
  44. }
  45. #if (($k == 1) ? (powmod(5, $d, $p) == 1) : (powmod(5, $d, $p) == $d-1)) {
  46. # push @{$common_divisors{$d}}, $p;
  47. #}
  48. }
  49. }
  50. }
  51. foreach my $arr (values %common_divisors) {
  52. my $l = $#{$arr} + 1;
  53. for (my $k = 3 ; $k <= $l ; $k += 2) {
  54. forcomb {
  55. my $n = Math::Prime::Util::GMP::vecprod(@{$arr}[@_]);
  56. $callback->($n);
  57. }
  58. $l, $k;
  59. }
  60. }
  61. }
  62. sub is_fibonacci_pseudoprime ($n) {
  63. Math::Prime::Util::GMP::lucasumod(1, -1, $n, $n) eq Math::Prime::Util::GMP::subint($n, 1);
  64. }
  65. fibonacci_pseudoprimes(
  66. \@list,
  67. sub ($n) {
  68. if (is_fibonacci_pseudoprime($n)) {
  69. say $n;
  70. warn "Fib: $n\n";
  71. if (is_euler_pseudoprime($n, 5)) {
  72. die "Found counter-example: $n";
  73. }
  74. if (kronecker(5, $n) == -1) {
  75. if (is_pseudoprime($n, 2)) {
  76. die "Found a special pseudoprime: $n";
  77. }
  78. }
  79. }
  80. }
  81. );