-
Notifications
You must be signed in to change notification settings - Fork 33
/
mertens_function.pl
executable file
·70 lines (51 loc) · 1.48 KB
/
mertens_function.pl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#!/usr/bin/perl
# A simple implementation of a nice algorithm for computing the Mertens function:
# M(x) = Sum_{k=1..n} moebius(k)
# Algorithm due to Marc Deleglise and Joel Rivat:
# https://projecteuclid.org/euclid.em/1047565447
# This implementation is not particularly optimized.
# See also:
# https://oeis.org/A002321
# https://oeis.org/A084237
# https://en.wikipedia.org/wiki/Mertens_function
# https://en.wikipedia.org/wiki/M%C3%B6bius_function
use 5.016;
use ntheory qw(sqrtint moebius);
use experimental qw(signatures);
sub mertens_function ($x) {
my $u = sqrtint($x);
my @M = (0);
my @mu = moebius(0, $u); # list of Moebius(k) for k=0..floor(sqrt(n))
# Partial sums of the Moebius function:
# M[n] = Sum_{k=1..n} moebius(k)
for my $i (1 .. $#mu) {
$M[$i] += $M[$i - 1] + $mu[$i];
}
my $sum = $M[$u];
foreach my $m (1 .. $u) {
$mu[$m] || next;
my $S1_t = 0;
foreach my $n (int($u / $m) + 1 .. sqrtint(int($x / $m))) {
$S1_t += $M[int($x / ($m * $n))];
}
my $S2_t = 0;
foreach my $n (sqrtint(int($x / $m)) + 1 .. int($x / $m)) {
$S2_t += $M[int($x / ($m * $n))];
}
$sum -= $mu[$m] * ($S1_t + $S2_t);
}
return $sum;
}
foreach my $n (1 .. 6) {
say "M(10^$n) = ", mertens_function(10**$n);
}
__END__
M(10^1) = -1
M(10^2) = 1
M(10^3) = 2
M(10^4) = -23
M(10^5) = -48
M(10^6) = 212
M(10^7) = 1037
M(10^8) = 1928
M(10^9) = -222