Skip to content

Commit c4a471b

Browse files
committed
new file: Math/prime_counting_from_almost_primes.pl
new file: Math/prime_counting_from_squarefree_almost_primes.pl
1 parent 627756e commit c4a471b

5 files changed

+163
-3
lines changed
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
#!/usr/bin/perl
2+
3+
# Author: Daniel "Trizen" Șuteu
4+
# Date: 27 August 2025
5+
# https://github.com/trizen
6+
7+
# A sublinear algorithm for computing the Prime Counting function `pi(n)`,
8+
# based on the number of k-almost primes <= n, for `k >= 2`, which can be computed in sublinear time.
9+
10+
# See also:
11+
# https://mathworld.wolfram.com/AlmostPrime.html
12+
13+
use 5.036;
14+
use ntheory qw(:all);
15+
16+
sub k_prime_count ($k, $n) {
17+
18+
if ($k == 1) {
19+
return my_prime_count($n);
20+
}
21+
22+
my $count = 0;
23+
24+
sub ($m, $p, $k, $j = 0) {
25+
26+
my $s = rootint(divint($n, $m), $k);
27+
28+
if ($k == 2) {
29+
30+
forprimes {
31+
$count += my_prime_count(divint($n, mulint($m, $_))) - $j++;
32+
} $p, $s;
33+
34+
return;
35+
}
36+
37+
foreach my $q (@{primes($p, $s)}) {
38+
__SUB__->($m * $q, $q, $k - 1, $j++);
39+
}
40+
}->(1, 2, $k);
41+
42+
return $count;
43+
}
44+
45+
sub my_prime_count ($n) {
46+
47+
state $pi_table = [0, 0, 1, 2, 2]; # a larger lookup table helps a lot!
48+
49+
if ($n < 0) {
50+
return 0;
51+
}
52+
53+
if (defined($pi_table->[$n])) {
54+
return $pi_table->[$n];
55+
}
56+
57+
my $M = $n - 1;
58+
59+
foreach my $k (2 .. logint($n, 2)) {
60+
$M -= k_prime_count($k, $n);
61+
}
62+
63+
return ($pi_table->[$n] //= $M);
64+
}
65+
66+
foreach my $n (1..7) { # takes ~3 seconds
67+
say "pi(10^$n) = ", my_prime_count(10**$n);
68+
}
69+
70+
__END__
71+
pi(10^1) = 4
72+
pi(10^2) = 25
73+
pi(10^3) = 168
74+
pi(10^4) = 1229
75+
pi(10^5) = 9592
76+
pi(10^6) = 78498
77+
pi(10^7) = 664579
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
#!/usr/bin/perl
2+
3+
# Author: Daniel "Trizen" Șuteu
4+
# Date: 27 August 2025
5+
# https://github.com/trizen
6+
7+
# A sublinear algorithm for computing the Prime Counting function `pi(n)`,
8+
# based on the number of squarefree k-almost primes <= n, for `k >= 2`, which can be computed in sublinear time.
9+
10+
# See also:
11+
# https://mathworld.wolfram.com/AlmostPrime.html
12+
13+
use 5.036;
14+
use ntheory qw(:all);
15+
16+
sub squarefree_almost_prime_count ($k, $n) {
17+
18+
if ($k == 0) {
19+
return (($n <= 0) ? 0 : 1);
20+
}
21+
22+
if ($k == 1) {
23+
return my_prime_count($n);
24+
}
25+
26+
my $count = 0;
27+
28+
sub ($m, $p, $k, $j = 1) {
29+
30+
my $s = rootint(divint($n, $m), $k);
31+
32+
if ($k == 2) {
33+
34+
forprimes {
35+
$count += my_prime_count(divint($n, mulint($m, $_))) - $j++;
36+
} $p, $s;
37+
38+
return;
39+
}
40+
41+
foreach my $q (@{primes($p, $s)}) {
42+
__SUB__->(mulint($m, $q), $q + 1, $k - 1, ++$j);
43+
}
44+
}
45+
->(1, 2, $k);
46+
47+
return $count;
48+
}
49+
50+
sub my_prime_count ($n) {
51+
52+
state $pi_table = [0, 0, 1, 2, 2]; # a larger lookup table helps a lot!
53+
54+
if ($n < 0) {
55+
return 0;
56+
}
57+
58+
if (defined($pi_table->[$n])) {
59+
return $pi_table->[$n];
60+
}
61+
62+
my $M = powerfree_count($n, 2) - 1;
63+
64+
foreach my $k (2 .. exp(LambertW(log($n))) + 1) {
65+
$M -= squarefree_almost_prime_count($k, $n);
66+
}
67+
68+
return ($pi_table->[$n] //= $M);
69+
}
70+
71+
foreach my $n (1..7) { # takes ~1 second
72+
say "pi(10^$n) = ", my_prime_count(10**$n);
73+
}
74+
75+
__END__
76+
pi(10^1) = 4
77+
pi(10^2) = 25
78+
pi(10^3) = 168
79+
pi(10^4) = 1229
80+
pi(10^5) = 9592
81+
pi(10^6) = 78498
82+
pi(10^7) = 664579

Math/prime_counting_liouville_formula.pl

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@
88
# based on the Liouville function and the number of k-almost primes <= n, for `k >= 2`.
99

1010
# See also:
11-
# https://en.wikipedia.org/wiki/Mertens_function
12-
# https://en.wikipedia.org/wiki/M%C3%B6bius_function
11+
# https://mathworld.wolfram.com/AlmostPrime.html
1312

1413
use 5.036;
1514
use ntheory qw(:all);

Math/prime_counting_mertens_formula.pl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ ($n)
6262

6363
my $M = mertens($n);
6464

65-
foreach my $k (2 .. logint($n, 2)) {
65+
foreach my $k (2 .. exp(LambertW(log($n))) + 1) {
6666
$M -= (-1)**$k * squarefree_almost_prime_count($k, $n);
6767
}
6868

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1067,6 +1067,8 @@ A nice collection of day-to-day Perl scripts.
10671067
* [Prime 41](./Math/prime_41.pl)
10681068
* [Prime abundant sequences](./Math/prime_abundant_sequences.pl)
10691069
* [Prime count smooth sum](./Math/prime_count_smooth_sum.pl)
1070+
* [Prime counting from almost primes](./Math/prime_counting_from_almost_primes.pl)
1071+
* [Prime counting from squarefree almost primes](./Math/prime_counting_from_squarefree_almost_primes.pl)
10701072
* [Prime counting liouville formula](./Math/prime_counting_liouville_formula.pl)
10711073
* [Prime counting mertens formula](./Math/prime_counting_mertens_formula.pl)
10721074
* [Prime factorization concept](./Math/prime_factorization_concept.pl)

0 commit comments

Comments
 (0)