Skip to content

Commit 40a7f60

Browse files
committed
new file: Math/count_of_rough_numbers_recursive.pl
modified: Math/meissel_lehmer_prime_count.pl modified: Math/prime_counting_from_squarefree_almost_primes.pl
1 parent a23fdee commit 40a7f60

5 files changed

+95
-20
lines changed

Math/count_of_rough_numbers.pl

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,13 @@
1010
# https://en.wikipedia.org/wiki/Rough_number
1111

1212
use 5.020;
13-
use integer;
1413
use ntheory qw(:all);
1514
use experimental qw(signatures);
1615

17-
sub rough_count ($n, $p) {
16+
sub my_rough_count ($n, $p) {
17+
18+
my %cache;
19+
1820
sub ($n, $p) {
1921

2022
if ($p > sqrtint($n)) {
@@ -26,12 +28,17 @@ ($n, $p)
2628
}
2729

2830
if ($p == 3) {
29-
my $t = $n / 3;
31+
my $t = divint($n, 3);
3032
return ($t - ($t >> 1));
3133
}
3234

35+
my $key = "$n,$p";
36+
37+
return $cache{$key}
38+
if exists $cache{$key};
39+
3340
my $u = 0;
34-
my $t = $n / $p;
41+
my $t = divint($n, $p);
3542

3643
for (my $q = 2 ; $q < $p ; $q = next_prime($q)) {
3744

@@ -46,12 +53,12 @@ ($n, $p)
4653
}
4754
}
4855

49-
$t - $u;
56+
$cache{$key} = $t - $u;
5057
}->($n * $p, $p);
5158
}
5259

5360
foreach my $p (@{primes(30)}) {
54-
say "Φ(10^n, $p) for n <= 10: [", join(', ', map { rough_count(powint(10, $_), $p) } 0 .. 10), "]";
61+
say "Φ(10^n, $p) for n <= 10: [", join(', ', map { my_rough_count(powint(10, $_), $p) } 0 .. 10), "]";
5562
}
5663

5764
__END__
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
#!/usr/bin/perl
2+
3+
# Daniel "Trizen" Șuteu
4+
# Date: 05 September 2025
5+
# https://github.com/trizen
6+
7+
# Count the number of B-rough numbers <= n.
8+
9+
# See also:
10+
# https://en.wikipedia.org/wiki/Rough_number
11+
12+
use 5.020;
13+
use ntheory qw(:all);
14+
use experimental qw(signatures);
15+
16+
sub my_rough_count($n, $k) {
17+
18+
my @P = @{primes($k - 1)};
19+
20+
return $n if (@P == 0);
21+
22+
my %cache;
23+
24+
sub ($n, $a) {
25+
26+
my $key = "$n,$a";
27+
28+
return $cache{$key}
29+
if exists $cache{$key};
30+
31+
# Initial count: odd numbers ≤ n
32+
my $count = $n - ($n >> 1);
33+
34+
# Inclusion-Exclusion principle
35+
for my $j (1 .. $a - 1) {
36+
last if ($P[$j] > $n);
37+
$count -= __SUB__->(divint($n, $P[$j]), $j);
38+
}
39+
40+
$cache{$key} = $count;
41+
}->($n, scalar @P);
42+
}
43+
44+
foreach my $p (@{primes(30)}) {
45+
say "Φ(10^n, $p) for n <= 10: [", join(', ', map { my_rough_count(powint(10, $_), $p) } 0 .. 10), "]";
46+
}
47+
48+
__END__
49+
Φ(10^n, 2) for n <= 10: [1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, 10000000000]
50+
Φ(10^n, 3) for n <= 10: [1, 5, 50, 500, 5000, 50000, 500000, 5000000, 50000000, 500000000, 5000000000]
51+
Φ(10^n, 5) for n <= 10: [1, 3, 33, 333, 3333, 33333, 333333, 3333333, 33333333, 333333333, 3333333333]
52+
Φ(10^n, 7) for n <= 10: [1, 2, 26, 266, 2666, 26666, 266666, 2666666, 26666666, 266666666, 2666666666]
53+
Φ(10^n, 11) for n <= 10: [1, 1, 22, 228, 2285, 22857, 228571, 2285713, 22857142, 228571428, 2285714285]
54+
Φ(10^n, 13) for n <= 10: [1, 1, 21, 207, 2077, 20779, 207792, 2077921, 20779221, 207792207, 2077922077]
55+
Φ(10^n, 17) for n <= 10: [1, 1, 20, 190, 1917, 19181, 191808, 1918081, 19180820, 191808190, 1918081917]
56+
Φ(10^n, 19) for n <= 10: [1, 1, 19, 179, 1806, 18053, 180524, 1805251, 18052535, 180525355, 1805253568]
57+
Φ(10^n, 23) for n <= 10: [1, 1, 18, 170, 1711, 17103, 171021, 1710234, 17102401, 171024023, 1710240224]
58+
Φ(10^n, 29) for n <= 10: [1, 1, 17, 163, 1634, 16361, 163586, 1635877, 16358819, 163588196, 1635881952]

Math/meissel_lehmer_prime_count.pl

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,7 @@
1919
my %pi_cache;
2020

2121
# Recursive φ(n, a): numbers <= n not divisible by first a primes
22-
sub recursive_rough_count ($n, $k) {
23-
24-
my @P = @{primes($k)};
22+
sub recursive_rough_count ($n, $P) {
2523

2624
sub ($n, $a) {
2725

@@ -30,13 +28,17 @@ ($n, $k)
3028
return $phi_cache{$key}
3129
if exists $phi_cache{$key};
3230

33-
if ($a == 0) {
34-
return $phi_cache{$key} = $n;
31+
my $count = $n - ($n >> 1);
32+
33+
foreach my $j (1 .. $a - 1) {
34+
my $np = divint($n, $P->[$j]);
35+
last if ($np == 0);
36+
$count -= __SUB__->($np, $j);
3537
}
3638

37-
$phi_cache{$key} = __SUB__->($n, $a - 1) - __SUB__->(divint($n, $P[$a - 1]), $a - 1);
39+
$phi_cache{$key} = $count;
3840
}
39-
->($n, scalar @P);
41+
->($n, scalar @$P);
4042
}
4143

4244
# P2 correction term
@@ -69,7 +71,7 @@ ($n)
6971
my $a = scalar @P;
7072
my $p_a = $P[-1];
7173

72-
my $phi = recursive_rough_count($n, $p_a + 1);
74+
my $phi = recursive_rough_count($n, \@P);
7375
my $p2 = P2($n, $a, $p_a);
7476

7577
my $result = $phi + $a - 1 - $p2;

Math/prime_counting_from_squarefree_almost_primes.pl

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ ($k, $n)
3333

3434
forprimes {
3535
$count += my_prime_count(divint($n, mulint($m, $_))) - $j++;
36-
} $p, $s;
36+
}
37+
$p, $s;
3738

3839
return;
3940
}
@@ -49,14 +50,20 @@ ($k, $n)
4950

5051
sub my_prime_count ($n) {
5152

52-
state $pi_table = [0, 0, 1, 2, 2]; # a larger lookup table helps a lot!
53+
state %cache = ( # a larger lookup table helps a lot!
54+
0 => 0,
55+
1 => 0,
56+
2 => 1,
57+
3 => 2,
58+
4 => 2,
59+
);
5360

5461
if ($n < 0) {
5562
return 0;
5663
}
5764

58-
if (defined($pi_table->[$n])) {
59-
return $pi_table->[$n];
65+
if (exists $cache{$n}) {
66+
return $cache{$n};
6067
}
6168

6269
my $M = powerfree_count($n, 2) - 1;
@@ -65,10 +72,10 @@ ($n)
6572
$M -= squarefree_almost_prime_count($k, $n);
6673
}
6774

68-
return ($pi_table->[$n] //= $M);
75+
$cache{$n} //= $M;
6976
}
7077

71-
foreach my $n (1..7) { # takes ~1 second
78+
foreach my $n (1 .. 7) { # takes ~1 second
7279
say "pi(10^$n) = ", my_prime_count(10**$n);
7380
}
7481

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -743,6 +743,7 @@ A nice collection of day-to-day Perl scripts.
743743
* [Count of perfect powers](./Math/count_of_perfect_powers.pl)
744744
* [Count of prime power](./Math/count_of_prime_power.pl)
745745
* [Count of rough numbers](./Math/count_of_rough_numbers.pl)
746+
* [Count of rough numbers recursive](./Math/count_of_rough_numbers_recursive.pl)
746747
* [Count of smooth numbers](./Math/count_of_smooth_numbers.pl)
747748
* [Count of smooth numbers mpz](./Math/count_of_smooth_numbers_mpz.pl)
748749
* [Count of smooth numbers mpz 2](./Math/count_of_smooth_numbers_mpz_2.pl)

0 commit comments

Comments
 (0)