carmichael_euler_phi.pl 1.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. #!/usr/bin/perl
  2. use 5.014;
  3. use strict;
  4. use warnings;
  5. use Math::GMPz;
  6. use Math::Prime::Util::GMP qw(totient is_carmichael);
  7. use experimental qw(signatures);
  8. sub big_euler_phi ($n) {
  9. if (length("$n") > 50) {
  10. say "Big input: ", length($n), " digits";
  11. my $res = eval {
  12. local $SIG{ALRM} = sub { die "alarm\n" };
  13. alarm 30;
  14. chomp(my $test = `$^X -MMath::Prime::Util::GMP=totient -E 'say totient("$n")'`);
  15. alarm 0;
  16. return Math::GMPz->new($test);
  17. };
  18. return $res if defined($res);
  19. return undef;
  20. }
  21. say "Small input: $n";
  22. Math::GMPz->new(totient($n));
  23. }
  24. my %seen;
  25. while (<>) {
  26. /\S/ || next;
  27. # /Fermat/ or next;
  28. if (/: (\d+)$/) {
  29. next if $seen{$1}++;
  30. my $n = Math::GMPz->new($1);
  31. is_carmichael($n) || next;
  32. my $phi = big_euler_phi($n) // next;
  33. say "phi($n) = $phi";
  34. if (($n-1)% $phi == 0) {
  35. die "Found counter-example: $n";
  36. }
  37. }
  38. }