// *********************************************************** // * MAMGMA tool for calculating Hecke algebras of * // * characteristic p Katz modular forms * // * * // * by Gabor Wiese * // * version of 30 March 2003 * // *********************************************************** // **************** internal functions ****************************** // the record containing all data: Hecke1F := recformat < Level : RngIntElt, Char : RngIntElt, Field : FldFin, Type : Cat, // ModFrm or ModSym Gamma : RngIntElt, // 0 or 1 Dimension : RngIntElt, // Dimension of wt 1 cusp forms Bound : RngIntElt, // the bound from the paper Error : BoolElt, // true, iff some calculation crashed b : SeqEnum, // list of indices s.t. the T_[b[i]] form a basis of the wt p Hecke algebra of modular forms/symbols MF : Mtrx, // the operator F from the paper MS : ModMatFld, // matrix space with basis consisting of weight p Hecke operators of modular forms/symbols HOp1 : SeqEnum, // list of calcd. Hecke ops in wt 1 C : Any // space of cuspidal modular forms/symbols started from >; declare verbose Hecke1,1; SetVerbose ("Hecke1",1); // calculates the index of Gamma_0(N) in SL_2(Z) _calcB := function (N) local B,L; B := N / 12; L := Factorization (N); for i := 1 to #L do B := B * (1 + (1/L[i][1])); end for; return B; end function; intrinsic GetPhi ( M :: Any, p :: RngIntElt ) -> Map {Computes a reduction homomorphism from the ring of integers of the coefficient ring of the space of modular symbols M to its residue class field modulo some prime above p.} local K,R,P,phi; K := CoefficientRing(M); if Characteristic(K) eq 0 then // we need to reduce R := RingOfIntegers(K); P := Decomposition(R,p)[1][1]; _,phi := ResidueClassField(R,P); else // the characteristic is already positive // so take phi to be the identity if IsPrime (#K) then phi := homK|>; else phi := homK|1>; end if; end if; return phi; end intrinsic; intrinsic MatrixInRing (M :: Any, D :: Rng) -> BoolElt {Checks whether all entries of the matrix M are in the ring D.} local ja, r, c, i, j; ja := true; r := NumberOfRows(M); c := NumberOfColumns(M); i := 1; while ja and (i le r) do j := 1; while ja and (j le c) do ja := M[i][j] in D; j := j + 1; end while; i := i + 1; end while; return ja; end intrinsic; // computes the image of a matrix under a homomorphism // of rings // the types AlgMatElt and ModMatFldElt are respected intrinsic MapMatrix (M :: Any, phi :: Map) -> Any, BoolElt {Computes the image of a matrix under a homomorphism of rings. The types AlgMatElt and ModMatFldElt are respected. If the matrix is not in the domain of phi, the zero matrix of the correct size is returned.} local D,C,R,c,B,ja; D := Domain(phi); C := Codomain(phi); r := NumberOfRows(M); c := NumberOfColumns(M); if Type(M) eq AlgMatElt then B := MatrixAlgebra(C,r)!0; else B := RMatrixSpace(C,r,c)!0; end if; ja := MatrixInRing (M, D); if ja then for i := 1 to r do for j := 1 to c do B[i][j] := phi(M[i][j]); end for; end for; end if; return B,ja; end intrinsic; intrinsic NewHeckeOperator ( C :: ModSym, n :: RngIntElt : useIntegral := true ) -> Any {Uses the command IntegralHeckeOperator if the space of modular symbols is defined over the rationals and the useIntegral option is set, otherwise uses HeckeOperator.} local K; K := BaseRing(C); if useIntegral and (Characteristic(K) eq 0) then if K eq RationalField() then return IntegralHeckeOperator(C,n); else return HeckeOperator(C,n); end if; else return HeckeOperator(C,n); end if; end intrinsic; // given a list of matrices, return a list of indeces // such that the corresponding matrices form a maximal // subset of linearly independent matrices // the matrices will be treated as indicated in the sequence indexL _calcBasis := function (L,indexL) local i,j,V,B,R; // find first non-zero matrix j := 1; W := Parent(L[1]); while (j le #indexL) and (L[indexL[j]] eq W!0) do j := j + 1; end while; if j gt #indexL then // there were only zero matrices -> no basis... return []; end if; // L[indexL[j]] is not the zero matrix B := [L[indexL[j]]]; R := [indexL[j]]; // create the matrix space generated by L[indexL[i]] // and extend it by all matrices not yet contained V := KMatrixSpaceWithBasis(B); for i := j+1 to #indexL do if not(L[indexL[i]] in V) then // extend basis B := Append(B, L[indexL[i]]); R := Append(R, indexL[i]); V := KMatrixSpaceWithBasis(B); end if; end for; return R; end function; // calculates a list containing the images under Phi of // the Hecke operators T_1,..,T_B of C // C is the space of modular forms/symbols, B the bound up to // which the operators are calculated and Hp is the weight // in question _calcHeckeOperators := function (C, B, Hp, Phi : useIntegral := true ) local i,j,p,r,d,L,mat,_Error; _Error := false; F := Codomain(Phi); eps := DirichletCharacter(C); d := Dimension (C); N := Level (C); // The Hecke operators should live in the algebra mat. mat := RMatrixSpace (F,d,d); // calculate list of Hecke operators in range 2, ..., B // and store them in the list L L := []; // We set T_1 to be the unit matrix and start at i = 2 L[1] := mat!ScalarMatrix (d, 1); i := 2; while (i le B) do // calculate the i-th Hecke operator of C // using the usual formula relating it to ops T_p, p prime f := Factorization(i); if (#f eq 1) then if f[1][2] eq 1 then // i is prime if IsVerbose("Hecke1") then print "Starting calculation of ",i,"th Hecke operator of weight ",Hp,"."; end if; M,ja := MapMatrix(NewHeckeOperator(C,i : useIntegral ),Phi); L[i] := mat!M; if not ja then vprint Hecke1: "Operator not in the domain of phi. Used zero matrix."; _Error := true; end if; else // i = p^r p := f[1][1]; r := f[1][2]; L[i] := L[p] * L[p^(r-1)] - Phi(Evaluate(eps,p)) * p^(Hp-1) * L[p^(r-2)]; end if; else L[i] := L[1]; // unit matrix for j := 1 to #f do L[i] := L[i] * L[ (f[j][1])^(f[j][2]) ]; end for; end if; i := i + 1; end while; return L, _Error; end function; // ******************** general functions ******************************* intrinsic ListCong ( b :: SeqEnum, n :: RngIntElt, p :: RngIntElt ) -> SeqEnum {Returns the sub-list of the elements of the list of integers b that are congruent n modulo p.} local i,a; a := []; for i := 1 to #b do if (b[i] mod p) eq n then a := Append(a,b[i]); end if; end for; return a; end intrinsic; // ******************** properties ************************************** intrinsic OriginalCharacter ( H :: Rec ) -> GrpDrchElt {Returns the original Dirichlet character.} return DirichletCharacter(H`C); end intrinsic; intrinsic Error ( H :: Rec ) -> BoolElt {Returns whether an error has occured.} return H`Error; end intrinsic; intrinsic Dimension ( H :: Rec ) -> RngIntElt {Returns the dimension.} if assigned H`Dimension then return H`Dimension; else print "Not yet calculated."; return -1; end if; end intrinsic; intrinsic Level ( H :: Rec ) -> RngIntElt {Returns the level.} if assigned H`Level then return H`Level; else print "Error."; return -1; end if; end intrinsic; intrinsic Characteristic ( H :: Rec ) -> RngIntElt {Returns the characteristic.} if assigned H`Char then return H`Char; else print "Error."; return -1; end if; end intrinsic; intrinsic Field ( H :: Rec ) -> Any {Returns the field.} if assigned H`Field then return H`Field; else print "Error."; return -1; end if; end intrinsic; intrinsic Bound ( H :: Rec ) -> RngIntElt {Returns the bound used.} if assigned H`Bound then return H`Bound; else print "Error."; return -1; end if; end intrinsic; // *********************** Hecke operators *********************** intrinsic HeckeOperatorsWt1 ( H :: Rec ) -> SeqEnum {Returns the list of all Hecke operators of weight 1 calculated so far.} return H`HOp1; end intrinsic; forward _HOP; // calculates the operator T_l`, i.e. of weight 1 for prime l // if l equals p then use formula from paper _HOPPrime := procedure (n, ~H, ~HOp2, Phi, eps : useIntegral := true) local A,Tn,MF,T,i,d,v,p; // n is assumed to be prime!!! d := Dimension(H); p := Characteristic(H); A := KMatrixSpace (Field(H),d,d); Tn := A!ScalarMatrix(d,0); // any matrix // T Hecke operator wt p wrt to standard basis of modular symbols // if already calculated, take that one, ow calculate it if IsDefined (HOp2, n) then T := HOp2[n]; else if IsVerbose("Hecke1") then print "Starting calculation of ",n,"th Hecke operator of weight ",p,"."; end if; T,ja := MapMatrix(NewHeckeOperator (H`C,n: useIntegral),Phi); if not ja then vprint Hecke1: "Operator not in the domain of phi. Used zero matrix."; H`Error := true; end if; end if; // calculate the rows of wt 1 T_n in the quotient // H`MS[1..d] / H`MS[(d+1)..(#H`MS)] for i := 1 to d do v := T* H`MS.i; Tn[i] := Vector( Coordinates(H`MS, v)[1..d] ); end for; // Tn now contains the wt 1 operator T_n // if n is p we want T_p`, so add operator

F (= H`MF) if n eq p then H`HOp1[n] := Phi(Evaluate(eps,p))*H`MF + Tn; else H`HOp1[n] := Tn; end if; end procedure; // calculates recursively the operator T_n` // store all needed operators in the list H`HOp1 // only assumes that H`HOp1[1] is the unit matrix _HOP := procedure (n, ~H, ~HOp2, Phi, eps : useIntegral := true ) local i,f,M,l,s; if IsDefined (H`HOp1,n) then return; end if; N := Level(H); f := Factorization (n); if #f eq 1 then // prime power, l^s l := f[1][1]; s := f[1][2]; if s eq 1 then // l is prime _HOPPrime (l, ~H, ~HOp2,Phi, eps : useIntegral); else // calculate the lower l powers recursively _HOP ( l^(s-1), ~H, ~HOp2, Phi, eps : useIntegral ); H`HOp1[ l^s ] := H`HOp1[ l ] * H`HOp1[ l^(s-1) ] - Phi(Evaluate(eps, l)) * H`HOp1[ l^(s-2) ]; end if; else // n is composite M := H`HOp1[1]; // always set as the unit matrix // calculate recursively all prime power operators // for prime powers dividing n // and take their product for i := 1 to #f do _HOP ( (f[i][1])^(f[i][2]), ~H, ~HOp2, Phi, eps : useIntegral ); M := M * H`HOp1 [ (f[i][1])^(f[i][2]) ]; end for; H`HOp1 [n] := M; end if; end procedure; // Using this procedure the operators calculated cannot be stored // memory, because the syntax is that of a function. intrinsic HeckeOperatorWt1 ( n :: RngIntElt, H :: Rec : useIntegral := true ) -> Mtrx, BoolElt {Calculates the nth Hecke operator of weight one.} local HOp2,Phi, eps; if IsDefined (H`HOp1,n) then return H`HOp1[n]; end if; if Dimension(H`MS) eq 0 then if Dimension(H) ne 0 then print "Hecke algebra structure not known. Nothing done."; end if; return H`MS!0; end if; Phi := GetPhi(H`C,Characteristic(H)); eps := OriginalCharacter(H); HOp2 := []; // No operator of wt p is known (any more) H`HOp1 [1] := KMatrixSpace (Field(H), Dimension(H), Dimension(H))!ScalarMatrix(Dimension(H),1); _HOP (n, ~H, ~HOp2, Phi, eps : useIntegral ); return H`HOp1 [n], H`Error; end intrinsic; intrinsic CalcHeckeOperatorsWt1 ( L :: SeqEnum, ~H :: Rec : useIntegral := true ) {Calculates the Hecke operators of weight one specified in the list of integers L.} local i,HOp2, Phi, eps; if Dimension(H`MS) eq 0 then if Dimension(H) ne 0 then print "Hecke algebra structure not known. Nothing done."; end if; return ; end if; Phi := GetPhi(H`C,Characteristic(H)); eps := OriginalCharacter(H); HOp2 := []; H`HOp1 [1] := KMatrixSpace (Field(H), Dimension(H), Dimension(H))!ScalarMatrix(Dimension(H),1); for i := 1 to #L do if IsVerbose("Hecke1") then print "Calculating ",L[i],"th Hecke operator of weight 1."; end if; _HOP (L[i], ~H, ~HOp2, Phi, eps : useIntegral ); end for; return; end intrinsic; intrinsic HeckeAlgebra ( H :: Rec ) -> AlgMat {Creates the Hecke algebra of weight 1 as a matrix algebra. As generators the operators of weight 1 calculated so far are used.} l := HeckeOperatorsWt1(H); if #l ne 0 then A := MatrixAlgebra (l); else A := MatrixAlgebra (Field(H),0); if Dimension(H) ne 0 then vprint Hecke1: "No operator calculated so far."; end if; end if; return A; end intrinsic; // ************************ creation functions ********************** intrinsic HeckeAlgebraWt1 ( ms :: ModSym : useIntegral := true ) -> Rec {Creates the Hecke algebra of weight 1 corresponding to the space of modular symbols ms.} local L,LF1,i, indexL,F,p,b1,V,v,N,M,M1,H,C,a,HOp2,Phi,eps; C := CuspidalSubspace (ms); p := Weight(C); N := Level(C); eps := DirichletCharacter(C); // value checking if (not IsPrime(p)) then print "Weight must be a prime. Error."; H := rec; elif not (Characteristic(BaseField(C)) in {0,p}) then print "Base field must have characteristic",p,"or 0. Error."; H:= rec; else // give warnings if still calculable, but mathematically uncertain if (N mod p eq 0) then print "Warning: Weight ought not divide the level"; elif N le 4 then print "Warning: Level ought to be greater equal 5."; end if; Phi := GetPhi(C,p); F := Codomain(Phi); // set some initial values H := rec< Hecke1F | Level := N, Char := p, Field := F, Bound := Floor((p+2) * _calcB(N)), C := C, HOp1 := [], Dimension := 0, Error := false, b := [], MS := KMatrixSpace (F,0,0), MF := KMatrixSpace (F,0,0)!0 >; // This is obsolete resp. futuristic. Currently, only modular symbols // are supported. H`Type := Type (C); H`Gamma := -1; if H`Type eq ModFrm then if IsGamma0(C) then H`Gamma := 0; elif IsGamma1(C) then H`Gamma := 1; else print "Group could not be determined."; end if; end if; // If there's nothing to do, quit here, otherwise errors will occur. if Dimension(C) eq 0 then // print "Dimension of the space of cusp forms of level ",p," is zero."; // print "Nothing done."; return H; end if; // calculate now the weight p Hecke operators up to the bound // over the field chosen for C (if finite) or over the integers HOp2, H`Error := _calcHeckeOperators(H`C,H`Bound,p, Phi : useIntegral ); // calculate now a basis of the Hecke algebra of wt p // such that the operators of index divisible by p come first indexL := []; for i := 1 to #HOp2 do if (i mod p) ne 0 then indexL := Append(indexL,i); end if; end for; for i := 1 to #HOp2 do if (i mod p) eq 0 then indexL := Append(indexL,i); end if; end for; if IsVerbose("Hecke1") then print "Calculating a basis"; end if; // b1 contains indices s.t. T_i form a basis b1 := _calcBasis(HOp2,indexL); // a is the part of b1 with entries congruent 0 modulo p a := ListCong (b1,0,p); d := #a; H`Dimension := d; // H`b contains indices s.t T_i form a basis and s.t. the indices // divisible by p come first. H`b := a; for i := 1 to #b1 - d do H`b := Append(H`b,b1[i]); end for; // store the wt p Hecke algebra as a matrix space with the // chosen basis H`b H`MS := KMatrixSpaceWithBasis( HOp2 [ H`b [1..(#H`b)] ] ); if Characteristic(BaseField(H`C)) eq 0 then if (2 * Dimension (H`MS) eq Dimension(H`C)) then vprint Hecke1: "Reduction yielded good dimension."; else vprint Hecke1: "Warning: dimension of weight p Hecke algebra not good."; end if; end if; // calculate the rows of the operator F (=MF) H`MF := KMatrixSpace(F, d, d)!0; // any matrix for i := 1 to d do v := HOp2 [ (H`b[i]) div p ] ; H`MF[i] := Vector( Coordinates(H`MS, v)[1..d] ); end for; // calculate Hecke operators of weight 1 for [1..Bound] H`HOp1 [1] := KMatrixSpace(F, d, d)!ScalarMatrix(d,1); // unit matrix for i := 1 to H`Bound do if IsVerbose("Hecke1") then print "Calculating ",i,"th Hecke operator of weight 1."; end if; _HOP (i, ~H, ~HOp2,Phi,eps : useIntegral); end for; end if; return H; end intrinsic; // ********************** output functions *************************** MyPrint := procedure ( file, st1, v, st2 ) PrintFile (file, st1 * Sprint (v, "Magma") * st2); return; end procedure; MyPrintSeqEnum := procedure ( file, name, L ) local i; PrintFile (file, name * " := [];"); for i := 1 to #L do if IsDefined (L,i) then MyPrint (file, name * "[", i, "] :="); MyPrint (file, "", L[i], ";"); end if; end for; return; end procedure; intrinsic SaveHeckeOperatorsWt1 ( file :: MonStgElt, name :: MonStgElt, H :: Rec ) {Saves the calculated list of Hecke operators of weight 1. Usage as for SaveHeckeInfoWt1.} PrintFile (file, "// Hecke operators weight 1" : Overwrite := true); MyPrintSeqEnum (file, name* "`HOp1", H`HOp1); return; end intrinsic; intrinsic SaveHeckeAlgebraWt1 ( file :: MonStgElt, name :: MonStgElt, H :: Rec ) {Saves the Hecke algebra structure. Usage as for SaveHeckeInfoWt1.} PrintFile (file, "// Hecke algebra weight 1" : Overwrite := true); MyPrint (file, name * "`MS := ", H`MS, ";"); return; end intrinsic; intrinsic SaveHeckeInfoWt1 ( file :: MonStgElt, name :: MonStgElt, H :: Rec ) {Saves the basic information on the Hecke algebra of weight 1 specified by H into the file. Neither the calculated Hecke operators of weight 1 nor the algebra structure are saved. For this use the procedures SaveHeckeOperatorsWt1 and SaveHeckeAlgebraWt1 resp. The string name will be the name of the identifier of the Hecke algebra after reloading. For this, you type in Magma: load file;} local ms,L,i,first; PrintFile (file, "// Hecke algebra of weight 1 information" : Overwrite := true); L := Names(H); PrintFile (file, name * " := rec< "); MyPrint (file, "",Format(H)," | "); first := true; for i := 1 to #L do if L[i] eq "MS" then // this is not supposed to be stored in info as it takes a loooot of memory ms := KMatrixSpace (Field(H),0,0); // must set to a value if first then first := false; else PrintFile (file, ", "); end if; MyPrint (file, "MS := ", ms, ""); elif L[i] eq "HOp1" then // this takes a lot of memory too, sometimes if first then first := false; else PrintFile (file, ", "); end if; PrintFile (file, "HOp1 := []"); elif L[i] eq "Error" then if first then first := false; else PrintFile (file, ", "); end if; PrintFile (file, "Error := "*Sprint(H`Error)); elif L[i] eq "C" then // make distinction between modular forms and symbols if first then first := false; else PrintFile (file, ", "); end if; if H`Type eq ModSym then PrintFile (file, "C := CuspidalSubspace(ModularSymbols(DirichletGroup( " * Sprint(Modulus(OriginalCharacter(H)),"Magma") * ", " * Sprint(CoefficientRing(OriginalCharacter(H)),"Magma") * ")!" * Sprint(ElementToSequence(OriginalCharacter(H)),"Magma") * ", " * Sprint(H`Char,"Magma") * "))"); // obsolete or futuristic elif H`Type eq ModFrm then if H`Gamma eq 0 then PrintFile (file, "C := CuspidalSubspace(ModularForms(" * Sprint(H`Level,"Magma") * ", " * Sprint(H`Char,"Magma") * "))"); elif H`Gamma eq 1 then PrintFile (file, "C := CuspidalSubspace(ModularForms(Gamma1(" * Sprint(H`Level,"Magma") * "), " * Sprint(H`Char,"Magma") * "))"); end if; end if; elif L[i] eq "VerbosityLevel" then // do nothing else if assigned H``(L[i]) then if first then first := false; else PrintFile (file, ", "); end if; MyPrint (file, L[i]*" := ", H``(L[i]), ""); end if; end if; end for; PrintFile (file, ">;"); return; end intrinsic; // *************************** database functions ************************* intrinsic ExistsInDatabase ( N :: RngIntElt, DatabasePath :: MonStgElt : what := "all" ) -> BoolElt {Returns whether the specified data of level N is stored in the database.} local existsInfo, existsOps, existsAlg, path, a; path := DatabasePath; s := IntegerToString(N); a := System ("test -f "*path*"info"*s); if a eq 0 then existsInfo := true; else existsInfo := false; end if; a := System ("test -f "*path*"alg"*s*".gz"); if a eq 0 then existsAlg := true; else existsAlg := false; end if; a := System ("test -f "*path*"ops"*s*".gz"); if a eq 0 then existsOps := true; else existsOps := false; end if; if what eq "info" then return existsInfo; elif what eq "alg" then return existsInfo and existsAlg; elif what eq "ops" then return existsInfo and existsOps; elif what eq "all" then return existsInfo and existsOps and existsAlg; end if; return false; end intrinsic; intrinsic SaveToDatabase ( H :: Rec, DatabasePath :: MonStgElt : what := "all" ) {Saves the specified subset of the Hecke algebra data H to the database.} local path,n; path := DatabasePath; n := IntegerToString(Level(H)); if (what eq "all") or (what eq "alg") or (what eq "ops") or (what eq "info") then if IsVerbose ("Hecke1") then print "Saving Hecke algebra information..."; end if; SaveHeckeInfoWt1 ( path*"info"*n, "H["*n*"]", H ); end if; if (what eq "all") or (what eq "alg") then if IsVerbose ("Hecke1") then print "Saving Hecke algebra structure..."; end if; SaveHeckeAlgebraWt1 ( path*"alg"*n, "H["*n*"]", H ); if IsVerbose ("Hecke1") then print "Zipping Hecke algebra..."; end if; System ("gzip -f " * path * "alg"*n); end if; if (what eq "all") or (what eq "ops") then if IsVerbose ("Hecke1") then print "Saving Hecke operators..."; end if; SaveHeckeOperatorsWt1 ( path*"ops"*n, "H["*n*"]", H ); if IsVerbose ("Hecke1") then print "Zipping Hecke operators..."; end if; System ("gzip -f " * path * "ops"*n); end if; return; end intrinsic; intrinsic AddToDatabase ( N :: RngIntElt, DatabasePath :: MonStgElt : what := "all" ) {Computes the Hecke algebra data of level N for the trivial character over the field GF(2) and adds them to the database. The coefficient field of the modular symbols used is RationalField().} local H,i,exAlg,exOps; if ExistsInDatabase (N, DatabasePath : what := what) then print "The required data for the level",N,"is already in the database. Nothing done."; else H := HeckeAlgebraWt1(ModularSymbols(N,2)); if what eq "all" then exAlg := ExistsInDatabase (N, DatabasePath : what := "alg"); exOps := ExistsInDatabase (N, DatabasePath : what := "ops"); if (not exAlg) and (not exOps) then SaveToDatabase (H, DatabasePath : what := "all"); elif (not exAlg) then SaveToDatabase (H, DatabasePath : what := "alg"); elif (not exOps) then SaveToDatabase (H, DatabasePath : what := "ops"); end if; elif (what eq "alg") or (what eq "ops") or (what eq "info") then SaveToDatabase (H, DatabasePath : what := what); end if; end if; return; end intrinsic; intrinsic AddToDatabase ( L :: SeqEnum, DatabasePath :: MonStgElt : what := "all" ) {Computes the Hecke algebra data for all levels in the list L for the trivial character over the field GF(2) and adds them to the database. The coefficient field of the modular symbols used is RationalField().} local i; for i := 1 to #L do if IsVerbose("Hecke1") then print "------------------------------"; print "------------------------------"; print "Now starting level ",L[i]; print "------------------------------"; print "------------------------------"; AddToDatabase (L[i], DatabasePath : what := what); end if; end for; return; end intrinsic; _writeAccessData := procedure (path,nameAcc,nameLoad,n,what) if (what eq "all") or (what eq "alg") or (what eq "ops") or (what eq "info") then PrintFile ( path*nameAcc, "vprint Hecke1:\"Loading information on Hecke algebra of level "*n*"...\";"); PrintFile ( path*nameAcc, "load \""*path*"info"*n*"\";" ); end if; if (what eq "all") or (what eq "alg") then PrintFile ( path*nameAcc, "vprint Hecke1:\"Unzipping Hecke algebra structure of level "*n*"...\";"); PrintFile ( path*nameAcc, "System (\"gunzip -c " * path * "alg"*n * ".gz > " * path*nameLoad * "\");" ); PrintFile ( path*nameAcc, "vprint Hecke1:\"Loading Hecke algebra structure of level "*n*"...\";"); PrintFile ( path*nameAcc, "load \""*path*nameLoad*"\";" ); PrintFile ( path*nameAcc, "System (\"rm -f "* path*nameLoad* "\");" ); end if; if (what eq "all") or (what eq "ops") then PrintFile ( path*nameAcc, "vprint Hecke1:\"Unzipping Hecke operators of level "*n*"...\";"); PrintFile ( path*nameAcc, "System (\"gunzip -c " * path * "ops"*n * ".gz > " * path*nameLoad * "\");" ); PrintFile ( path*nameAcc, "vprint Hecke1:\"Loading Hecke operators of level "*n*"...\";"); PrintFile ( path*nameAcc, "load \""*path*nameLoad*"\";" ); PrintFile ( path*nameAcc, "System (\"rm -f "* path*nameLoad* "\");" ); end if; end procedure; intrinsic AccessDatabase ( L :: SeqEnum, DatabasePath :: MonStgElt : what := "all" ) -> MonStgElt {Creates and returns the name of a file, which you load in order to obtain the specified data for the levels in the list L.} local path,nameAcc, nameLoad, n,i; path := DatabasePath; nameAcc := "Access"; nameLoad := "LoadIn"; PrintFile ( path*nameAcc, "//File for database access" : Overwrite := true); for i := 1 to #L do n := IntegerToString(L[i]); _writeAccessData (path,nameAcc,nameLoad,n,what); end for; return path*nameAcc; end intrinsic; intrinsic SearchDatabase ( L :: SeqEnum, DatabasePath :: MonStgElt : what := "info" ) -> MonStgElt {Searches the database. Please consult the example in the documentation for the usage.} local path,nameAcc, nameLoad, n,i; path := DatabasePath; nameAcc := "Search"; nameLoad := "LoadIn"; PrintFile ( path*nameAcc, "//File for database search" : Overwrite := true); for i := 1 to #L do n := IntegerToString(L[i]); _writeAccessData (path,nameAcc,nameLoad,n,what); PrintFile ( path*nameAcc, "if IsDefined (H,"*n*") then print SEARCH (H["*n*"]); Undefine (~H, "*n*"); end if;" ); end for; return path*nameAcc; end intrinsic; // ******************************* print properties ********************************** // procedures calculating interesting data for a given Hecke algebra intrinsic HeckePropsToString ( H :: Rec : format := "TXT") -> MonStgElt {Prints some properties of the Hecke algebra in weight 1 to a string. Currently the formats "TXT" and "CR" are supported.} local N, n, D, i, j, K, cn, O, A, l, P, m, F, R, T, p, s; N := Level(H); // write intro case format: when "TXT": s := "Level N = "*Sprint(N)*":\n***************************\n\n"; when "CR": s := ""; else s := ""; end case; // write dimension case format: when "TXT": s := s*"Dimension = "*Sprint (Dimension(H))*"\n"; when "CR": s := s*"_Dimension["*Sprint(N)*"] := "*Sprint (Dimension(H))*";\n"; end case; // write bound case format: when "TXT": s := s*"Bound = "*Sprint (Bound(H))*"\n"; when "CR": s := s*"_Bound["*Sprint(N)*"] := "*Sprint (Bound(H))*";\n"; end case; // calculate class number of quadratic extension with discriminant // the square free part of N D := 1; n := Factorisation(N); for j := 1 to #n do D := D * n[j][1]; end for; if D eq 1 then K := RationalField(); cn := 1; else if (D mod 4) eq 3 then K := NumberField(Polynomial([D,0,1])); else K := NumberField(Polynomial([-D,0,1])); end if; O := MaximalOrder(K); cn := ClassNumber(O); end if; case format: when "TXT": s := s*"Class number of quadratic extension with |disc| = "*Sprint (N)*" is: "*Sprint (cn)*"\n"; when "CR": s := s*"_QuadClassNumber["*Sprint(N)*"] := "*Sprint (cn)*";\n"; end case; // calculate the number of local factors A := HeckeAlgebra(H); l := HeckeOperatorsWt1(H); P := LocalDecomposition(A); case format: when "TXT": s := s* "There are "*Sprint (#P)*" local factors.\n"; when "CR": s := s* "_NumberMaxIdeals["*Sprint(N)*"] := "*Sprint (#P)*";\n"; end case; // initialize lists for local factors case format: // when "TXT": when "CR": s := s* "_ResidueField["*Sprint(N)*"] := [];\n"; s := s* "_LocalDimension["*Sprint(N)*"] := [];\n"; s := s* "_NumberMaxIdealsSF["*Sprint(N)*"] := [];\n"; s := s* "_Eigenvalues["*Sprint(N)*"] := [];\n"; s := s* "_UPO["*Sprint(N)*"] := [];\n"; end case; // compute the local data for i := 1 to #P do // intro of i-th local factor case format: when "TXT": case i: when 1: s := s* "\nLooking at "*Sprint(i)*"st local factor:\n\n"; when 2: s := s* "\nLooking at "*Sprint(i)*"nd local factor:\n\n"; when 3: s := s* "\nLooking at "*Sprint(i)*"rd local factor:\n\n"; else s := s* "\nLooking at "*Sprint(i)*"th local factor:\n\n"; end case; // when "CR": end case; // local algebra over ground field B := MatrixAlgebra (A,P[i]); m := MaximalIdeals(B)[1]; // we know it's local // write residue field F := GF(# quo); case format: when "TXT": s := s* " Residue field = GF("*Sprint(#F)*")\n"; when "CR": s := s* "_ResidueField["*Sprint(N)*"]["*Sprint(i)*"] := "*Sprint(#F)*";\n"; end case; // write local dimension case format: when "TXT": s := s* " Local dimension = "*Sprint(Dimension(B))*"\n"; when "CR": s := s* "_LocalDimension["*Sprint(N)*"]["*Sprint(i)*"] := "*Sprint(Dimension(B))*";\n"; end case; // write B(m) = min_n m^n = (0) r := 1; n := m; while Dimension(n) ne 0 do r := r+1; n := n*m; end while; case format: when "TXT": s := s* " UPO = "*Sprint(r)*"\n"; when "CR": s := s* "_UPO["*Sprint(N)*"]["*Sprint(i)*"] := "*Sprint(r)*";\n"; end case; // calculate set of eigenvalues p := 3; T := {}; while (p le Bound(H)) do if (N mod p) ne 0 then E := SetToSequence(Eigenvalues(ChangeRing(RestrictMatrix(l[p],P[i]),F))); T := T join { E[j][1] : j in {1..#E} }; end if; p := NextPrime(p); end while; T := SetToSequence(T); // write eigenvalues case format: when "TXT": s := s* " Eigenvalues = { "; for j := 1 to #T-1 do s := s* Sprint(T[j])*", "; end for; s := s* Sprint(T[#T])*" }\n"; when "CR": s := s* "_Field := GF("*Sprint(#F)*"); \n"; s := s* "_Eigenvalues["*Sprint(N)*"]["*Sprint(i)*"] := [* "; for j := 1 to #T-1 do s := s* Sprint(T[j])*", "; end for; s := s* Sprint(T[#T])*"*]; \n"; end case; // write number of local factors // should be equal to r in F = GF(p,r) ???????????? C := ChangeRing(B,F); p := LocalDecomposition(C); case format: when "TXT": s := s* " Number of max. ideals over residue field = "*Sprint(#p)*"\n"; when "CR": s := s* "_NumberMaxIdealsSF["*Sprint(N)*"]["*Sprint(i)*"] := "*Sprint(#p)*";\n"; end case; end for; return s; end intrinsic; intrinsic HeckePropsToFile ( H :: Rec, file :: MonStgElt : format := "TXT") {Same as HeckePropsToString. The output string is appended to the specified file.} s := HeckePropsToString(H : format := format); PrintFile (file, s); return; end intrinsic; intrinsic CreateFilePropsCR ( file :: MonStgElt ) {Creates a file for storing MAGMA readable properties (for use with HeckePropsToFile in format "CR").} s := "_Bound := [];\n"; s := s*"_NumberMaxIdeals := [];\n"; s := s*"_QuadClassNumber := [];\n"; s := s*"_ResidueField := [];\n"; s := s*"_LocalDimension := [];\n"; s := s*"_NumberMaxIdealsSF := [];\n"; s := s*"_Eigenvalues := [];\n"; s := s*"_UPO := [];\n"; PrintFile (file, s : Overwrite := true); return; end intrinsic;