generate_carmichael-hebyshev_pseudoprimes.pl 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. #!/usr/bin/perl
  2. # Generate Carmichael-Chebyshev pseudoprimes.
  3. # https://oeis.org/A299799
  4. use 5.020;
  5. use warnings;
  6. use ntheory qw(:all);
  7. use experimental qw(signatures);
  8. sub divceil ($x,$y) { # ceil(x/y)
  9. my $q = divint($x, $y);
  10. ($q*$y == $x) ? $q : ($q+1);
  11. }
  12. sub carmichael_numbers_in_range ($A, $B, $k, $callback) {
  13. $A = vecmax($A, pn_primorial($k+1)>>1);
  14. sub ($m, $lambda, $p, $k, $u = undef, $v = undef) {
  15. if (defined($u) and $u > $v) {
  16. return;
  17. }
  18. if ($k == 1) {
  19. $v = vecmin($v, 1000);
  20. if ($u > $v) {
  21. return;
  22. }
  23. forprimes {
  24. my $t = $m*$_;
  25. if (($t-1)%$lambda == 0 and ($t-1)%(($_*$_ - 1)>>1) == 0) {
  26. $callback->($t);
  27. }
  28. } $u, $v;
  29. return;
  30. }
  31. my $s = rootint(divint($B, $m), $k);
  32. for (my $r; $p <= $s; $p = $r) {
  33. last if ($p > 1000);
  34. $r = next_prime($p);
  35. is_smooth($p - 1, 19) || next;
  36. is_smooth($p*$p - 1, 19) || next;
  37. my $L = lcm($lambda, ($p*$p-1)>>1);
  38. gcd($L, $m) == 1 or next;
  39. #is_smooth($p*$p - 1, 127) || next;
  40. #is_smooth($p - 1, 19) || next;
  41. # gcd($m*$p, euler_phi($m*$p)) == 1 or die "$m*$p: not cyclic";
  42. my $t = $m*$p;
  43. my $u = divceil($A, $t);
  44. my $v = divint($B, $t);
  45. if ($u <= $v) {
  46. __SUB__->($t, $L, $r, $k - 1, (($k==2 && $r>$u) ? $r : $u), $v);
  47. }
  48. }
  49. }->(Math::GMPz->new(1), 1, 3, $k);
  50. }
  51. use Math::GMPz;
  52. my $k = 12;
  53. my $from = Math::GMPz->new("1");
  54. my $upto = $from+100;
  55. while (1) {
  56. say ":: [$k] Sieving ($from, $upto)";
  57. carmichael_numbers_in_range($from, $upto, $k, sub ($n) { say $n });
  58. $from = $upto+1;
  59. $upto = 2*$from;
  60. }