upper-bounds.pl 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. #!/usr/bin/perl
  2. # Smallest base-2 even pseudoprime (A006935) with exactly n prime factors, or 0 if no such number exists.
  3. # https://oeis.org/A270973
  4. # Known terms:
  5. # 161038, 215326, 209665666, 4783964626, 1656670046626, 1202870727916606
  6. # New terms:
  7. # a(9) = 52034993731418446
  8. # a(10) = 1944276680165220226
  9. # a(11) = 1877970990972707747326
  10. # a(12) = 1959543009026971258888306
  11. # a(13) = 102066199849378101848830606
  12. # Lower-bounds:
  13. # a(12) > 1397223754507606670514567
  14. # a(13) > 41815837812760091234926591
  15. # Upper-bounds:
  16. # a(12) <= 4766466010613887747468126
  17. # a(13) <= 102066199849378101848830606 < 264142222928897318700339646 < 1725479220139163740111585726
  18. # a(14) <= 830980424310040957294391274226 < 866600672627375092851058279666 < 1983132824527094983631028842626 < 2091681251598900871449480765826
  19. # a(15) <= 108084747660126676387861365978526 < 1842817788240578750872074253088926
  20. # a(16) <= 37216678196711615864826518577193726 < 37843891059100280944238655216335326
  21. # a(17) <= 14165393571115472875428298421578481266
  22. # a(18) <= 29754760201190206689697709808980720234206
  23. # a(19) <= 83297267513662079869290363590704788631466446
  24. # a(20) <= 38869290181330286854504265440667019466376871106
  25. use 5.036;
  26. use ntheory qw(:all);
  27. use Math::GMPz;
  28. sub squarefree_fermat_pseudoprimes_in_range ($A, $B, $k, $base, $callback) {
  29. $A = vecmax($A, pn_primorial($k));
  30. $A = Math::GMPz->new("$A");
  31. my $u = Math::GMPz::Rmpz_init();
  32. my $v = Math::GMPz::Rmpz_init();
  33. sub ($m, $L, $lo, $k) {
  34. Math::GMPz::Rmpz_tdiv_q($u, $B, $m);
  35. Math::GMPz::Rmpz_root($u, $u, $k);
  36. my $hi = Math::GMPz::Rmpz_get_ui($u);
  37. if ($lo > $hi) {
  38. return;
  39. }
  40. if ($k == 1) {
  41. Math::GMPz::Rmpz_cdiv_q($u, $A, $m);
  42. if (Math::GMPz::Rmpz_fits_ulong_p($u)) {
  43. $lo = vecmax($lo, Math::GMPz::Rmpz_get_ui($u));
  44. }
  45. elsif (Math::GMPz::Rmpz_cmp_ui($u, $lo) > 0) {
  46. if (Math::GMPz::Rmpz_cmp_ui($u, $hi) > 0) {
  47. return;
  48. }
  49. $lo = Math::GMPz::Rmpz_get_ui($u);
  50. }
  51. if ($lo > $hi) {
  52. return;
  53. }
  54. Math::GMPz::Rmpz_invert($v, $m, $L);
  55. if (Math::GMPz::Rmpz_cmp_ui($v, $hi) > 0) {
  56. return;
  57. }
  58. if (Math::GMPz::Rmpz_fits_ulong_p($L)) {
  59. $L = Math::GMPz::Rmpz_get_ui($L);
  60. }
  61. my $t = Math::GMPz::Rmpz_get_ui($v);
  62. $t > $hi && return;
  63. $t += $L while ($t < $lo);
  64. for (my $p = $t ; $p <= $hi ; $p += $L) {
  65. if (is_prime($p)) {
  66. Math::GMPz::Rmpz_mul_ui($v, $m, $p);
  67. Math::GMPz::Rmpz_sub_ui($u, $v, 1);
  68. if (Math::GMPz::Rmpz_divisible_ui_p($u, znorder($base, $p))) {
  69. my $w = Math::GMPz::Rmpz_init_set($v);
  70. say "Found upper-bound: $w";
  71. $B = $w if ($w < $B);
  72. $callback->($w);
  73. }
  74. }
  75. }
  76. return;
  77. }
  78. my $z = Math::GMPz::Rmpz_init();
  79. my $lcm = Math::GMPz::Rmpz_init();
  80. foreach my $p (@{primes($lo, $hi)}) {
  81. $base % $p == 0 and next;
  82. is_smooth($p-1, 17) || next;
  83. my $o = znorder($base, $p);
  84. Math::GMPz::Rmpz_gcd_ui($Math::GMPz::NULL, $m, $o) == 1 or next;
  85. Math::GMPz::Rmpz_lcm_ui($lcm, $L, $o);
  86. Math::GMPz::Rmpz_mul_ui($z, $m, $p);
  87. __SUB__->($z, $lcm, $p+1, $k-1);
  88. }
  89. }->(Math::GMPz->new(2), Math::GMPz->new(1), 3, $k-1);
  90. }
  91. sub a ($n) {
  92. if ($n < 3) {
  93. return;
  94. }
  95. my $x = Math::GMPz->new(pn_primorial($n));
  96. #my $x = Math::GMPz->new("698611877253803335257283");
  97. my $y = 3 * $x;
  98. #$x = Math::GMPz->new("8659342796477276452489576392442249215");
  99. #$y = Math::GMPz->new("14165393571115472875428298421578481266");
  100. while (1) {
  101. say("[$n] Sieving range: [$x, $y]");
  102. my @v;
  103. squarefree_fermat_pseudoprimes_in_range(
  104. $x, $y, $n, 2,
  105. sub ($k) {
  106. push @v, $k;
  107. }
  108. );
  109. @v = sort { $a <=> $b } @v;
  110. if (scalar(@v) > 0) {
  111. return $v[0];
  112. }
  113. $x = $y + 1;
  114. $y = 3 * $x;
  115. }
  116. }
  117. foreach my $n (20) {
  118. say "a($n) <= ", a($n);
  119. }