carmichael_from_combinations_of_primes_recursive_mpz.pl 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. #!/usr/bin/perl
  2. # Daniel "Trizen" Șuteu
  3. # Date: 17 March 2023
  4. # https://github.com/trizen
  5. # Generate Carmichael numbers from a given multiple.
  6. # See also:
  7. # https://trizenx.blogspot.com/2020/08/pseudoprimes-construction-methods-and.html
  8. use 5.036;
  9. use Math::GMPz;
  10. #use ntheory qw(:all);
  11. use Math::Sidef qw(:all);
  12. use ntheory qw(vecall forcomb);
  13. sub carmichael_from_multiple ($m, $callback, $reps = 1e4) {
  14. my $t = Math::GMPz::Rmpz_init();
  15. my $u = Math::GMPz::Rmpz_init();
  16. my $v = Math::GMPz::Rmpz_init();
  17. is_square_free($m) || return;
  18. my $L = lambda($m);
  19. $m = Math::GMPz->new("$m");
  20. $L = Math::GMPz->new("$L");
  21. Math::GMPz::Rmpz_invert($v, $m, $L) || return;
  22. for (my $p = Math::GMPz::Rmpz_init_set($v) ; --$reps > 0 ; Math::GMPz::Rmpz_add($p, $p, $L)) {
  23. $p > 1 or next;
  24. Math::GMPz::Rmpz_gcd($t, $m, $p);
  25. Math::GMPz::Rmpz_cmp_ui($t, 1) == 0 or next;
  26. is_square_free($p) || next;
  27. Math::GMPz::Rmpz_mul($v, $m, $p);
  28. Math::GMPz::Rmpz_sub_ui($u, $v, 1);
  29. Math::GMPz::Rmpz_set_str($t, lambda($p), 10);
  30. if (Math::GMPz::Rmpz_divisible_p($u, $t)) {
  31. $callback->(Math::GMPz::Rmpz_init_set($v));
  32. }
  33. }
  34. }
  35. my %seen;
  36. my @primes;
  37. #foreach my $p (almost_primes(2, 10000, 100000)) {
  38. while (<>) {
  39. my $p = (split(' ', $_))[-1];
  40. $p =~ /^\d+\z/ or next;
  41. #$p > 2000 or next;
  42. # log($p)/log(10) > 100 or next;
  43. next if $seen{$p}++;
  44. is_square_free($p) || next;
  45. $p = Math::GMPz->new("$p");
  46. push @primes, $p;
  47. }
  48. #foreach my $p (@primes) {
  49. forcomb {
  50. my $p = Math::GMPz->new(join '', prod(@primes[@_]));
  51. if (lambda($p) < iroot($p, 3)->sqr) {
  52. say "# Sieving with p = $p";
  53. my @list = ($p);
  54. while (@list) {
  55. my $m = shift(@list);
  56. $seen{$m} = 1;
  57. carmichael_from_multiple(
  58. $m,
  59. sub ($n) {
  60. if ($n > $m) {
  61. if ($n > ~0) {
  62. say $n;
  63. }
  64. if (!$seen{$n}++) {
  65. push @list, $n;
  66. }
  67. }
  68. }
  69. );
  70. }
  71. }
  72. } scalar(@primes), 2;