non-residue_generate.pl 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. #!/usr/bin/perl
  2. # Author: Daniel "Trizen" Șuteu
  3. # Date: 28 January 2019
  4. # https://github.com/trizen
  5. # A new algorithm for generating Fermat pseudoprimes to base 2.
  6. # See also:
  7. # https://oeis.org/A050217 -- Super-Poulet numbers: Poulet numbers whose divisors d all satisfy d|2^d-2.
  8. # https://oeis.org/A214305 -- Fermat pseudoprimes to base 2 with two prime factors.
  9. # See also:
  10. # https://en.wikipedia.org/wiki/Fermat_pseudoprime
  11. # https://trizenx.blogspot.com/2018/08/investigating-fibonacci-numbers-modulo-m.html
  12. use 5.020;
  13. use warnings;
  14. use experimental qw(signatures);
  15. use ntheory qw(:all);
  16. use Math::GMPz;
  17. #use Math::AnyNum qw(prod);
  18. use Math::Prime::Util::GMP;
  19. my @primes = @{primes(35)};
  20. sub least_nonresidue_sqrtmod ($n) { # for any n
  21. #for (my $p = 2 ; ; $p = next_prime($p)) {
  22. foreach my $p(@primes) {
  23. #sqrtmod($p, $n) // return $p;
  24. if (kronecker($p, $n) == -1) {
  25. return $p;
  26. }
  27. }
  28. return 97;
  29. }
  30. # 2, 3, 4, 102/25, 11/2, 6, 22/3, 12, 13, 73
  31. my $k = 1;
  32. my $z = 3*5*7;
  33. say "# Generating with k = $k";
  34. forprimes {
  35. #if (($_-1) % 3 == 0 and is_prime($k*($_-1) + 1)) {
  36. if (($_-1)%$z == 0) {
  37. foreach my $j(2..20) {
  38. next if ($j == $z);
  39. my $k = $j/$z;
  40. if (is_prime($k*($_-1) + 1) and least_nonresidue_sqrtmod($_) >= 35 and least_nonresidue_sqrtmod($k*($_-1) + 1) >= 35) {
  41. my $p = $_;
  42. my $n = $p * ($k*($p-1) + 1);
  43. if ($n > ((~0) >> 7)) {
  44. $n = Math::Prime::Util::GMP::mulint($p, $k*($p-1) + 1);
  45. }
  46. say "# Testing: $n with k = $k and p = $p";
  47. if (is_pseudoprime($n, 2)) {
  48. #if ($n > ~0) {
  49. # $n = Math::GMPz::Rmpz_init_set_str($n, 10);
  50. #}
  51. #if (least_nonresidue_sqrtmod($n) >= 20) {
  52. say $n;
  53. # }
  54. }
  55. }
  56. }
  57. }
  58. #} sqrtint(divint((~0)>>8, int($k))), 1e10;
  59. } 1e10, 1e11;
  60. #} sqrtint(divint((~0)>>4, int($k))), 1e11;
  61. #} 66745519681, 1e11;
  62. __END__
  63. #say least_nonresidue_sqrtmod(151110961);
  64. #say least_nonresidue_sqrtmod(302221921);
  65. sub fermat_pseudoprimes ($limit, $callback) {
  66. my %common_divisors;
  67. forprimes {
  68. my $p = $_;
  69. #foreach my $p(11, 23, 31, 89, 97, 193, 241, 1151, 1201, 1321, 1801, 14951, 18191, 55441, 110881, 332641, 849601, 1327871, 1932841, 3466369, 11597041, 29375641, 96563041, 151110961, 215421361, 302221921, 1158756481) {
  70. #if ($p >= 3 and least_nonresidue_sqrtmod($p) >= 30) {
  71. #if ($p > 2) {
  72. if (least_nonresidue_sqrtmod($p) >= 40) {
  73. warn "Found: $p\n";
  74. my $z = znorder(2, $p);
  75. foreach my $d (divisors($p - 1)) {
  76. if (gcd($z, $d) == $z) {
  77. push @{$common_divisors{$d}}, $p;
  78. }
  79. }
  80. }
  81. #}
  82. } 1158756481, 2*1158756481;
  83. warn "Done...\n";
  84. my %seen;
  85. foreach my $arr (values %common_divisors) {
  86. my $l = $#{$arr} + 1;
  87. foreach my $k (2 .. $l) {
  88. forcomb {
  89. my $n = prod(@{$arr}[@_]);
  90. $callback->($n, @{$arr}[@_]) if !$seen{$n}++;
  91. } $l, $k;
  92. }
  93. }
  94. }
  95. sub is_fermat_pseudoprime ($n, $base) {
  96. powmod($base, $n - 1, $n) == 1;
  97. }
  98. sub is_fibonacci_pseudoprime($n) {
  99. (lucas_sequence($n, 1, -1, $n - kronecker($n, 5)))[0] == 0;
  100. }
  101. #my @pseudoprimes;
  102. fermat_pseudoprimes(
  103. 11234,
  104. sub ($n, @f) {
  105. if ($n >= 45669044917576081 and is_pseudoprime($n, 2)) {
  106. warn "$n\n";
  107. say $n;
  108. }
  109. }
  110. );