omega_prime_numbers_in_range_mpz.pl 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. #!/usr/bin/perl
  2. # Daniel "Trizen" Șuteu
  3. # Date: 14 March 2021
  4. # Edit: 04 April 2024
  5. # https://github.com/trizen
  6. # Generate all the k-omega primes in range [A,B].
  7. # Definition:
  8. # k-omega primes are numbers n such that omega(n) = k.
  9. # See also:
  10. # https://en.wikipedia.org/wiki/Almost_prime
  11. # https://en.wikipedia.org/wiki/Prime_omega_function
  12. use 5.036;
  13. use Math::GMPz;
  14. use ntheory qw(:all);
  15. sub omega_prime_numbers ($A, $B, $k) {
  16. $A = vecmax($A, pn_primorial($k));
  17. $A = Math::GMPz->new("$A");
  18. $B = Math::GMPz->new("$B");
  19. my $u = Math::GMPz::Rmpz_init();
  20. my @values = sub ($m, $lo, $j) {
  21. Math::GMPz::Rmpz_tdiv_q($u, $B, $m);
  22. Math::GMPz::Rmpz_root($u, $u, $j);
  23. my $hi = Math::GMPz::Rmpz_get_ui($u);
  24. if ($lo > $hi) {
  25. return;
  26. }
  27. my @lst;
  28. my $v = Math::GMPz::Rmpz_init();
  29. foreach my $q (@{primes($lo, $hi)}) {
  30. Math::GMPz::Rmpz_mul_ui($v, $m, $q);
  31. while (Math::GMPz::Rmpz_cmp($v, $B) <= 0) {
  32. if ($j == 1) {
  33. if (Math::GMPz::Rmpz_cmp($v, $A) >= 0) {
  34. push @lst, Math::GMPz::Rmpz_init_set($v);
  35. }
  36. }
  37. else {
  38. push @lst, __SUB__->($v, $q + 1, $j - 1);
  39. }
  40. Math::GMPz::Rmpz_mul_ui($v, $v, $q);
  41. }
  42. }
  43. return @lst;
  44. }
  45. ->(Math::GMPz->new(1), 2, $k);
  46. sort { Math::GMPz::Rmpz_cmp($a, $b) } @values;
  47. }
  48. # Generate 5-omega primes in the range [3000, 10000]
  49. my $k = 5;
  50. my $from = 3000;
  51. my $upto = 10000;
  52. my @arr = omega_prime_numbers($from, $upto, $k);
  53. my @test = grep { prime_omega($_) == $k } $from .. $upto; # just for testing
  54. join(' ', @arr) eq join(' ', @test) or die "Error: not equal!";
  55. say join(', ', @arr);
  56. # Run some tests
  57. foreach my $k (1 .. 6) {
  58. my $from = pn_primorial($k) + int(rand(1e4));
  59. my $upto = $from + int(rand(1e5));
  60. say "Testing: $k with $from .. $upto";
  61. my @arr = omega_prime_numbers($from, $upto, $k);
  62. my @test = grep { prime_omega($_) == $k } $from .. $upto;
  63. join(' ', @arr) eq join(' ', @test) or die "Error: not equal!";
  64. }