bfw_pseudoprime_db.pl 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. #!/usr/bin/perl
  2. # Try to find a BPSW pseudoprime.
  3. use 5.036;
  4. use Math::GMPz;
  5. use ntheory qw(forprimes foroddcomposites);
  6. use Math::Prime::Util::GMP qw(:all);
  7. eval { require GDBM_File };
  8. my $cache_db = "cache/factors.db";
  9. dbmopen(my %db, $cache_db, 0444)
  10. or die "Can't create/access database <<$cache_db>>: $!";
  11. sub findQ ($n) {
  12. # Find first D for which kronecker(D, n) == -1
  13. for (my $k = 2 ; ; ++$k) {
  14. my $D = (-1)**$k * (2 * $k + 1);
  15. my $K = Math::GMPz::Rmpz_si_kronecker($D, $n);
  16. if ($K == 0) {
  17. my $g = gcd($D, $n);
  18. if ($g > 1 and $g < $n) {
  19. return undef;
  20. }
  21. }
  22. if ($k == 20 and Math::GMPz::Rmpz_perfect_square_p($n)) {
  23. return undef;
  24. }
  25. if ($K == -1) {
  26. return divint((1 - $D), 4);
  27. }
  28. }
  29. }
  30. sub is_lucas_V_pseudoprime ($n) {
  31. if (ref($n) ne 'Math::GMPz') {
  32. $n = Math::GMPz->new("$n");
  33. }
  34. if (Math::GMPz::Rmpz_even_p($n)) {
  35. return 1 if (Math::GMPz::Rmpz_cmp_ui($n, 2) == 0);
  36. return 0;
  37. }
  38. my $P = 1;
  39. my $Q = findQ($n) // return 0;
  40. if ($Q == -1) {
  41. $P = 5;
  42. $Q = 5;
  43. }
  44. state $t = Math::GMPz::Rmpz_init();
  45. state $u = Math::GMPz::Rmpz_init();
  46. Math::GMPz::Rmpz_add_ui($t, $n, 1);
  47. my $V = lucasvmod($P, $Q, $t, $n);
  48. Math::GMPz::Rmpz_set_str($t, $V, 10);
  49. Math::GMPz::Rmpz_set_si($u, 2 * $Q);
  50. Math::GMPz::Rmpz_congruent_p($t, $u, $n);
  51. }
  52. is_lucas_V_pseudoprime(913) or die "error";
  53. is_lucas_V_pseudoprime(150267335403) or die "error";
  54. is_lucas_V_pseudoprime(430558874533) or die "error";
  55. is_lucas_V_pseudoprime(14760229232131) or die "error";
  56. is_lucas_V_pseudoprime(936916995253453) or die "error";
  57. my $n = Math::GMPz::Rmpz_init();
  58. while (my ($key) = each %db) {
  59. Math::GMPz::Rmpz_set_str($n, $key, 10);
  60. if (is_lucas_V_pseudoprime($n)) {
  61. say $n;
  62. }
  63. }