test_fermat_fib.pl 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. #!/usr/bin/perl
  2. use 5.020;
  3. use strict;
  4. use warnings;
  5. use experimental qw(signatures);
  6. use Math::GMPz;
  7. use ntheory qw(is_prime kronecker);
  8. sub is_fermat_fibonacci_prime($n) {
  9. if (ref($n) eq 'Math::GMPz') {
  10. $n = Math::GMPz::Rmpz_init_set($n);
  11. }
  12. else {
  13. $n = Math::GMPz->new("$n");
  14. }
  15. if (Math::GMPz::Rmpz_even_p($n)) {
  16. return ((Math::GMPz::Rmpz_cmp_ui($n, 2) == 0) ? 1 : 0);
  17. }
  18. if (Math::GMPz::Rmpz_cmp_ui($n, 5) == 0) {
  19. return 1;
  20. }
  21. my $t = Math::GMPz::Rmpz_init_set_ui(2);
  22. my $u = Math::GMPz::Rmpz_init();
  23. Math::GMPz::Rmpz_sub_ui($u, $n, 1);
  24. Math::GMPz::Rmpz_powm($u, $t, $u, $n);
  25. Math::GMPz::Rmpz_cmp_ui($u, 1) == 0 or return 0;
  26. my $v = Math::GMPz::Rmpz_init();
  27. my $w = Math::GMPz::Rmpz_init();
  28. Math::GMPz::Rmpz_sub_ui($w, $n, 1);
  29. my $m = Math::GMPz::Rmpz_init_set($n);
  30. my $f = Math::GMPz::Rmpz_init_set_ui(0);
  31. my $g = Math::GMPz::Rmpz_init_set_ui(1);
  32. my $a = Math::GMPz::Rmpz_init_set_ui(0);
  33. my $b = Math::GMPz::Rmpz_init_set_ui(1);
  34. my $c = Math::GMPz::Rmpz_init_set_ui(1);
  35. my $d = Math::GMPz::Rmpz_init_set_ui(1);
  36. for (; ;) {
  37. if (Math::GMPz::Rmpz_odd_p($n)) {
  38. Math::GMPz::Rmpz_set($t, $f);
  39. Math::GMPz::Rmpz_mul($f, $f, $a);
  40. Math::GMPz::Rmpz_addmul($f, $g, $c);
  41. Math::GMPz::Rmpz_mod($f, $f, $m);
  42. Math::GMPz::Rmpz_mul($g, $g, $d);
  43. Math::GMPz::Rmpz_addmul($g, $t, $b);
  44. Math::GMPz::Rmpz_mod($g, $g, $m);
  45. }
  46. Math::GMPz::Rmpz_div_2exp($n, $n, 1);
  47. Math::GMPz::Rmpz_sgn($n) || last;
  48. Math::GMPz::Rmpz_set($t, $a);
  49. Math::GMPz::Rmpz_mul($a, $a, $a);
  50. Math::GMPz::Rmpz_addmul($a, $b, $c);
  51. Math::GMPz::Rmpz_mod($a, $a, $m);
  52. Math::GMPz::Rmpz_set($u, $b);
  53. Math::GMPz::Rmpz_mul($b, $b, $d);
  54. Math::GMPz::Rmpz_addmul($b, $u, $t);
  55. Math::GMPz::Rmpz_mod($b, $b, $m);
  56. Math::GMPz::Rmpz_set($v, $c);
  57. Math::GMPz::Rmpz_mul($c, $c, $t);
  58. Math::GMPz::Rmpz_addmul($c, $v, $d);
  59. Math::GMPz::Rmpz_mod($c, $c, $m);
  60. Math::GMPz::Rmpz_mul($d, $d, $d);
  61. Math::GMPz::Rmpz_addmul($d, $v, $u);
  62. Math::GMPz::Rmpz_mod($d, $d, $m);
  63. }
  64. if ( Math::GMPz::Rmpz_cmp_ui($f, 1) == 0
  65. or Math::GMPz::Rmpz_cmp($f, $w) == 0) {
  66. if (not is_prime($w + 1)) {
  67. say "error for ", $w + 1, " -> with $f";
  68. }
  69. return 1;
  70. }
  71. return 0;
  72. }
  73. my %seen;
  74. my @nums;
  75. while (<>) {
  76. next if /^\h*#/;
  77. /\S/ or next;
  78. my $n = (split(' ', $_))[-1];
  79. $n || next;
  80. next if $seen{$n}++;
  81. #say $. if $. % 10000 == 0;
  82. #if ($n >= (~0 >> 1)) {
  83. $n = Math::GMPz->new("$n");
  84. #}
  85. push @nums, $n;
  86. #ntheory::is_provable_prime($n) && die "error: $n\n";
  87. #ntheory::is_prime($n) && die "error: $n\n";
  88. #ntheory::is_aks_prime($n) && die "error: $n\n";
  89. #ntheory::miller_rabin_random($n, 7) && die "error: $n\n";
  90. }
  91. @nums = sort { $a <=> $b } @nums;
  92. foreach my $n (@nums) {
  93. is_fermat_fibonacci_prime($n) && do {
  94. warn "error: $n\n";
  95. last;
  96. };
  97. }