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
QQ := Rationals();

intrinsic MDCongruenceSubgroup(M :: ModSym) -> GrpPSL2
{
  Return the congruence subgroup that was used to define the ambient space of this modular
  symbols space.
} 
  M := AmbientSpace(M);
  if IsTrivial(DirichletCharacter(M)) then
    return Gamma0(Level(M));
  elif IsMultiChar(M) then
    if assigned M`isgamma1 and M`isgamma1 then
      return Gamma1(Level(M));
    elif assigned M`isgamma and M`isgamma then
      return CongruenceSubgroup(Integers()!Sqrt(Level(M)));
    end if;
  end if;
  require false : "Only implemented for Gamma0(N), Gamma1(N) and Gamma(N)";
end intrinsic;




intrinsic MDDiagonalALBasis(decomposition :: SeqEnum[ModSym]) -> SeqEnum[SeqEnum[ModFrmElt]], SeqEnum[SeqEnum[SeqEnum[FldRatElt]]]
{
  Given a decomposition of the modular symbols of weight k for some group Gamma0(N) it gives a corresponding basis
  of the modular in S_k(Gamma0(N)) respecting this decomposition such that further more the Atkin-Lehner operators 
  act diagonally. The second return value are the Atkin-Lehner eigenvalues on this basis
}
  if #decomposition eq 0 then
    return [],[];
  end if;
  G := MDCongruenceSubgroup(decomposition[1]);
  N := Level(G);
  require G eq Gamma0(N) : "Only implemented for Gamma0(N)";
  g :=  Genus(G);
  prec := 2*g;
  k := Weight(decomposition[1]);

  M := ModularForms(G,k);
  S := CuspidalSubspace(M);
  V, VtoS, StoV := RSpace(S);

  al_divisors := [pe[1]^pe[2] : pe in Factorisation(N)];
  al := [AtkinLehnerOperator(S,d) : d in al_divisors];
  q_basis := [qIntegralBasis(Si, prec) : Si in decomposition];

  V_basis := [[StoV(S ! f) : f in B] : B in q_basis];
  V_dec := [ChangeRing(sub< V | B>, QQ) : B in V_basis];

  V_basis_diag := [];
  al_diag := [[] : w_p in al];

  for Vi in V_dec do
    al_res :=  [MDRestriction(w_p, Vi) : w_p in al];
    diag, t :=  Diagonalisation(al_res);
    basis := [ClearDenominator(v) : v in Rows(t*BasisMatrix(Vi))];
    Append(~V_basis_diag, basis);
    for i in [1..#diag] do
      Append(~al_diag[i],Diagonal(diag[i]));
    end for;
  end for;


  q_basis_diag := [[VtoS(f) : f in B] : B in V_basis_diag];

  return q_basis_diag,al_diag;

end intrinsic;