## Modular symbols

Let Δ0 := Div^0(ℙ^1(ℚ)) be the abelian group of divisors of degree 0 on the rational projective line. The standard GL(2,ℚ) action on ℙ^1(ℚ) via homographies naturally extends to Δ0. Given

* G a finite index subgroup of SL(2,ℤ),

* a field F and a finite dimensional representation V/F of GL(2,ℚ),

we consider the space of modular symbols M := HomG0, V). This finite dimensional F-vector space is a G-module, canonically isomorphic to H^1c(X(G), V), and allows to compute modular forms for G.

Currently, we only support the groups Γ0(N) (N > 0 an integer) and the representations Vk = ℚ[X,Y]k-2 (k ≥ 2 an integer) over ℚ. We represent a space of modular symbols by an ms structure, created by the function msinit. It encodes basic data attached to the space: chosen ℤ[G]-generators (gi) for Δ0 (and relations among those) and an F-basis of M. A modular symbol s is thus given either in terms of this fixed basis, or as a collection of values s(gi) satisfying certain relations.

A subspace of M (e.g. the cuspidal or Eisenstein subspaces, the new or old modular symbols, etc.) is given by a structure allowing quick projection and restriction of linear operators; its first component is a matrix whose columns form an F-basis of the subspace.

#### msatkinlehner(M, Q, {H})

Let M be a full modular symbol space of level N, as given by msinit, let Q | N, (Q,N/Q) = 1, and let H be a subspace stable under the Atkin-Lehner involution wQ. Return the matrix of wQ acting on H (M if omitted).

  ? M = msinit(36,2); \\ M2(Gamma0(36))
? w = msatkinlehner(M,4); w^2 == 1
%2 = 1
? #w   \\ involution acts on a 13-dimensional space
%3 = 13
? M = msinit(36,2, -1); \\ M2(Gamma0(36))^-
? w = msatkinlehner(M,4); w^2 == 1
%5 = 1
? #w
%6 = 4


The library syntax is GEN msatkinlehner(GEN M, long Q, GEN H = NULL).

#### mscosets(gen, inH)

gen being a system of generators for a group G and H being a subgroup of finite index in G, return a list of right cosets of H\G and the right action of G on H\G. The subgroup H is given by a criterion inH (closure) deciding whether an element of G belongs to H. The group G is restricted to types handled by generic multiplication (*) and inversion (g^(-1)), such as matrix groups or permutation groups.

Let gens = [g1,..., gr]. The function returns [C,M] where C lists the h = [G:H] representatives [γ1,..., γh] for the right cosets Hγ1,...,Hγh; γ1 is always the neutral element in G. For all i ≤ h, j ≤ r, if M[i][j] = k then H γi gj = Hγk.

  ? PSL2 = [[0,1;-1,0], [1,1;0,1]];  \\ S and T
\\ G = PSL2, H = Gamma0(2)
? [C, M] = mscosets(PSL2, g->g[2,1] % 2 == 0);
? C \\ three cosets
%3 = [[1, 0; 0, 1], [0, 1; -1, 0], [0, 1; -1, -1]]
? M
%4 = [Vecsmall([2, 1]), Vecsmall([1, 3]), Vecsmall([3, 2])]


Looking at M we see that S belongs to the second coset and T to the first (trivial) coset.

The library syntax is GEN mscosets0(GEN gen, GEN inH). Also available is the function GEN mscosets(GEN G, void *E, long (*inH)(void *, GEN))

#### mscuspidal(M, {flag = 0})

M being a full modular symbol space, as given by msinit, return its cuspidal part S. If flag = 1, return [S,E] its decomposition into cuspidal and Eisenstein parts.

A subspace is given by a structure allowing quick projection and restriction of linear operators; its first component is a matrix with integer coefficients whose columns form a ℚ-basis of the subspace.

  ? M = msinit(2,8, 1); \\ M8(Gamma0(2))^+
? [S,E] = mscuspidal(M, 1);
? E  \\ 2-dimensional
%3 =
[0 -10]

[0 -15]

[0  -3]

[1   0]

? S  \\ 1-dimensional
%4 =
[ 3]



[ 6]

[-8]


The library syntax is GEN mscuspidal(GEN M, long flag).

#### msdim(M)

M being a full modular symbol space or subspace, for instance as given by msinit or mscuspidal, return its dimension as a ℚ-vector space.

  ? M = msinit(11,4); msdim(M)
%1 = 6
? M = msinit(11,4,1); msdim(M)
%2 = 4 \\ dimension of the '+' part
? [S,E] = mscuspidal(M,1);
? [msdim(S), msdim(E)]
%4 = [2, 2]


Note that mfdim([N,k]) is going to be much faster if you only need the dimension of the space and not really to work with it. This function is only useful to quickly check the dimension of an existing space.

The library syntax is long msdim(GEN M).

#### mseisenstein(M)

M being a full modular symbol space, as given by msinit, return its Eisenstein subspace. A subspace is given by a structure allowing quick projection and restriction of linear operators; its first component is a matrix with integer coefficients whose columns form a ℚ-basis of the subspace. This is the same basis as given by the second component of mscuspidal(M, 1).

  ? M = msinit(2,8, 1); \\ M8(Gamma0(2))^+
? E = mseisenstein(M);
? E  \\ 2-dimensional
%3 =
[0 -10]

[0 -15]

[0  -3]

[1   0]

? E == mscuspidal(M,1)
%4 = 1


The library syntax is GEN mseisenstein(GEN M).

#### mseval(M, s, {p})

Let Δ0 := Div^0(ℙ^1 (ℚ)). Let M be a full modular symbol space, as given by msinit, let s be a modular symbol from M, i.e. an element of HomG0, V), and let p = [a,b] ∈ Δ0 be a path between two elements in ℙ^1(ℚ), return s(p) ∈ V. The path extremities a and b may be given as t_INT, t_FRAC or oo = (1:0); it is also possible to describe the path by a 2 x 2 integral matrix whose columns give the two cusps. The symbol s is either

* a t_COL coding a modular symbol in terms of the fixed basis of HomG0,V) chosen in M; if M was initialized with a nonzero sign (+ or -), then either the basis for the full symbol space or the ±-part can be used (the dimension being used to distinguish the two).

* a t_MAT whose columns encode modular symbols as above. This is much faster than evaluating individual symbols on the same path p independently.

* a t_VEC (vi) of elements of V, where the vi = s(gi) give the image of the generators gi of Δ0, see mspathgens. We assume that s is a proper symbol, i.e. that the vi satisfy the mspathgens relations.

If p is omitted, convert a single symbol s to the second form: a vector of the s(gi). A t_MAT is converted to a vector of such.

  ? M = msinit(2,8,1); \\ M8(Gamma0(2))^+
? g = mspathgens(M)
%2 = [[+oo, 0], [0, 1]]
? N = msnew(M); #N \\ Q-basis of new subspace, dimension 1
%3 = 1
? s = N[,1]         \\ t_COL representation
%4 = [-3, 6, -8]~
? S = mseval(M, s)   \\ t_VEC representation
%5 = [64*x^6-272*x^4+136*x^2-8, 384*x^5+960*x^4+192*x^3-672*x^2-432*x-72]
? mseval(M,s, g)
%6 = 64*x^6 - 272*x^4 + 136*x^2 - 8
? mseval(M,S, g)
%7 = 64*x^6 - 272*x^4 + 136*x^2 - 8


Note that the symbol should have values in V = ℚ[x,y]k-2, we return the de-homogenized values corresponding to y = 1 instead.

The library syntax is GEN mseval(GEN M, GEN s, GEN p = NULL).

#### msfarey(F, inH, {&CM})

F being a Farey symbol attached to a group G contained in PSL2(ℤ) and H a subgroup of G, return a Farey symbol attached to H. The subgroup H is given by a criterion inH (closure) deciding whether an element of G belongs to H. The symbol F can be created using

* mspolygon: G = Γ0(N), which runs in time Õ(N);

* or msfarey itself, which runs in time O([G:H]^2).

If present, the argument CM is set to mscosets(F), giving the right cosets of H \G and the action of G by right multiplication. Since msfarey's algorithm is quadratic in the index [G:H], it is advisable to construct subgroups by a chain of inclusions if possible.

  \\ Gamma0(N)
G0(N) = mspolygon(N);

\\ Gamma1(N): direct construction, slow
G1(N) = msfarey(mspolygon(1), g -> my(a = g[1,1]%N, c = g[2,1]%N);\
c == 0 && (a == 1 || a == N-1));
\\ Gamma1(N) via Gamma0(N): much faster
G1(N) = msfarey(G0(N), g -> my(a=g[1,1]%N); a==1 || a==N-1);


Note that the simpler criterion g[1,1]%N == 1 would not be correct since it must apply to elements of PSL2(ℤ) hence be invariant under g  ⟼ -g. Here are other examples:

  \\ Gamma(N)
G(N) = msfarey(G1(N), g -> g[1,2]%N==0);

G_00(N) = msfarey(G0(N), x -> x[1,2]%N==0);
G10(N1,N2) = msfarey(G0(1), x -> x[2,1]%N1==0 && x[1,2]%N2==0);

\\ Gamma0(91) has 4 elliptic points of order 3, Gamma1(91) has none
D0 = mspolygon(G0(91), 2);
D1 = mspolygon(G1(91), 2);
write("F.tex","\\documentclass{article}\\usepackage{tikz}\\begin{document}",\
D0,"\n",D1,"\\end{document}");


The library syntax is GEN msfarey0(GEN F, GEN inH, GEN *CM = NULL). Also available is GEN msfarey(GEN F, void *E, long (*inH)(void *, GEN), GEN *pCM).

#### msfromcusp(M, c)

Returns the modular symbol attached to the cusp c, where M is a modular symbol space of level N, attached to G = Γ0(N). The cusp c in ℙ^1(ℚ)/G is given either as oo ( = (1:0)) or as a rational number a/b ( = (a:b)). The attached symbol maps the path [b] - [a] ∈ Div^0 (ℙ^1(ℚ)) to Ec(b) - Ec(a), where Ec(r) is 0 when r != c and Xk-2 | γr otherwise, where γr.r = (1:0). These symbols span the Eisenstein subspace of M.

  ? M = msinit(2,8);  \\  M8(Gamma0(2))
? E =  mseisenstein(M);
? E \\ two-dimensional
%3 =
[0 -10]

[0 -15]

[0  -3]

[1   0]

? s = msfromcusp(M,oo)
%4 = [0, 0, 0, 1]~
? mseval(M, s)
%5 = [1, 0]
? s = msfromcusp(M,1)
%6 = [-5/16, -15/32, -3/32, 0]~
? mseval(M,s)
%7 = [-x^6, -6*x^5 - 15*x^4 - 20*x^3 - 15*x^2 - 6*x - 1]


In case M was initialized with a nonzero sign, the symbol is given in terms of the fixed basis of the whole symbol space, not the + or - part (to which it need not belong).

  ? M = msinit(2,8, 1);  \\  M8(Gamma0(2))^+
? E =  mseisenstein(M);
? E \\ still two-dimensional, in a smaller space
%3 =
[ 0 -10]

[ 0   3]

[-1   0]

? s = msfromcusp(M,oo) \\ in terms of the basis for M8(Gamma0(2)) !
%4 = [0, 0, 0, 1]~
? mseval(M, s) \\ same symbol as before
%5 = [1, 0]


The library syntax is GEN msfromcusp(GEN M, GEN c).

#### msfromell(E, {sign = 0})

Let E/ℚ be an elliptic curve of conductor N. For ϵ = ±1, we define the (cuspidal, new) modular symbol x^ϵ in H^1c(X0(N),ℚ)^ϵ attached to E. For all primes p not dividing N we have Tp(x^ϵ) = ap x^ϵ, where ap = p+1-#E(𝔽p).

Let Ω^ += E.omega be the real period of E (integration of the Néron differential dx/(2y+a_1x+a3) on the connected component of E(ℝ), i.e. the generator of H1(E,ℤ)^+) normalized by Ω^+ > 0. Let iΩ^- the integral on a generator of H1(E,ℤ)^- with Ω^- ∈ ℝ > 0. If c_ oo is the number of connected components of E(ℝ), Ω^- is equal to (-2/c_ oo ) x imag(E.omega). The complex modular symbol is defined by F: δ → 2iπ ∫δ f(z) dz The modular symbols x^ϵ are normalized so that F = x^+ Ω^+ + x^- iΩ^-. In particular, we have x^+(-[ oo ]) = L(E,1) / Ω^+, which defines x± unless L(E,1) = 0. Furthermore, for all fundamental discriminants D such that ϵ.D > 0, we also have ∑0 ≤ a < |D| (D|a) x^ϵ([a/|D|]-[ oo ]) = L(E,(D|.),1) / Ωϵ, where (D|.) is the Kronecker symbol. The period Ω^- is also 2/c_ oo x the real period of the twist E(-4) = elltwist(E,-4).

This function returns the pair [M, x], where M is msinit(N,2) and x is xsign as above when sign = ±1, and x = [x^+,x^-, LE] when sign is 0, where LE is a matrix giving the canonical ℤ-lattice attached to E in the sense of mslattice applied to ℚ x^+ + ℚ x^-. Explicitly, it is generated by (x+,x-) when E(ℝ) has two connected components and by (x+ - x-,2x^-) otherwise.

The modular symbols x^± are given as a t_COL (in terms of the fixed basis of HomG0,ℚ) chosen in M).

  ? E=ellinit([0,-1,1,-10,-20]);  \\ X0(11)
? [M,xp]= msfromell(E,1);
? xp
%3 = [1/5, -1/2, -1/2]~
? [M,x]= msfromell(E);
? x    \\  x^+, x^- and LE
%5 = [[1/5, -1/2, -1/2]~, [0, 1/2, -1/2]~, [1/5, 0; -1, 1; 0, -1]]
? p = 23; (mshecke(M,p) - ellap(E,p))*x
%6 = [0, 0, 0]~ \\ true at all primes, including p = 11; same for x
? (mshecke(M,p) - ellap(E,p))*x == 0
%7 = 1


Instead of a single curve E, one may use instead a vector of isogenous curves. The function then returns M and the vector of attached modular symbols.

The library syntax is GEN msfromell(GEN E, long sign).

#### msfromhecke(M, v, {H})

Given a msinit M and a vector v of pairs [p, P] (where p is prime and P is a polynomial with integer coefficients), return a basis of all modular symbols such that P(Tp)(s) = 0. If H is present, it must be a Hecke-stable subspace and we restrict to s ∈ H. When Tp has a rational eigenvalue and P(x) = x-ap has degree 1, we also accept the integer ap instead of P.

  ? E = ellinit([0,-1,1,-10,-20]) \\11a1
? ellap(E,2)
%2 = -2
? ellap(E,3)
%3 = -1
? M = msinit(11,2);
? S = msfromhecke(M, [[2,-2],[3,-1]])
%5 =
[ 1  1]

[-5  0]

[ 0 -5]
? mshecke(M, 2, S)
%6 =
[-2  0]

[ 0 -2]

? M = msinit(23,4);
? S = msfromhecke(M, [[5, x^4-14*x^3-244*x^2+4832*x-19904]]);
? factor( charpoly(mshecke(M,5,S)) )
%9 =
[x^4 - 14*x^3 - 244*x^2 + 4832*x - 19904 2]


The library syntax is GEN msfromhecke(GEN M, GEN v, GEN H = NULL).

#### msgetlevel(M)

M being a full modular symbol space, as given by msinit, return its level N.

The library syntax is long msgetlevel(GEN M).

#### msgetsign(M)

M being a full modular symbol space, as given by msinit, return its sign: ±1 or 0 (unset).

  ? M = msinit(11,4, 1);
? msgetsign(M)
%2 = 1
? M = msinit(11,4);
? msgetsign(M)
%4 = 0


The library syntax is long msgetsign(GEN M).

#### msgetweight(M)

M being a full modular symbol space, as given by msinit, return its weight k.

  ? M = msinit(11,4);
? msgetweight(M)
%2 = 4


The library syntax is long msgetweight(GEN M).

#### mshecke(M, p, {H})

M being a full modular symbol space, as given by msinit, p being a prime number, and H being a Hecke-stable subspace (M if omitted) return the matrix of Tp acting on H (Up if p divides N). Result is undefined if H is not stable by Tp (resp. Up).

  ? M = msinit(11,2); \\ M2(Gamma0(11))
? T2 = mshecke(M,2)
%2 =
[3  0  0]

[1 -2  0]

[1  0 -2]
? M = msinit(11,2, 1); \\ M2(Gamma0(11))^+
? T2 = mshecke(M,2)
%4 =
[ 3  0]

[-1 -2]

? N = msnew(M) \\ Q-basis of new cuspidal subspace
%5 =
[-2]

[-5]

? p = 1009; mshecke(M, p, N) \\ action of T_1009 on N
%6 =
[-10]
? ellap(ellinit("11a1"), p)
%7 = -10


The library syntax is GEN mshecke(GEN M, long p, GEN H = NULL).

#### msinit(G, V, {sign = 0})

Given G a finite index subgroup of SL(2,ℤ) and a finite dimensional representation V of GL(2,ℚ), creates a space of modular symbols, the G-module HomG(Div^0(ℙ^1 (ℚ)), V). This is canonically isomorphic to H^1c(X(G), V), and allows to compute modular forms for G. If sign is present and nonzero, it must be ±1 and we consider the subspace defined by Ker (σ - sign), where σ is induced by [-1,0;0,1]. Currently the only supported groups are the Γ0(N), coded by the integer N > 0. The only supported representation is Vk = ℚ[X,Y]k-2, coded by the integer k ≥ 2.

  ? M = msinit(11,2); msdim(M) \\ Gamma0(11), weight 2
%1 = 3
? mshecke(M,2) \\ T2 acting on M
%2 =
[3  1  1]

[0 -2  0]

[0  0 -2]
? msstar(M) \\ * involution
%3 =
[1 0 0]

[0 0 1]

[0 1 0]

? Mp = msinit(11,2, 1); msdim(Mp) \\ + part
%4 = 2
? mshecke(Mp,2)  \\ T2 action on M^+
%5 =
[3  2]

[0 -2]
? msstar(Mp)
%6 =
[1 0]

[0 1]


The library syntax is GEN msinit(GEN G, GEN V, long sign).

#### msissymbol(M, s)

M being a full modular symbol space, as given by msinit, check whether s is a modular symbol attached to M. If A is a matrix, check whether its columns represent modular symbols and return a 0-1 vector.

  ? M = msinit(7,8, 1); \\ M8(Gamma0(7))^+
? A = msnew(M);
? s = A[,1];
? msissymbol(M, s)
%4 = 1
? msissymbol(M, A)
%5 = [1, 1, 1]
? S = mseval(M,s);
? msissymbol(M, S)
%7 = 1
? [g,R] = mspathgens(M); g
%8 = [[+oo, 0], [0, 1/2], [1/2, 1]]
? #R  \\ 3 relations among the generators gi
%9 = 3
? T = S; T++; \\ randomly perturb S(g3)
? msissymbol(M, T)
%11 = 0  \\ no longer satisfies the relations


The library syntax is GEN msissymbol(GEN M, GEN s).

#### mslattice(M, {H})

Let Δ0 := Div^0(ℙ^1(ℚ)) and Vk = ℚ[x,y]k-2. Let M be a full modular symbol space, as given by msinit and let H be a subspace, e.g. as given by mscuspidal. This function returns a canonical ℤ structure on H defined as follows. Consider the map c: M = HomΓ0(N)0, Vk) → H^1(Γ0(N), Vk) given by φ : — >class(γ → φ({0, γ-1 0})). Let Lk = ℤ[x,y]k-2 be the natural ℤ-structure of Vk. The result of mslattice is a ℤ-basis of the inverse image by c of H^1(Γ0(N), Lk) in the space of modular symbols generated by H.

For user convenience, H can be defined by a matrix representing the ℚ-basis of H (in terms of the canonical ℚ-basis of M fixed by msinit and used to represent modular symbols).

If omitted, H is the cuspidal part of M as given by mscuspidal. The Eisenstein part HomΓ0(N)(Div(ℙ^1(ℚ)), Vk) is in the kernel of c, so the result has no meaning for the Eisenstein part H.

  ? M=msinit(11,2);
? [S,E] = mscuspidal(M,1); S \\ a primitive Q-basis of S
%2 =
[ 1  1]
[-5  0]
[ 0 -5]
? mslattice(M,S)
%3 =
[-1/5 -1/5]
[   1    0]
[   0    1]
? mslattice(M,E)
%4 =



? M=msinit(5,4);
? S=mscuspidal(M); S
%6 =
[  7  20]
[  3   3]
[-10 -23]
[-30 -30]
? mslattice(M,S)
%7 =
[-1/10 -11/130]
[    0  -1/130]
[ 1/10    6/65]
[    0    1/13]


The library syntax is GEN mslattice(GEN M, GEN H = NULL).

#### msnew(M)

M being a full modular symbol space, as given by msinit, return the new part of its cuspidal subspace. A subspace is given by a structure allowing quick projection and restriction of linear operators; its first component is a matrix with integer coefficients whose columns form a ℚ-basis of the subspace.

  ? M = msinit(11,8, 1); \\ M8(Gamma0(11))^+
? N = msnew(M);
? #N  \\ 6-dimensional
%3 = 6


The library syntax is GEN msnew(GEN M).

#### msomseval(Mp, PHI, path)

Return the vectors of moments of the p-adic distribution attached to the path path by the overconvergent modular symbol PHI.

  ? M = msinit(3,6,1);
? phi = [5,-3,-1]~;
? msissymbol(M,phi)
%4 = 1
? PHI = mstooms(Mp,phi);
? ME = msomseval(Mp,PHI,[oo, 0]);


The library syntax is GEN msomseval(GEN Mp, GEN PHI, GEN path).

#### mspadicL(mu, {s = 0}, {r = 0})

Returns the value (or r-th derivative) on a character χ^s of ℤp* of the p-adic L-function attached to mu.

Let Φ be the p-adic distribution-valued overconvergent symbol attached to a modular symbol φ for Γ0(N) (eigenvector for TN(p) for the eigenvalue ap). Then Lp(Φ,χ^s) = Lp(μ,s) is the p-adic L function defined by Lp(Φ,χ^s) = ∫p* χ^s(z) dμ(z) where μ is the distribution on ℤp* defined by the restriction of Φ([ oo ]-) to ℤp*. The r-th derivative is taken in direction <χ>: Lp(r)(Φ,χ^s) = ∫p* χ^s(z) (log z)^r dμ(z). In the argument list,

* mu is as returned by mspadicmoments (distributions attached to Φ by restriction to discs a + p^νℤp, (a,p) = 1).

* s = [s1,s2] with s1 ∈ ℤ ⊂ ℤp and s2 mod p-1 or s2 mod 2 for p = 2, encoding the p-adic character χ^s := < χ >s1 τs2; here χ is the cyclotomic character from Gal(ℚpp^ oo )/ℚp) to ℤp*, and τ is the Teichmüller character (for p > 2 and the character of order 2 on (ℤ/4ℤ)* if p = 2); for convenience, the character [s,s] can also be represented by the integer s.

When ap is a p-adic unit, Lp takes its values in ℚp. When ap is not a unit, it takes its values in the two-dimensional ℚp-vector space Dcris(M(φ)) where M(φ) is the "motive" attached to φ, and we return the two p-adic components with respect to some fixed ℚp-basis.

  ? M = msinit(3,6,1); phi=[5, -3, -1]~;
? msissymbol(M,phi)
%2 = 1
? Mp = mspadicinit(M, 5, 4);
? mu = mspadicmoments(Mp, phi); \\ no twist
\\ End of initializations

%5 = 5 + 2*5^2 + 2*5^3 + 2*5^4 + ...
? mspadicL(mu,1) \\ Lp(chi), zero for parity reasons
%6 = [O(5^13)]~
%7 = 3 + 4*5 + 4*5^2 + 3*5^5 + ...
%8 = 3 + 5 + 2*5^2 + 2*5^3 + ...
%9 = 3*5 + 2*5^2 + 5^3 + 2*5^7 + 5^8 + 5^10 + 2*5^11 + O(5^13)
%10 = 2*5 + 4*5^2 + 3*5^3 + ...
? mspadicL(mu, 2, 1) \\ Lp'(chi^2)
%11 = 4*5 + 3*5^2 + 5^3 + 5^4 + ...


Now several quadratic twists: mstooms is indicated.

  ? PHI = mstooms(Mp,phi);
? mu = mspadicmoments(Mp, PHI, 12); \\ twist by 12
%14 = 5 + 5^2 + 5^3 + 2*5^4 + ...
? mu = mspadicmoments(Mp, PHI, 8); \\ twist by 8
%16 = 2 + 3*5 + 3*5^2 + 2*5^4 + ...
? mu = mspadicmoments(Mp, PHI, -3); \\ twist by -3 < 0
%18 = O(5^13) \\ always 0, phi is in the + part and D < 0


One can locate interesting symbols of level N and weight k with msnew and mssplit. Note that instead of a symbol, one can input a 1-dimensional Hecke-subspace from mssplit: the function will automatically use the underlying basis vector.

  ? M=msinit(5,4,1); \\ M4(Gamma0(5))^+
? L = mssplit(M, msnew(M)); \\ list of irreducible Hecke-subspaces
? phi = L; \\ one Galois orbit of newforms
? #phi \\... this one is rational
%4 = 1
? Mp = mspadicinit(M, 3, 4);
%7 = 1 + 3 + 3^3 + 3^4 + 2*3^5 + 3^6 + O(3^9)

? M = msinit(11,8, 1); \\ M8(Gamma0(11))^+
? Mp = mspadicinit(M, 3, 4);
? L = mssplit(M, msnew(M));
? phi = L; #phi \\ ... this one is two-dimensional
%11 = 2
***                    ^ —  —  —  —  —  — --
*** mspadicmoments: incorrect type in mstooms [dimQ (eigenspace) > 1]


The library syntax is GEN mspadicL(GEN mu, GEN s = NULL, long r).

M being a full modular symbol space, as given by msinit, and p a prime, initialize technical data needed to compute with overconvergent modular symbols, modulo p^n. If flag is unset, allow all symbols; else initialize only for a restricted range of symbols depending on flag: if flag = 0 restrict to ordinary symbols, else restrict to symbols φ such that Tp(φ) = ap φ, with vp(ap) ≥ flag, which is faster as flag increases. (The fastest initialization is obtained for flag = 0 where we only allow ordinary symbols.) For supersingular eigensymbols, such that p | ap, we must further assume that p does not divide the level.

  ? E = ellinit("11a1");
? [M,phi] = msfromell(E,1);
? ellap(E,3)
%3 = -1
? Mp = mspadicinit(M, 3, 10, 0); \\ commit to ordinary symbols
? PHI = mstooms(Mp,phi);


If we restrict the range of allowed symbols with flag (for faster initialization), exceptions will occur if vp(ap) violates this bound:

  ? E = ellinit("15a1");
? [M,phi] = msfromell(E,1);
? ellap(E,7)
%3 = 0
? Mp = mspadicinit(M,7,5,0); \\ restrict to ordinary symbols
? PHI = mstooms(Mp,phi)
***   at top-level: PHI=mstooms(Mp,phi)
***                     ^ —  —  —  —  —
*** mstooms: incorrect type in mstooms [vp(ap) > mspadicinit flag] (t_VEC).
? Mp = mspadicinit(M,7,5); \\ no restriction
? PHI = mstooms(Mp,phi);


This function uses O(N^2(n+k)^2p) memory, where N is the level of M.

The library syntax is GEN mspadicinit(GEN M, long p, long n, long flag).

#### mspadicmoments(Mp, PHI, {D = 1})

Given Mp from mspadicinit, an overconvergent eigensymbol PHI from mstooms and a fundamental discriminant D coprime to p, let PHI^D denote the twisted symbol. This function computes the distribution μ = PHI^D( - oo ]) | ℤp* restricted to ℤp*. More precisely, it returns the moments of the p-1 distributions PHI^D(-[ oo ]) | (a + pℤp), 0 < a < p. We also allow PHI to be given as a classical symbol, which is then lifted to an overconvergent symbol by mstooms; but this is wasteful if more than one twist is later needed.

The returned data μ (p-adic distributions attached to PHI) can then be used in mspadicL or mspadicseries. This precomputation allows to quickly compute derivatives of different orders or values at different characters.

  ? M = msinit(3,6, 1);
? phi = [5,-3,-1]~;
? msissymbol(M, phi)
%3 = 1
? p = 5; mshecke(M,p) * phi  \\ eigenvector of T5, a5 = 6
%4 = [30, -18, -6]~
? Mp = mspadicinit(M, p, 10, 0); \\ restrict to ordinary symbols, mod p^10
? PHI = mstooms(Mp, phi);
%8 = 5 + 2*5^2 + 2*5^3 + ...
? mu = mspadicmoments(Mp, PHI, 12); \\ twist by 12
%10 = 5 + 5^2 + 5^3 + 2*5^4 + ...


The library syntax is GEN mspadicmoments(GEN Mp, GEN PHI, long D).

Let Φ be the p-adic distribution-valued overconvergent symbol attached to a modular symbol φ for Γ0(N) (eigenvector for TN(p) for the eigenvalue ap). If μ is the distribution on ℤp* defined by the restriction of Φ([ oo ]-) to ℤp*, let Lp(μ,τi)(x) = ∫p* τ^i(t) (1+x)logp(t)/logp(u)dμ(t) Here, τ is the Teichmüller character and u is a specific multiplicative generator of 1+2pℤp. (Namely 1+p if p > 2 or 5 if p = 2.) To explain the formula, let G_ oo := Gal(ℚ(μp oo )/ ℚ), let χ:G_ oo → ℤp* be the cyclotomic character (isomorphism) and γ the element of G_ oo such that χ(γ) = u; then χ(γ)logp(t)/logp(u) = <t >.

The p-padic precision of individual terms is maximal given the precision of the overconvergent symbol μ.

  ? [M,phi] = msfromell(ellinit("17a1"),1);
? mu = mspadicmoments(Mp, phi,1); \\ overconvergent symbol
%4 = (4 + 3*5 + 4*5^2 + 2*5^3 + 2*5^4 + 5^5 + 4*5^6 + 3*5^7 + O(5^9)) \
+ (3 + 3*5 + 5^2 + 5^3 + 2*5^4 + 5^6 + O(5^7))*x \
+ (2 + 3*5 + 5^2 + 4*5^3 + 2*5^4 + O(5^5))*x^2 \
+ (3 + 4*5 + 4*5^2 + O(5^3))*x^3 \
+ (3 + O(5))*x^4 + O(x^5)


An example with nonzero Teichmüller:

  ? [M,phi] = msfromell(ellinit("11a1"),1);
%4 = (2 + 3 + 3^2 + 2*3^3 + 2*3^5 + 3^6 + 3^7 + 3^10 + 3^11 + O(3^12)) \
+ (1 + 3 + 2*3^2 + 3^3 + 3^5 + 2*3^6 + 2*3^8 + O(3^9))*x \
+ (1 + 2*3 + 3^4 + 2*3^5 + O(3^6))*x^2 \
+ (3 + O(3^2))*x^3 + O(x^4)


Supersingular example (not checked)

  ? E = ellinit("17a1"); ellap(E,3)
%1 = 0
? [M,phi] = msfromell(E,1);
%5 = [(2*3^-1 + 1 + 3 + 3^2 + 3^3 + 3^4 + 3^5 + 3^6 + O(3^7)) \
+ (2 + 3^3 + O(3^5))*x \
+ (1 + 2*3 + O(3^2))*x^2 + O(x^3),\
(3^-1 + 1 + 3 + 3^2 + 3^3 + 3^4 + 3^5 + 3^6 + O(3^7)) \
+ (1 + 2*3 + 2*3^2 + 3^3 + 2*3^4 + O(3^5))*x \
+ (3^-2 + 3^-1 + O(3^2))*x^2 + O(3^-2)*x^3 + O(x^4)]


Example with a twist:

  ? E = ellinit("11a1");
? [M,phi] = msfromell(E,1);
? mu = mspadicmoments(Mp, phi,5); \\ twist by 5
%5 = (2*3^2 + 2*3^4 + 3^5 + 3^6 + 2*3^7 + 2*3^10 + O(3^12)) \
+ (2*3^2 + 2*3^6 + 3^7 + 3^8 + O(3^9))*x \
+ (3^3 + O(3^6))*x^2 + O(3^2)*x^3 + O(x^4)
%6 = [2*3^2 + 2*3^4 + 3^5 + 3^6 + 2*3^7 + 2*3^10 + O(3^12)]~
%7 = 2 + 2*3^2 + 3^3 + 2*3^4 + 2*3^5 + 3^6 + 2*3^7 + O(3^10)
? mspadicseries(mu,1) \\ must be 0
%8 = O(3^12) + O(3^9)*x + O(3^6)*x^2 + O(3^2)*x^3 + O(x^4)


The library syntax is GEN mspadicseries(GEN mu, long i).

#### mspathgens(M)

Let Δ0 := Div^0(ℙ^1(ℚ)). Let M being a full modular symbol space, as given by msinit, return a set of ℤ[G]-generators for Δ0. The output is [g,R], where g is a minimal system of generators and R the vector of ℤ[G]-relations between the given generators. A relation is coded by a vector of pairs [ai,i] with ai ∈ ℤ[G] and i the index of a generator, so that ∑i ai g[i] = 0.

An element [v]-[u] in Δ0 is coded by the "path" [u,v], where oo denotes the point at infinity (1:0) on the projective line. An element of ℤ[G] is either an integer n ( = n [id2]) or a "factorization matrix": the first column contains distinct elements gi of G and the second integers ni and the matrix codes ∑ ni [gi]:

  ? M = msinit(11,8); \\ M8(Gamma0(11))
? [g,R] = mspathgens(M);
? g
%3 = [[+oo, 0], [0, 1/3], [1/3, 1/2]] \\ 3 paths
? #R  \\ a single relation
%4 = 1
? r = R; #r \\ ...involving all 3 generators
%5 = 3
? r
%6 = [[1, 1; [1, 1; 0, 1], -1], 1]
? r
%7 = [[1, 1; [7, -2; 11, -3], -1], 2]
? r
%8 = [[1, 1; [8, -3; 11, -4], -1], 3]


The given relation is of the form ∑i (1-γi) gi = 0, with γi ∈ Γ0(11). There will always be a single relation involving all generators (corresponding to a round trip along all cusps), then relations involving a single generator (corresponding to 2 and 3-torsion elements in the group:

  ? M = msinit(2,8); \\ M8(Gamma0(2))
? [g,R] = mspathgens(M);
? g
%3 = [[+oo, 0], [0, 1]]


Note that the output depends only on the group G, not on the representation V.

The library syntax is GEN mspathgens(GEN M).

#### mspathlog(M, p)

Let Δ0 := Div^0(ℙ^1(ℚ)). Let M being a full modular symbol space, as given by msinit, encoding fixed ℤ[G]-generators (gi) of Δ0 (see mspathgens). A path p = [a,b] between two elements in ℙ^1(ℚ) corresponds to [b]-[a] ∈ Δ0. The path extremities a and b may be given as t_INT, t_FRAC or oo = (1:0). Finally, we also allow to input a path as a 2 x 2 integer matrix, whose first and second column give a and b respectively, with the convention [x,y]~ = (x:y) in ℙ^1(ℚ).

Returns (pi) in ℤ[G] such that p = ∑i pi gi.

  ? M = msinit(2,8); \\ M8(Gamma0(2))
? [g,R] = mspathgens(M);
? g
%3 = [[+oo, 0], [0, 1]]
? p = mspathlog(M, [1/2,2/3]);
? p
%5 =
[[1, 0; 2, 1] 1]

? p
%6 =
[[1, 0; 0, 1] 1]

[[3, -1; 4, -1] 1]
? mspathlog(M, [1,2;2,3]) == p  \\ give path via a 2x2 matrix
%7 = 1


Note that the output depends only on the group G, not on the representation V.

The library syntax is GEN mspathlog(GEN M, GEN p).

#### mspetersson(M, {F}, {G = F})

M being a full modular symbol space for Γ = Γ0(N), as given by msinit, calculate the intersection product {F, G} of modular symbols F and G on M = HomΓ0, Vk) extended to an hermitian bilinear form on M ⨂ ℂ whose radical is the Eisenstein subspace of M.

Suppose that f1 and f2 are two parabolic forms. Let F1 and F2 be the attached modular symbols Fi(δ) = ∫δ fi(z).(z X + Y)k-2 dz and let F1, F2 be the attached real modular symbols Fi(δ) = ∫δ Re(fi(z).(z X + Y)k-2 dz) Then we have

{ F1, F2 } = -2 (2i)k-2. Im( < f1,f2 > Petersson) and { F1, F2 } = (2i)k-2 < f1,f2 > Petersson In weight 2, the intersection product {F, G} has integer values on the ℤ-structure on M given by mslattice and defines a Riemann form on H^1par(Γ,ℝ).

For user convenience, we allow F and G to be matrices and return the attached Gram matrix. If F is omitted: treat it as the full modular space attached to M; if G is omitted, take it equal to F.

  ? M = msinit(37,2);
? C = mscuspidal(M);
%3 =
[ 0 -17 -8 -17]
[17   0 -8 -25]
[ 8   8  0 -17]
[17  25 17   0]
%4 =
[0 -1 0 -1]
[1  0 0 -1]
[0  0 0 -1]
[1  1 1  0]
? E = ellinit("33a1");
? [M,xpm] = msfromell(E); [xp,xm,L] = xpm;
%7 =
[0 -3]
[3  0]
? ellmoddegree(E)
%8 = [3, -126]


The coefficient 3 in the matrix is the degree of the modular parametrization.

The library syntax is GEN mspetersson(GEN M, GEN F = NULL, GEN G = NULL).

#### mspolygon(M, {flag = 0})

M describes a subgroup G of finite index in the modular group PSL2(ℤ), as given by msinit or a positive integer N (encoding the group G = Γ0(N)), or by msfarey (arbitrary subgroup). Return an hyperbolic polygon (Farey symbol) attached to G. More precisely:

* Its vertices are an ordered list in ℙ1(ℚ) and contain a representatives of all cusps.

* Its edges are hyperbolic arcs joining two consecutive vertices; each edge e is labelled by an integer μ(e) ∈ { oo ,2,3}.

* Given a path (a,b) between two elements of ℙ^1(ℚ), let (a,b) = (b,a) be the opposite path. There is an involution e → e* on the edges. We have μ(e) = oo if and only if e != e*; when μ(e) != 3, e is G-equivalent to e*, i.e. there exists γe ∈ G such that e = γe e*; if μ(e) = 3 there exists γe ∈ G of order 3 such that the hyperbolic triangle (e, γe e, γe^2 e) is invariant by γe. In all cases, to each edge we have attached γe ∈ G of order μ(e).

The polygon is given by a triple [E, A, g]

* The list E of its consecutive edges as matrices in M2(ℤ).

* The permutation A attached to the involution: if e = E[i] is the i-th edge, then A[i] is the index of e* in E.

* The list g of pairing matrices γe. Remark that γe* = γe-1 if μ(e) != 3, i.e., g[i]-1 = g[A[i]] whenever i != A[i] (μ(g[i]) = 1) or μ(g[i]) = 2 (g[i]^2 = 1). Modulo these trivial relations, the pairing matrices form a system of independant generators of G. Note that γe is elliptic if and only if e^ *= e.

The above data yields a fundamental domain for G acting on Poincaré's half-plane: take the convex hull of the polygon defined by

* The edges in E such that e != e* or e^ *= e, where the pairing matrix γe has order 2;

* The edges (r,t) and (t,s) where the edge e = (r,s) ∈ E is such that e = e* and γe has order 3 and the triangle (r,t,s) is the image of (0,exp(2iπ/3), oo ) by some element of PSL2(ℚ) formed around the edge.

Binary digits of flag mean:

1: return a normalized hyperbolic polygon if set, else a polygon with unimodular edges (matrices of determinant 1). A polygon is normalized in the sense of compact orientable surfaces if the distance d(a,a*) between an edge a and its image by the involution a* is less than 2, with equality if and only if a is linked with another edge b (a, b, a* et b* appear consecutively in E up to cyclic permutation). In particular, the vertices of all edges such that that d(a,a*) != 1 (distance is 0 or 2) are all equivalent to 0 modulo G. The external vertices of a a* such that d(a,a*) = 1 are also equivalent to 0; the internal vertices a∩ a* (a single point), together with 0, form a system of representatives of the cusps of G\ℙ1(ℚ). This is useful to compute the homology group H1(G,ℤ) as it gives a symplectic basis for the intersection pairing. In this case, the number of parabolic matrices (trace 2) in the system of generators G is 2(t-1), where t is the number of non equivalent cusps for G. This is currently only implemented for G = Γ0(N).

2: add graphical representations (in LaTeX form) for the hyperbolic polygon in Poincaré's half-space and the involution a → a* of the Farey symbol. The corresponding character strings can be included in a LaTeX document provided the preamble contains \usepackage{ tikz}.

  ? [V,A,g] = mspolygon(3);
? V
%2 = [[-1, 1; -1, 0], [1, 0; 0, 1], [0, 1; -1, 1]]
? A
%3 = Vecsmall([2, 1, 3])
? g
%4 = [[-1, -1; 0, -1], [1, -1; 0, 1], [1, -1; 3, -2]]
? [V,A,g, D1,D2] = mspolygon(11,2); \\ D1 and D2 contains pictures
? {write("F.tex",
"\\documentclass{article}\\usepackage{tikz}\\begin{document}"
D1, "\n", D2,
"\\end{document}");}

? [V1,A1] = mspolygon(6,1); \\ normalized
? V1
%8 = [[-1, 1; -1, 0], [1, 0; 0, 1], [0, 1; -1, 3],
[1, -2; 3, -5], [-2, 1; -5, 2], [1, -1; 2, -1]]
? A1
%9 = Vecsmall([2, 1, 4, 3, 6, 5])

? [V0,A0] = mspolygon(6);  \\ not normalized V* = V, d(V,V) = 3
? A0
%11 = Vecsmall([2, 1, 6, 5, 4, 3])

? [V,A] = mspolygon(14, 1);
? A
%13 = Vecsmall([2, 1, 4, 3, 6, 5, 9, 10, 7, 8])


One can see from this last example that the (normalized) polygon has the form (a1, a1*, a2, a2*, a3, a3*, a4, a5, a4*, a5*), that X0(14) is of genus 1 (in general the genus is the number of blocks of the form aba*b*), has no elliptic points (A has no fixed point) and 4 cusps (number of blocks of the form aa* plus 1). The vertices of edges a4 and a5 all project to 0 in X0(14): the paths a4 and a5 project as loops in X0(14) and give a symplectic basis of the homology H1(X0(14),ℤ).

  ? [V,A] = mspolygon(15);
? apply(matdet, V) \\ all unimodular
%2 = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
? [V,A] = mspolygon(15,1);
? apply(matdet, V) \\ normalized polygon but no longer unimodular edges
%4 = [1, 1, 1, 1, 2, 2, 47, 11, 47, 11]


The library syntax is GEN mspolygon(GEN M, long flag).

#### msqexpansion(M, projH, {B = seriesprecision})

M being a full modular symbol space, as given by msinit, and projH being a projector on a Hecke-simple subspace (as given by mssplit), return the Fourier coefficients an, n ≤ B of the corresponding normalized newform. If B is omitted, use seriesprecision.

This function uses a naive O(B^2 d^3) algorithm, where d = O(kN) is the dimension of Mk0(N)).

  ? M = msinit(11,2, 1); \\ M2(Gamma0(11))^+
? L = mssplit(M, msnew(M));
? msqexpansion(M,L, 20)
%3 = [1, -2, -1, 2, 1, 2, -2, 0, -2, -2, 1, -2, 4, 4, -1, -4, -2, 4, 0, 2]
? ellan(ellinit("11a1"), 20)
%4 = [1, -2, -1, 2, 1, 2, -2, 0, -2, -2, 1, -2, 4, 4, -1, -4, -2, 4, 0, 2]


The shortcut msqexpansion(M, s, B) is available for a symbol s, provided it is a Hecke eigenvector:

  ? E = ellinit("11a1");
? [M,S] = msfromell(E); [sp,sm] = S;
? msqexpansion(M,sp,10) \\ in the + eigenspace
%3 = [1, -2, -1, 2, 1, 2, -2, 0, -2, -2]
? msqexpansion(M,sm,10) \\ in the - eigenspace
%4 = [1, -2, -1, 2, 1, 2, -2, 0, -2, -2]
? ellan(E, 10)
%5 = [1, -2, -1, 2, 1, 2, -2, 0, -2, -2]


The library syntax is GEN msqexpansion(GEN M, GEN projH, long precdl).

#### mssplit(M, {H}, {dimlim})

Let M denote a full modular symbol space, as given by msinit(N,k,1) or msinit(N,k,-1) and let H be a Hecke-stable subspace of msnew(M) (the full new subspace if H is omitted). This function splits H into Hecke-simple subspaces. If dimlim is present and positive, restrict to subspaces of dimension ≤ dimlim. A subspace is given by a structure allowing quick projection and restriction of linear operators; its first component is a matrix with integer coefficients whose columns form a ℚ-basis of the subspace.

  ? M = msinit(11,8, 1); \\ M8(Gamma0(11))^+
? L = mssplit(M); \\ split msnew(M)
? #L
%3 = 2
? f = msqexpansion(M,L,5); f.mod
%4 = x^2 + 8*x - 44
? lift(f)
%5 = [1, x, -6*x - 27, -8*x - 84, 20*x - 155]
? g = msqexpansion(M,L,5); g.mod
%6 = x^4 - 558*x^2 + 140*x + 51744


To a Hecke-simple subspace corresponds an orbit of (normalized) newforms, defined over a number field. In the above example, we printed the polynomials defining the said fields, as well as the first 5 Fourier coefficients (at the infinite cusp) of one such form.

The library syntax is GEN mssplit(GEN M, GEN H = NULL, long dimlim).

#### msstar(M, {H})

M being a full modular symbol space, as given by msinit, return the matrix of the * involution, induced by complex conjugation, acting on the (stable) subspace H (M if omitted).

  ? M = msinit(11,2); \\ M2(Gamma0(11))
? w = msstar(M);
? w^2 == 1
%3 = 1


The library syntax is GEN msstar(GEN M, GEN H = NULL).

#### mstooms(Mp, phi)

Given Mp from mspadicinit, lift the (classical) eigen symbol phi to a p-adic distribution-valued overconvergent symbol in the sense of Pollack and Stevens. More precisely, let φ belong to the space W of modular symbols of level N, vp(N) ≤ 1, and weight k which is an eigenvector for the Hecke operator TN(p) for a nonzero eigenvalue ap and let N0 = lcm(N,p).

Under the action of TN0(p), φ generates a subspace W_φ of dimension 1 (if p | N) or 2 (if p does not divide N) in the space of modular symbols of level N0.

Let Vp = [p,0;0,1] and Cp = [ap,pk-1;-1,0]. When p does not divide N and ap is divisible by p, mstooms returns the lift Φ of (φ,φ|k Vp) such that TN0(p) Φ = Cp Φ

When p does not divide N and ap is not divisible by p, mstooms returns the lift Φ of φ - α-1 φ|k Vp which is an eigenvector of TN0(p) for the unit eigenvalue where α^2 - ap α + pk-1 = 0.

The resulting overconvergent eigensymbol can then be used in mspadicmoments, then mspadicL or mspadicseries.

  ? M = msinit(3,6, 1); p = 5;
? Tp = mshecke(M, p); factor(charpoly(Tp))
%2 =
[x - 3126 2]

[   x - 6 1]
? phi = matker(Tp - 6)[,1] \\ generator of p-Eigenspace, ap = 6
%3 = [5, -3, -1]~
? Mp = mspadicinit(M, p, 10, 0); \\ restrict to ordinary symbols, mod p^10
? PHI = mstooms(Mp, phi);
%7 = 5 + 2*5^2 + 2*5^3 + ...


A non ordinary symbol.

  ? M = msinit(4,6,1); p = 3;
? Tp = mshecke(M, p); factor(charpoly(Tp))
%2 =
[x - 244 3]

[ x + 12 1]
? phi = matker(Tp + 12)[,1] \\ ap = -12 is divisible by p = 3
%3 = [-1/32, -1/4, -1/32, 1]~
? msissymbol(M,phi)
%4 = 1

The library syntax is GEN mstooms(GEN Mp, GEN phi).