tomasz_A309284_db.pl 2.6 KB

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