tomasz_A309285_db.pl 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. #!/usr/bin/perl
  2. # a(n) is the smallest odd composite k such that prime(n)^((k-1)/2) == 1 (mod k) and q^((k-1)/2) == -1 (mod k) for every prime q < prime(n).
  3. # https://oeis.org/A309285
  4. # Known terms:
  5. # 341, 29341, 48354810571, 493813961816587, 32398013051587
  6. # Upper-bounds:
  7. # a(6) <= 35141256146761030267
  8. # a(7) <= 4951782572086917319747
  9. use 5.020;
  10. use strict;
  11. use warnings;
  12. use Math::GMPz;
  13. use ntheory qw(:all);
  14. use Math::Prime::Util::GMP;
  15. use experimental qw(signatures);
  16. eval { require GDBM_File };
  17. my $cache_db = "cache/factors.db";
  18. dbmopen(my %db, $cache_db, 0444)
  19. or die "Can't create/access database <<$cache_db>>: $!";
  20. my $z = Math::GMPz::Rmpz_init();
  21. my $t = Math::GMPz::Rmpz_init();
  22. my $u = Math::GMPz::Rmpz_init();
  23. my $ONE = Math::GMPz::Rmpz_init_set_ui(1);
  24. sub check {
  25. my ($n) = @_;
  26. my $p = 2;
  27. my $count = 0;
  28. Math::GMPz::Rmpz_sub_ui($t, $n, 1);
  29. Math::GMPz::Rmpz_set($u, $t);
  30. Math::GMPz::Rmpz_div_2exp($t, $t, 1);
  31. while (1) {
  32. Math::GMPz::Rmpz_set_ui($z, $p);
  33. Math::GMPz::Rmpz_powm($z, $z, $t, $n);
  34. if (Math::GMPz::Rmpz_congruent_p($z, $u, $n)) {
  35. ++$count;
  36. }
  37. elsif (Math::GMPz::Rmpz_congruent_p($z, $ONE, $n)) {
  38. return $count + 1;
  39. }
  40. else {
  41. return undef;
  42. }
  43. $p = next_prime($p);
  44. }
  45. return $count;
  46. }
  47. my @tests = qw(341 29341 48354810571 493813961816587 32398013051587 35141256146761030267 4951782572086917319747);
  48. foreach my $i (0 .. $#tests) {
  49. check(Math::GMPz->new($tests[$i])) == ($i + 1)
  50. or die "Error for $tests[$i]";
  51. }
  52. my @table = ();
  53. my $w = Math::GMPz::Rmpz_init();
  54. while (my ($n, $value) = each %db) {
  55. Math::Prime::Util::GMP::is_euler_pseudoprime($n, 2) || next;
  56. Math::GMPz::Rmpz_set_str($w, $n, 10);
  57. my $v = check($w) // next;
  58. if (defined($table[$v])) {
  59. next if ($table[$v] < $w);
  60. }
  61. $table[$v] = Math::GMPz->new($n);
  62. say "a($v) <= $n";
  63. }
  64. dbmclose(%db);
  65. say "\nFinal results:\n";
  66. foreach my $i (0 .. $#table) {
  67. if (defined($table[$i])) {
  68. printf("a(%2d) <= %s\n", $i, $table[$i]);
  69. }
  70. }
  71. __END__
  72. a( 1) <= 18446744073709551617
  73. a( 2) <= 18456397176186985861
  74. a( 3) <= 18512248848925882051
  75. a( 4) <= 137384819210890995547
  76. a( 5) <= 28000000000613222386069826859187
  77. a( 6) <= 35141256146761030267
  78. a( 7) <= 4951782572086917319747
  79. a(11) <= 11968794224604718293549908104759518204343930652759288592987578098131927050572705181539873293848476235393230314654912729920657864630317971562727057595285667
  80. a(12) <= 16293065699588634810831933763781141498750450660078823067
  81. a(17) <= 7901877332421117604277233556001994548174031728058485631926375876865078028180049751981627864304181541061183590498201673009039329539171539230651776950727307