hcn_between_twin_primes.pl 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. #!/usr/bin/perl
  2. # Daniel "Trizen" Șuteu
  3. # Date: 27 June 2019
  4. # https://github.com/trizen
  5. # Find highly composite numbers H(n) such that H(n)-1 and H(n)+1 are both primes.
  6. # In other words, find highly composite numbers sandwiched between twin primes.
  7. # The sequence of indices of highly composite numbers A002182 which are between a twin prime pair, begins as:
  8. # 3, 4, 5, 9, 11, 12, 20, 28, 30, 84, 108, 118, 143, 149, 208, 330, 362, 1002, 2395, 3160, 10535
  9. # Example:
  10. # H(10535) = A108951(52900585920)
  11. # = 14742217487368791965347653720647452690286549052234444179664342042930370966727413549068727214664401976854238590421417268673037399536054005777393104248210539172848500736334237168727231561710827753972114334247396552090671649834020135652920430241738510495400044737265204738821393451152066370913670083496651044937158497896720493198891148968218874744806522767468280764179516341996273430700779982929787918221844760577694188288275419541410142336911631623319041967633591283303769044016192030492715535641753600000
  12. # where H(10535)-1 and H(10535)+1 are both prime numbers.
  13. # See also:
  14. # https://oeis.org/A321995 -- Indices of highly composite numbers A002182 which are between a twin prime pair.
  15. # https://oeis.org/A108951 -- Completely multiplicative with a(p) = p# for prime p, where x# is the primorial A034386(x).
  16. # https://oeis.org/A002182 -- Highly composite numbers, definition (1): where d(n), the number of divisors of n (A000005), increases to a record.
  17. use 5.020;
  18. use strict;
  19. use warnings;
  20. use Math::GMPz;
  21. use POSIX qw(ULONG_MAX);
  22. use ntheory qw(:all);
  23. use IO::Uncompress::Bunzip2;
  24. use experimental qw(signatures declared_refs);
  25. local $| = 1;
  26. prime_precalc(1e7);
  27. sub primality_pretest ($n) {
  28. # Must be positive
  29. (Math::GMPz::Rmpz_sgn($n) > 0) || return;
  30. # Check for divisibilty by 2
  31. if (Math::GMPz::Rmpz_even_p($n)) {
  32. return (Math::GMPz::Rmpz_cmp_ui($n, 2) == 0);
  33. }
  34. # Return early if n is too small
  35. Math::GMPz::Rmpz_cmp_ui($n, 101) > 0 or return 1;
  36. # Check for very small factors
  37. if (ULONG_MAX >= 18446744073709551615) {
  38. Math::GMPz::Rmpz_gcd_ui($Math::GMPz::NULL, $n, 16294579238595022365) == 1 or return 0;
  39. Math::GMPz::Rmpz_gcd_ui($Math::GMPz::NULL, $n, 7145393598349078859) == 1 or return 0;
  40. }
  41. else {
  42. Math::GMPz::Rmpz_gcd_ui($Math::GMPz::NULL, $n, 3234846615) == 1 or return 0;
  43. }
  44. # Size of n in base-2
  45. my $size = Math::GMPz::Rmpz_sizeinbase($n, 2);
  46. # When n is large enough, try to find a small factor (up to 10^8)
  47. if ($size > 10_000) {
  48. state %cache;
  49. state $g = Math::GMPz::Rmpz_init_nobless();
  50. my @checks = (1e4);
  51. push(@checks, 1e6) if ($size > 15_000);
  52. push(@checks, 1e7) if ($size > 20_000);
  53. push(@checks, 1e8) if ($size > 30_000);
  54. my $prev;
  55. foreach my $k (@checks) {
  56. my $primorial = (
  57. $cache{$k} //= do {
  58. my $z = Math::GMPz::Rmpz_init_nobless();
  59. Math::GMPz::Rmpz_primorial_ui($z, $k);
  60. Math::GMPz::Rmpz_divexact($z, $z, $prev) if defined($prev);
  61. $z;
  62. }
  63. );
  64. Math::GMPz::Rmpz_gcd($g, $primorial, $n);
  65. if (Math::GMPz::Rmpz_cmp_ui($g, 1) > 0) {
  66. return 0;
  67. }
  68. $prev = $primorial;
  69. }
  70. }
  71. return 1;
  72. }
  73. sub primorial_inflation ($n) {
  74. state %primorial;
  75. my $tmp = Math::GMPz->new(1);
  76. my $prod = Math::GMPz->new(1);
  77. foreach my \@pp(factor_exp($n)) {
  78. my ($p, $e) = @pp;
  79. my $prim = $primorial{$p} //= do {
  80. my $z = Math::GMPz::Rmpz_init_nobless();
  81. Math::GMPz::Rmpz_primorial_ui($z, $p);
  82. $z;
  83. };
  84. if ($e > 1) {
  85. Math::GMPz::Rmpz_pow_ui($tmp, $prim, $e);
  86. Math::GMPz::Rmpz_mul($prod, $prod, $tmp);
  87. }
  88. else {
  89. Math::GMPz::Rmpz_mul($prod, $prod, $prim);
  90. }
  91. }
  92. return $prod;
  93. }
  94. # "HCN.bz2" was generated by Achim Flammenkamp, and is available at:
  95. # http://wwwhomes.uni-bielefeld.de/achim/HCN.bz2
  96. # "HCN_primorial_deflated.txt.bz2" is a primorial deflation of each highly composite number H(n) from "HCN.bz2", such that A108951(A181815(H(n))) = H(n).
  97. my $z = IO::Uncompress::Bunzip2->new("HCN_primorial_deflated.txt.bz2");
  98. while (defined(my $line = $z->getline())) {
  99. chomp($line);
  100. my $hcn = primorial_inflation($line);
  101. if ( primality_pretest($hcn - 1)
  102. and primality_pretest($hcn + 1)
  103. and is_prob_prime($hcn + 1)
  104. and is_prob_prime($hcn - 1)) {
  105. print $., ", ";
  106. }
  107. }