test2.pl 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. #!/usr/bin/perl
  2. use 5.010;
  3. use strict;
  4. use warnings;
  5. use Math::GMPz;
  6. use ntheory qw(powmod rootint next_prime);
  7. # [359505020161, 1121414775001, 1682253492481, ]
  8. my $max = 0;
  9. use 5.020;
  10. use strict;
  11. use warnings;
  12. no warnings 'recursion';
  13. use ntheory qw(is_prime);
  14. use experimental qw(signatures);
  15. sub mulmod {
  16. my ($n, $k, $mod) = @_;
  17. ref($mod)
  18. ? ((($n % $mod) * $k) % $mod)
  19. : ntheory::mulmod($n, $k, $mod);
  20. }
  21. # Creates the `modulo_test*` subroutines.
  22. foreach my $g (
  23. [1, 1, 4, 29],
  24. [2, 1, 61, 3 * 41 * 17],
  25. #[3, 1, 5, 3],
  26. [4, 1, 53, 10 * 31 * 71],
  27. [5, 1, 23, 43],
  28. ) {
  29. no strict 'refs';
  30. *{__PACKAGE__ . '::' . 'modulo_test' . $g->[0]} = sub ($n, $mod) {
  31. my %cache;
  32. sub ($n) {
  33. $n == 0 && return $g->[1];
  34. $n == 1 && return $g->[2];
  35. if (exists $cache{$n}) {
  36. return $cache{$n};
  37. }
  38. my $k = $n >> 1;
  39. #<<<
  40. $cache{$n} = (
  41. $n % 2 == 0
  42. ? (mulmod(__SUB__->($k), __SUB__->($k), $mod) - mulmod(mulmod($g->[3], __SUB__->($k - 1), $mod), __SUB__->($k - 1), $mod)) % $mod
  43. : (mulmod(__SUB__->($k), __SUB__->($k + 1), $mod) - mulmod(mulmod($g->[3], __SUB__->($k - 1), $mod), __SUB__->($k), $mod)) % $mod
  44. );
  45. #>>>
  46. }
  47. ->($n - 1);
  48. };
  49. }
  50. sub is_probably_prime($n) {
  51. $n <= 1 && return 0;
  52. $n == 2 && return 1;
  53. $n == 3 && return 1;
  54. $n == 11 && return 1;
  55. $n == 13 && return 1;
  56. $n == 17 && return 1;
  57. $n == 59 && return 1;
  58. powmod(2, $n - 1, $n) == 1 or return 0;
  59. my $r5 = modulo_test5($n, $n);
  60. ($r5 == 1) or ($r5 == $n - 1) or return 0;
  61. my $r4 = modulo_test4($n, $n);
  62. ($r4 == 1) or ($r4 == $n - 1) or return 0;
  63. # my $r3 = modulo_test3($n, $n);
  64. # ($r3 == 1) or ($r3 == $n-1) or return 0;
  65. my $r2 = modulo_test2($n, $n);
  66. ($r2 == 1) or ($r2 == $n - 1) or return 0;
  67. my $r1 = modulo_test1($n, $n);
  68. (($n % 4 == 3) ? ($r1 == $n - 1) : ($r1 == 1)) or return 0;
  69. #my $r6 = modulo_test6($n, $n);
  70. #($r6 == 1) or ($r6 == $n-1) or return 0;
  71. }
  72. # Find counter-examples
  73. foreach my $n (1 .. 3000) {
  74. if (is_probably_prime($n)) {
  75. if (not is_prime($n)) {
  76. warn "Counter-examples: $n\n";
  77. }
  78. }
  79. elsif (is_prime($n)) {
  80. warn "Missed a prime: $n\n";
  81. }
  82. }
  83. foreach my $n (
  84. qw(
  85. 790623289
  86. 530443201
  87. 151813201
  88. 10024561
  89. 1507746241
  90. 1825568641
  91. 1330655041
  92. 5385832561
  93. 9294465601
  94. 6189121
  95. 90698401
  96. 888700681
  97. 772727356801
  98. 459572555521
  99. 766015436161
  100. 24783645601
  101. 61615404001
  102. 310449770401
  103. 1887933601
  104. 30680814529
  105. 38069223721
  106. 1414273150081
  107. 43674868591201
  108. 328420730229121
  109. 348475822294081
  110. 615482316860401
  111. 1412368404878881
  112. 1489873293627841
  113. 484662529
  114. 212680023361
  115. 262396677543001
  116. 1425631483865161
  117. 1973944203788899
  118. 2518825754955511
  119. 4139764902984481
  120. 221306864032801
  121. 359505020161
  122. 1121414775001
  123. 1682253492481
  124. 24400777040641
  125. 38989474716193
  126. 40977671331601
  127. 46668334332673
  128. 54080321943649
  129. 106309139227201
  130. 195449862688081
  131. 224530340357233
  132. 240723140898241
  133. 320247762202369
  134. 372402596837701
  135. 443372888629441
  136. 596657267497201
  137. 712424619363601
  138. 1444302789209281
  139. 1514208533704777
  140. 1961656420426561
  141. 1984323150552601
  142. 2161556745579001
  143. 2256137288796301
  144. 2427442746677521
  145. 3198224171193481
  146. 3448064239362601
  147. 3716673343381441
  148. 4002924544218601
  149. 4025380496726161
  150. 5085501271868161
  151. 5606301981821641
  152. 5819114530600801
  153. 39671149333495681
  154. )
  155. ) {
  156. say(is_probably_prime(Math::GMPz->new($n)) ? "failed: $n" : "WOW ($n)");
  157. }
  158. say "=========";
  159. my %seen;
  160. my @nums;
  161. while (<>) {
  162. next if /^\h*#/;
  163. my ($n) = (split(' '))[-1];
  164. $n || next;
  165. next if $seen{$n}++;
  166. #say $. if $. % 10000 == 0;
  167. if ($n >= (~0 >> 1)) {
  168. $n = Math::GMPz->new("$n");
  169. }
  170. # push @nums, $n;
  171. is_probably_prime($n) && warn "error: $n\n";
  172. #ntheory::is_prime($n) && die "error: $n\n";
  173. #ntheory::is_aks_prime($n) && die "error: $n\n";
  174. #ntheory::miller_rabin_random($n, 7) && die "error: $n\n";
  175. }
  176. #@nums = sort {$a <=> $b} @nums;
  177. #foreach my $n(@nums) {
  178. # is_probably_prime($n) && warn "error: $n\n";
  179. #}
  180. __END__
  181. Known counter-examples:
  182. 359505020161
  183. 1121414775001
  184. 1682253492481
  185. 24400777040641
  186. 38989474716193
  187. 40977671331601
  188. 46668334332673
  189. 54080321943649
  190. 106309139227201
  191. 195449862688081
  192. 224530340357233
  193. 240723140898241
  194. 320247762202369
  195. 372402596837701
  196. 596657267497201
  197. 712424619363601
  198. 1444302789209281
  199. 1514208533704777
  200. 1961656420426561
  201. 1984323150552601
  202. 2161556745579001
  203. 2256137288796301
  204. 2427442746677521
  205. 3198224171193481
  206. 3448064239362601
  207. 3716673343381441
  208. 4002924544218601
  209. 4025380496726161
  210. 5085501271868161
  211. 5606301981821641
  212. 5819114530600801
  213. 443372888629441
  214. 39671149333495681