B2TorsionCode
/*

1. The command FindB2(n,m) returns the group B2(Zn+Zm).

2. The command TorsionSubgroup(FindB2(n,m)) will return the torsion subgroup of B2(Zn+Zm).

3. The comman TorsionFreeRank(FindB2(n,m)) will return the Q-rank of B2(Zn+Zm)

*/





//Create the function checking whether (i1,j1) and (i2,j2) generates Zn+Zm (n<=m)
CheckGenerator1s:=function (n,m,i1,j1,i2,j2);
if n eq 1 then//Simplify the case when Z/n+Z/m=Z/mn
if Gcd(Gcd(j1,j2), m) eq 1 then
return true;
else 
return false;
end if; 
else
Z:=RModule(IntegerRing(),2);
L:=sub<Z|[n,0],[0,m]>;
Znm:=quo<Z|L>;
gen:=sub<Znm|[i1,j1],[i2,j2]>;

if gen eq Znm then
return true;
else
return false;
end if;
end if;
end function;






//Create the function returning B2
FindB2:=function (n,m);
number:=0;
row:=0;
relation:=0;
A:= AssociativeArray();//where (i1,j1) is stored
B:= AssociativeArray();//where (i2,j2) is stored
Index:=AssociativeArray();//index the generator1 ((i1,j1),(i2,j2))
//Make sure Zn+Zm is reduced to the simpliefied form
if Gcd(n,m) eq 1 then
m:=m*n;
n:=1;
else
prod:=n*m;
n:=Gcd(n,m);
m:=prod div n;
end if;



//Find the generating symbols
for i1 in [0..n-1] do
for j1 in [0..m-1] do
for i2 in [0..n-1] do
for j2 in [0..m-1] do



if (CheckGenerator1s(n,m,i1,j1,i2,j2)) then
number:=number+1;
A[number] := [i1, j1];//Store(i1,j1)
B[number] := [i2, j2];//Store(i2,j2)
Index[i1*(10^9)+j1*(10^6)+i2*(10^3)+j2]:=number;//Store the index
end if;
end for;
end for;
end for;
end for;



//Create B2(Zn+Zm)
M:=FreeAbelianGroup(number);//Create the free groups on symbols
relation:={};

for i in [1..number] do

if A[i] eq B[i] then
//On symbols of the form (a,a)
search:=A[i][1]*(10^9)+A[i][2]*(10^6);
target:=Index[search];
relation:=Include(relation, M.target-M.i);//Relation (B)
else
//On symbols of the form (a,b), a neq b
if A[i] le B[i] then//(a,b) and (b,a) will procude the same relation
search:=B[i][1]*(10^9)+B[i][2]*(10^6)+A[i][1]*(10^3)+A[i][2];
target:=Index[search];
relation:=Include(relation, M.target-M.i);//Symmetric Relation

i1:=(A[i][1]-B[i][1]) mod n;
j1:=(A[i][2]-B[i][2]) mod m;
i2:=(B[i][1]-A[i][1]) mod n;
j2:=(B[i][2]-A[i][2]) mod m;
Generator1:=[A[i], [i2, j2]];
Generator2:=[[i1, j1], B[i]];
search:=Generator2[1][1]*(10^9)+Generator2[1][2]*(10^6)+Generator2[2][1]*(10^3)+Generator2[2][2];
target1:=Index[search];
search:=Generator1[1][1]*(10^9)+Generator1[1][2]*(10^6)+Generator1[2][1]*(10^3)+Generator1[2][2];
target2:=Index[search];
relation:=Include(relation, M.target1+M.target2-M.i);//Relation(B)
end if;
end if;
end for;

B2:= quo<M|relation>;
torsion:=TorsionSubgroup(B2);
return torsion;
end function;






/* Sample running:

print "This is a list of torsions of B_2";
for i in [1..60] do
print "";
print "";
print "";
print "Torsion of B_2(Z/" cat IntegerToString(i) cat ") is:";
FindB2(1,i);
print "";
print "";
print "";
end for;

for i in [1..15] do
print "";
print "";
print "";
print "Torsion of B_2(Z/" cat IntegerToString(i) cat "+Z/" cat IntegerToString(i) cat ") is:";
FindB2(i,i);
print "";
print "";
print "";
end for;

*/










B2-TorsionCode
/*

1. The command FindB2minus(n,m) returns the group B2^-(Zn+Zm).

2. The command TorsionSubgroup(FindB2minus(n,m)) will return the torsion subgroup of B2^-(Zn+Zm).

3. The comman TorsionFreeRank(FindB2minus(n,m)) will return the Q-rank of B2^-(Zn+Zm)

*/







//Create the function checking whether (i1,j1) and (i2,j2) generates Zn+Zm (n<=m)
CheckGenerator1s:=function (n,m,i1,j1,i2,j2);
if n eq 1 then//Simplify the case when Z/n+Z/m=Z/mn
if Gcd(Gcd(j1,j2), m) eq 1 then
return true;
else 
return false;
end if; 
else
Z:=RModule(IntegerRing(),2);
L:=sub<Z|[n,0],[0,m]>;
Znm:=quo<Z|L>;
gen:=sub<Znm|[i1,j1],[i2,j2]>;

if gen eq Znm then
return true;
else
return false;
end if;
end if;
end function;





//Create the function returning B2
FindB2minus:=function (n,m);
number:=0;
row:=0;
relation:=0;
A:= AssociativeArray();//where (i1,j1) is stored
B:= AssociativeArray();//where (i2,j2) is stored
Index:=AssociativeArray();//index the generator1 ((i1,j1),(i2,j2))
//Make sure Zn+Zm is reduced to the simpliefied form
if Gcd(n,m) eq 1 then
m:=m*n;
n:=1;
else
prod:=n*m;
n:=Gcd(n,m);
m:=prod div n;
end if;

//Find the generating symbols
for i1 in [0..n-1] do
for j1 in [0..m-1] do
for i2 in [0..n-1] do
for j2 in [0..m-1] do

if (CheckGenerator1s(n,m,i1,j1,i2,j2)) then
number:=number+1;
A[number] := [i1, j1];//Store(i1,j1)
B[number] := [i2, j2];//Store(i2,j2)
Index[i1*(10^9)+j1*(10^6)+i2*(10^3)+j2]:=number;//Store the index
end if;
end for;
end for;
end for;
end for;


//Create B2^-(Zn+Zm)
M:=FreeAbelianGroup(number);//Create the free groups on symbols
relation:=[];

for i in [1..number] do

if A[i] eq B[i] then
//On symbols of the form (a,a)
search:=A[i][1]*(10^9)+A[i][2]*(10^6);
target:=Index[search];
relation:=relation cat [M.target-M.i];//Relation (B)
else
//On symbols of the form (a,b), a neq b
if A[i] le B[i] then//(a,b) and (b,a) will procude the same relation
search:=B[i][1]*(10^9)+B[i][2]*(10^6)+A[i][1]*(10^3)+A[i][2];
target:=Index[search];
relation:=relation cat [M.target-M.i];//Symmetric Relation

i1:=(A[i][1]-B[i][1]) mod n;
j1:=(A[i][2]-B[i][2]) mod m;
i2:=(B[i][1]-A[i][1]) mod n;
j2:=(B[i][2]-A[i][2]) mod m;
Generator1:=[A[i], [i2, j2]];
Generator2:=[[i1, j1], B[i]];
search:=Generator2[1][1]*(10^9)+Generator2[1][2]*(10^6)+Generator2[2][1]*(10^3)+Generator2[2][2];
target1:=Index[search];
search:=Generator1[1][1]*(10^9)+Generator1[1][2]*(10^6)+Generator1[2][1]*(10^3)+Generator1[2][2];
target2:=Index[search];
relation:=relation cat [M.target1+M.target2-M.i];//Relation(B)
end if;
end if;

//quotient relation for B2^-
i1:=(-A[i][1]) mod n;
j1:=(-A[i][2]) mod m;
Generator:=[[i1, j1], B[i]];
search:=Generator[1][1]*(10^9)+Generator[1][2]*(10^6)+Generator[2][1]*(10^3)+Generator[2][2];
target:=Index[search];
relation:=relation cat [M.target+M.i];//Relation [a,b]=[-a,b]

end for;

B2minus:= quo<M|relation>;
torsion:=TorsionSubgroup(B2minus);

return torsion;
end function;







/* Sample running:

print "This is a list of torsions of B_2";
for i in [1..20] do
print "";
print "";
print "";
print "Torsion of B_2(Z/" cat IntegerToString(i) cat ") is:";
FindB2(1,i);
print "";
print "";
print "";
end for;

for i in [1..5] do
print "";
print "";
print "";
print "Torsion of B_2(Z/" cat IntegerToString(i) cat "+Z/" cat IntegerToString(i) cat ") is:";
FindB2(i,i);
print "";
print "";
print "";
end for;

*/