//********** For standard Magma (V2.22-3) only **********
// In mingens.m , I commented out the line with GrpPSL2`ShimFDSidepairsVertices; (unknown attribute) 
// in domain.m, I stated : import "../ModFrmHil/level_old.m" (the new level.m provoqued crashes) 
AttachSpec("GrpPSL2Shim/spec");
/*I attach the old mingens.m anyway (the new from Toby doesn't work when calling Group(G) ) :
In file "/cal/homes/rambaud/GrpPSL2Shim/mingens.m", line 240, column 38:
>>   m := map<U -> G | x :-> &*([G!O!1] cat [ gammagens[Abs(s)]^Sign(s) : s in
Runtime error in 'cat': Incompatible sequences */
// or, sometimes also, stops because of an unknown attribute InternalTriangleGroupPresentation
Attach("GrpPSL2Shim/mingens_old.m");
AttachSpec("GrpPSL2/spec");
Attach("ModFrmHil/level_old.m");
AttachSpec("AlgQuat/spec");
AttachSpec("AlgAss/spec");
AttachSpec("spec");

//Given a matrix M of M_2(Z_F/pp^2) (as a list of coefficients), returns the permutation given by its left action on the full P1(Z_F/pp^2) (or just the subset of P1 equal to the orbit of Gamma_0(p) when logLev equals 1)  
function ActionOnP1(M, orbit, logLev) 
  orbitImgs:=[0 : i in orbit];
  R:=Parent(M[1]);
  GM:=MatrixGroup<2,R| M>; 
  mat:=GM!M;
  for i in [1..#orbit] do 
    v:=orbit[i];
    image:=v*Transpose(mat);
    if IsUnit(image[2]) and logLev eq 0 then
      image *:=1/image[2];
      ii := Index(orbit, image);
      error if ii eq 0, i,"unexpected action of G on the full P1"; 
      orbitImgs[i]:=ii;
    elif IsUnit(image[1]) then
       image *:=1/image[1];
       ii := Index(orbit, image);
        error if ii eq 0, i,"unexpected action of G on the orbit"; 
       orbitImgs[i]:=ii; 
    else error i,"unexpected action of G on vectors";
    end if;
   end for;
   return  orbitImgs;
end function;


//Given the images of generators of G in M_2(Z_F/pp^2) (as lists of coefficients), returns the permutation group generated by their left action on the full P1(Z_F/pp^2) (or just the subset of P1 equal to the orbit of G=Gamma_0(p), when logLev equals 1)  
function ActionGensGamma0_p2( MgensR,logLev)
R:=Parent(MgensR[1][1]);
orbitGOnP1:=[Vector([R!1,x]): x in R | not IsUnit(x)];
if logLev eq 0 then
  orbitGOnP1 cat:=[Vector([R!x,1]): x in R];
end if;
n:=#orbitGOnP1;
ListPerms:= [ActionOnP1(M,orbitGOnP1,logLev): M in MgensR];
return [Sym(n)|x : x in ListPerms];
end function;

//canonical ordering
procedure SimultCanonicalOrderC3(~gens, ~perms, ~inds)
    g := Sym(3)!(1,2,3);
    for e:=0 to 2 do
	if ((inds[1] eq inds[2]) and (inds[1] eq inds[3])) or ((inds[1] ge inds[2]) and (inds[1] gt inds[3])) then
            break;
        end if;
        inds := [ inds[i^g] : i in [1..#inds] ];
	gens:=[gens[i^g] : i in [1..#gens] ];
	perms:=[perms[i^g] : i in [1..#perms] ];
        inds;
    end for;
end procedure;

//Given a fuchsian group G, arising from the units one group of an eichler order of level 0 or pp|p (p inert or totally ramified for the moment), and which is a triangle group (resp. of signature a pointed torus), returns :
//- a triple Ga,Gb,Gc in G (Ga.Gb.Gc=1) (resp a double Ga,Gb) of generators. Their orders a,b,c are printed (resp. the order of the action of the loop around the point of the torus).
//- the permutation triple (resp. double) [da,db,dc] of its left coset action on the units congruence subgroup (Gamma_0(pp^2))^(1) (so that, with Magma's composition convention where permutations act on the right, dc*db*da=Id);
//- and the monodromy group it generates.
function ActionGGamma0_p2(G, p)
O:=BaseRing(G);
ZF:=BaseRing(O);
pp:=Factorization(ideal<ZF | p>)[1][1];
sign:=Signature(G);
if [sign[1],#sign[2]] eq [0,3] then
  base:="triangle";
elif [sign[1],#sign[2]] eq [1,1] then
  base:="ptdtorus";
else error "G must be of signature a triangle group or a pointed torus";
end if;
if G`ShimLevel eq ideal<ZF | 1> then
  logLev:=0;
elif G`ShimLevel eq pp then
  logLev:=1;
else error "Order must be of level 1 or pp|p";
end if;
O:=BaseRing(G);
U,mm,mO:=Group(G);
if base eq "triangle" then
  Ga:=mO(U.1);
  Gb:=mO(U.2);
  Gc:=mO(U.2^(-1)*U.1^(-1)) ; //otherwise, Gb^(-1)*Ga^(-1) was automatically coerced into G
  if MultiplicativeOrder(Gc) eq 0 then
    Gb:=mO(U.2^(-1));
    Gc:=Gb^(-1)*Ga^(-1);
  end if;
  Ggens:=[Ga,Gb,Gc];
  orders:=[MultiplicativeOrder(x): x in Ggens];
elif base eq "ptdtorus" then
  Ga:=mO(U.1);
  Gb:=mO(U.2);
  Com:=Ga*Gb*Ga^(-1)*Gb^(-1);
  if MultiplicativeOrder(Com) eq 0 then
    Gb:=mO(U.2^(-1));
    Com:=Ga*Gb*Ga^(-1)*Gb^(-1);
  end if;
  Ggens:=[Ga,Gb];
  orders:=[MultiplicativeOrder(Com)];
  error if orders[1] ne sign[2][1],"the sides of the fundamental domain should make a loop around the point, try another orientation";
end if;
M2Fp, mat, v := pMatrixRing(O, pp); //v:F->Fp
Mgens:=[mat(g): g in Ggens];
R, mR := quo< ZF | pp^2 >;
MgensR:=[ [mR(M[i[1]][i[2]]@@v): i in CartesianPower([1,2],2)]: M in Mgens];
error if logLev eq 1 and &or[IsUnit(M[3]): M in MgensR],"conjugate the quaternion order to make it lower triangular mod pp";
perms:=ActionGensGamma0_p2(MgensR,logLev);
if base eq "triangle" then
  error if orders ne [Order(tau):tau in perms], "generators got mixed up";
  SimultCanonicalOrderC3(~Ggens, ~perms, ~orders);  
end if;
"orders ", orders;
mon:=sub<Parent(perms[1]) | perms>;
error if base eq "triangle" and &*[perms[3-i]:i in [0..2]] ne Id(mon), "permutations got mixed up"; //Magma has permutations act on the right => * is anti-composition
error if base eq "ptdtorus" and Order((perms[2],perms[1])) ne orders[1], "permutations got mixed up";
"monodromy group of order",Factorization(#mon);
return [G!x : x in Ggens], perms, mon ;
end function;
