FastM2
/*
The function M2(n,m) returns the Q-rank of M2(Cn+Cm). For the case of M2(Cn), please input M2(1,n);
The function M2m(n,m) returns the Q-rank of M2-(Cn+Cm). For the case of M2-(Cn), please input M2m(1,n);
*/
//M1+
function a(n);
if (n eq 1) or (n eq 2) then
return 1;
else
return EulerPhi(n) div 2;
end if;
end function;
//M1-
function b(n);
if n eq 2 then
return 0;
elif n eq 1 then
return 0;
else
return EulerPhi(n) div 2;
end if;
end function;
//M2-(Cn+Cnm) n ne 2
function c1(n,m);
dim:=1;
for i in [2..n*m] do
if IsPrime(i) and (n*m mod i eq 0)then
dim:=dim*(1-i^(-2));
end if;
end for;
if n eq 2 then
s:=1;
else
s:=EulerPhi(n) div 2;
end if;
return s*(1+m^2*n^3*dim/12);
end function;
//M2-(Cn+Cnm) n=2
function c2(m)
dim:=1;
for i in [2..2*m] do
if IsPrime(i) and (2*m mod i eq 0) then
dim:=dim*(1+1/i);
end if;
end for;
c:=(2*EulerPhi(m)+EulerPhi(2*m)) div 2;
return 1+m*EulerPhi(2*m)/6*dim-c;
end function;
//Ker(M2-->M2-(Cn+Cnm)
function f(n,m);
A:=FreeAbelianGroup(2);
A:=quo<A|n*A.1, (n*m)*A.2>;
record:=[];
dim:=0;
for x in A do
B:=sub<A|x>;
C:=quo<A|B>;
if Ngens(C) eq 1 then
if not (B in record) then
dim:=dim+a(Order(x))*b((n*n*m) div Order(x));
record:=record cat [B];
end if;
end if;
end for;
return dim;
end function;
//ker(M2-->M2-(Cn))
function g(n);
A:=FreeAbelianGroup(1);
A:=quo<A|n*A.1>;
record:=[];
dim:=0;
for x in A do
B:=sub<A|x>;
C:=quo<A|B>;
if Ngens(C) eq 1 then
if not (B in record) then
dim:=dim+a(Order(x))*b(n div Order(x));
record:=record cat [B];
end if;
end if;
end for;
return dim;
end function;
//M2-(Cn)
function h(n);
mu:=1;
for i in [2..n] do
if IsPrime(i) and (n mod i eq 0) then
mu:=mu*(1+1/i);
end if;
end for;
mu:=mu*n*EulerPhi(n)/2;
if n mod 2 eq 0 then
C2:=EulerPhi(n)+EulerPhi(n div 2);
else
C2:=EulerPhi(n);
end if;
return 1+mu/12-C2/2;
end function;
//M2(Cn)
function kn(n);
return h(n)+g(n);
end function;
//M2(Cn+Cnm)
function k(n,m);
if n eq 2 then
return c2(m)+f(n,m);
else
return c1(n,m)+f(n,m);
end if;
end function;
function M2(n,m);
if Gcd(n,m) eq 1 then
n:=n*m;
if n eq 2 then
return 0;
else
return kn(n);
end if;
else
prod:=n*m;
n:=Gcd(n,m);
m:=prod div n;
if n eq 2 and m eq 2 then
return 0;
else
return k(n, m div n);
end if;
end if;
end function;
function M2m(n,m);
if Gcd(n,m) eq 1 then
n:=n*m;
if n eq 2 then
return 0;
else
return h(n);
end if;
else
prod:=n*m;
n:=Gcd(n,m);
m:=prod div n;
if n eq 2 then
if m eq 2 then
return 0;
else
return c2(m div 2);
end if;
else
return c1(n, m div n);
end if;
end if;
end function;