Ring of Drinfeld modular forms#
This module defines a class named DrinfeldModularFormsRing
.
Currently, the implementation only supports the full group modular group \(\mathrm{GL}_r(A)\) where \(A = \mathbb{F}_q[T]\).
The implementation is based on the following identification:
where \(g_i\) the \(i\)-th coefficient form of weight \(q^{i} - 1\).
EXAMPLES:
sage: from drinfeld_modular_forms import DrinfeldModularFormsRing
sage: q = 3
sage: A = GF(q)['T']
sage: K.<T> = Frac(A)
sage: M = DrinfeldModularFormsRing(K, 2) # rank 2
sage: M.gens() # generators
[g1, g2]
sage: M.inject_variables() # assign variables
Defining g1, g2
sage: g1.weight()
2
sage: g2.weight()
8
sage: M = DrinfeldModularFormsRing(K, 3) # rank 3
sage: M.gens()
[g1, g2, g3]
sage: [g.weight() for g in M.gens()] # list of the weights
[2, 8, 26]
sage: M.inject_variables()
Defining g1, g2, g3
sage: g1.weight() == 3 - 1
True
sage: g2.weight() == 3^2 - 1
True
sage: g3.weight() == 3^3 - 1
True
One can compute basis for any subspace of given weight:
sage: M = DrinfeldModularFormsRing(K, 4)
sage: M.basis_of_weight(q^4 - 1)
[g4,
g2^10,
g1*g3^3,
g1^2*g2^3*g3^2,
g1^3*g2^6*g3,
g1^4*g2^9,
g1^6*g2^2*g3^2,
g1^7*g2^5*g3,
g1^8*g2^8,
g1^10*g2*g3^2,
g1^11*g2^4*g3,
g1^12*g2^7,
g1^14*g3^2,
g1^15*g2^3*g3,
g1^16*g2^6,
g1^19*g2^2*g3,
g1^20*g2^5,
g1^23*g2*g3,
g1^24*g2^4,
g1^27*g3,
g1^28*g2^3,
g1^32*g2^2,
g1^36*g2,
g1^40]
We note that the elements of this ring may not be modular forms as as they may have mixed weight components:
sage: M = DrinfeldModularFormsRing(K, 4)
sage: M.inject_variables()
Defining g1, g2, g3, g4
sage: F = g1 + g2 + g3 + g4
sage: F.is_drinfeld_modular_form()
False
This is why we call these elements graded Drinfeld modular forms.
The rank 2 case
In rank 2 case, one can also compute the expansion at infinity of Drinfeld modular forms.
EXAMPLES:
sage: from drinfeld_modular_forms import DrinfeldModularFormsRing
sage: q = 3
sage: A = GF(q)['T']
sage: K.<T> = Frac(A)
sage: M = DrinfeldModularFormsRing(K, 2) # rank 2
sage: M.inject_variables()
Defining g1, g2
sage: g1.expansion()
1 + ((2*T^3+T)*t^2) + O(t^7)
sage: g2.expansion()
t^2 + 2*t^6 + O(t^8)
The returned series is a lazy power series, meaning that it can compute any coefficient at any precision on demands:
sage: g2[6]
2
sage: g2[24]
T^9 + 2*T^3
sage: g2[36]
2*T^9 + T^3
sage: g2[702] # long time
2*T^252 + T^246 + 2*T^90 + T^84 + 2*T^36 + T^30 + T^18 + T^12 + T^6
AUTHORS:
David Ayotte (2022): initial version
- class drinfeld_modular_forms.ring.DrinfeldModularFormsRing(base_ring, rank=2, group=None, has_type=False, names='g')#
Bases:
Parent
,UniqueRepresentation
Base class for the graded Drinfeld modular forms ring.
INPUT:
base_ring
– The fraction field of a univariate polynomial ring over \(\mathbb{F}_q\).rank
(integer, default: 2) – the rank of the ringgroup
(NoneType) – the group of self. The current implementation only supports the full group \(\mathbb{GL}_r(A)\).has_type
(bool, default:False
) – if set to True, returns the graded ring of arbitrary type. Currently only implemented in rank two.names
(string, default:'g'
) – a single character or a comma seperated string of character representing the names of the generators.
TESTS:
sage: from drinfeld_modular_forms import DrinfeldModularFormsRing sage: K = Frac(GF(3)['T']) sage: TestSuite(DrinfeldModularFormsRing(K)).run() sage: TestSuite(DrinfeldModularFormsRing(K, 3)).run() sage: TestSuite(DrinfeldModularFormsRing(K, 4)).run() sage: K = Frac(GF(7)['T']) sage: TestSuite(DrinfeldModularFormsRing(K)).run() sage: TestSuite(DrinfeldModularFormsRing(K, 3)).run() sage: TestSuite(DrinfeldModularFormsRing(K, 4)).run()
- Element#
alias of
DrinfeldModularFormsRingElement
- basis(k)#
Return a list of Drinfeld modular forms which forms a basis for the subspace of weight \(k\).
Note that if \(k\not\equiv 0\) modulo \(q-1\), then the subspace is 0.
An alias of this method is
basis
.INPUT:
k
– an integer.
EXAMPLES:
sage: from drinfeld_modular_forms import DrinfeldModularFormsRing sage: q = 3; A = GF(q)['T']; K = Frac(A); sage: M = DrinfeldModularFormsRing(K, 2) sage: M.basis_of_weight(q - 1) [g1] sage: M.basis_of_weight(q^2 - 1) [g2, g1^4] sage: M.basis_of_weight(q^3 - 1) [g1*g2^3, g1^5*g2^2, g1^9*g2, g1^13] sage: M.basis_of_weight(19*(q-1)) [g1^3*g2^4, g1^7*g2^3, g1^11*g2^2, g1^15*g2, g1^19]
- basis_of_weight(k)#
Return a list of Drinfeld modular forms which forms a basis for the subspace of weight \(k\).
Note that if \(k\not\equiv 0\) modulo \(q-1\), then the subspace is 0.
An alias of this method is
basis
.INPUT:
k
– an integer.
EXAMPLES:
sage: from drinfeld_modular_forms import DrinfeldModularFormsRing sage: q = 3; A = GF(q)['T']; K = Frac(A); sage: M = DrinfeldModularFormsRing(K, 2) sage: M.basis_of_weight(q - 1) [g1] sage: M.basis_of_weight(q^2 - 1) [g2, g1^4] sage: M.basis_of_weight(q^3 - 1) [g1*g2^3, g1^5*g2^2, g1^9*g2, g1^13] sage: M.basis_of_weight(19*(q-1)) [g1^3*g2^4, g1^7*g2^3, g1^11*g2^2, g1^15*g2, g1^19]
- coefficient_form(i)#
Return the \(i\)-th coefficient form of the universal Drinfeld module over \(\Omega^r(\mathbb{C}_{\infty})\).
EXAMPLES:
sage: from drinfeld_modular_forms import DrinfeldModularFormsRing sage: q = 3 sage: A = GF(q)['T'] sage: K.<T> = Frac(A) sage: M = DrinfeldModularFormsRing(K, 3) sage: M.coefficient_form(1) g1 sage: M.coefficient_form(2) g2 sage: M.coefficient_form(3) g3
sage: M = DrinfeldModularFormsRing(K, 2, has_type=True) sage: M.coefficient_form(1) g1 sage: M.coefficient_form(2) h^2
- eisenstein_series(k)#
Return the Drinfeld Eisenstein series of weight \(k\).
The method is currently only implemented for rank 2 and when \(k\) is of of the form \(q^i - 1\). If \(k = 0\), the method returns 0.
EXAMPLES:
sage: from drinfeld_modular_forms import DrinfeldModularFormsRing sage: q = 3 sage: A = GF(q)['T']; K = Frac(A); T = K.gen() sage: M = DrinfeldModularFormsRing(K, 2) sage: M.eisenstein_series(0) 0 sage: M.eisenstein_series(q - 1) g1 sage: M.eisenstein_series(q^2 - 1) g1^4 sage: M.eisenstein_series(q^3 - 1) g1^13 + (-T^9 + T)*g1*g2^3
- from_expansion(expansion, k)#
Return the Drinfeld modular form which corresponds to the given expansion.
INPUT:
expansion
– a lazy power series, a power series, a list or a tuple. The precision or the length must be at least the Sturm bound of the weight \(k\) subspace.k
– an integer representing the weight of the expected Drinfeld modular form.
EXAMPLES:
sage: from drinfeld_modular_forms import DrinfeldModularFormsRing sage: q = 3 sage: A = GF(q)['T'] sage: K.<T> = Frac(A) sage: M = DrinfeldModularFormsRing(K) sage: M.sturm_bound(q - 1) 1 sage: M.from_expansion([K.one()], q - 1) g1 sage: f = (M.1).expansion() sage: M.from_expansion(f, (M.1).weight()) g2
- gen(n)#
Return the \(n\)-th generator of the ring.
EXAMPLES:
sage: from drinfeld_modular_forms import DrinfeldModularFormsRing sage: A = GF(3)['T']; K = Frac(A); T = K.gen() sage: M = DrinfeldModularFormsRing(K, 2) sage: M.0 g1 sage: M.1 g2
- gens()#
Return a list of generators for this ring.
EXAMPLES:
sage: from drinfeld_modular_forms import DrinfeldModularFormsRing sage: A = GF(3)['T']; K = Frac(A); T = K.gen() sage: M = DrinfeldModularFormsRing(K, 5) sage: M.gens() [g1, g2, g3, g4, g5]
- ngens()#
Return the number of generators of the ring.
Note that the number of generators is equal to the rank.
EXAMPLES:
sage: from drinfeld_modular_forms import DrinfeldModularFormsRing sage: A = GF(3)['T']; K = Frac(A); T = K.gen() sage: M = DrinfeldModularFormsRing(K, 5) sage: M.ngens() 5
- one()#
Return the multiplicative identity of the ring.
EXAMPLES:
sage: from drinfeld_modular_forms import DrinfeldModularFormsRing sage: A = GF(3)['T']; K = Frac(A); T = K.gen() sage: M = DrinfeldModularFormsRing(K, 2) sage: M.one() 1 sage: M.one() * M.0 g1 sage: M.one().is_one() True
- petrov_expansion(k, n)#
Return a Drinfeld modular form which admits the \(A\)-expansion for \(k\) and \(n\) as defined by Petrov.
Recall that it is defined by:
\[\begin{split}f_{k, i}(z) := \sum_{\substack{a\in \mathbb{F}_q[T] \\ a\text{ monic}}} a^{k - i}G_i(t(az))\end{split}\]where \(k\) and \(n\) are 2 integers which are divisible by \(q - 1\) and \(n \leq p^{v_{p}(k - n)}\) (\(p\) is the characteristic).
INPUT:
k
– an integer divisible by \(q-1\).n
– an integer divisible by \(q-1\) which is stricly less than \(p^{v_{p}(k - n)}\).name
– string, the name of the parameter at infinity.
OUTPUT: a Drinfeld modular form of weight \(k\).
EXAMPLES:
sage: from drinfeld_modular_forms import DrinfeldModularFormsRing sage: q = 3 sage: A = GF(q)['T']; K = Frac(A) sage: M = DrinfeldModularFormsRing(K, 2) sage: M.petrov_expansion((q + 1)*(q - 1), q - 1) g2 sage: M.petrov_expansion((q^2 + 1)*(q - 1), q - 1) g1^6*g2 sage: M.petrov_expansion((q^3 + 1)*(q - 1), q - 1) g1^24*g2 + (T^27 - T^9)*g1^12*g2^4 + (T^54 + T^36 + T^18)*g2^7
- polynomial_ring()#
Return the multivariate polynomial ring over the base ring where each variable corresponds to a generator of a ring.
EXAMPLES:
sage: from drinfeld_modular_forms import DrinfeldModularFormsRing sage: q = 3; A = GF(q)['T']; K = Frac(A); sage: M = DrinfeldModularFormsRing(K, 2) sage: P = M.polynomial_ring() sage: P Multivariate Polynomial Ring in g1, g2 over Fraction Field of Univariate Polynomial Ring in T over Finite Field of size 3
The degree of the variables corresponds to the weight of the associated generator:
sage: P.inject_variables() Defining g1, g2 sage: g1.degree() 2 sage: g2.degree() 8
- rank()#
Return the rank of the ring of Drinfeld modular forms.
EXAMPLES:
sage: from drinfeld_modular_forms import DrinfeldModularFormsRing sage: A = GF(3)['T']; K = Frac(A); sage: DrinfeldModularFormsRing(K, 2).rank() 2 sage: DrinfeldModularFormsRing(K, 3).rank() 3 sage: DrinfeldModularFormsRing(K, 4).rank() 4
- sturm_bound(k)#
Return the Sturm bound of the subspace of weight \(k\).
Currently only implemented in rank 2.
INPUT:
k
– an integer
EXAMPLES:
sage: from drinfeld_modular_forms import DrinfeldModularFormsRing sage: q = 3; A = GF(q)['T']; K = Frac(A); sage: M = DrinfeldModularFormsRing(K, 2) sage: M.sturm_bound(q - 1) 1 sage: M.sturm_bound(q^2 - 1) 3 sage: M.sturm_bound(q^9 - 1) 4921
- zero()#
Return the additive identity of the ring.
EXAMPLES:
sage: from drinfeld_modular_forms import DrinfeldModularFormsRing sage: A = GF(3)['T']; K = Frac(A); T = K.gen() sage: M = DrinfeldModularFormsRing(K, 2) sage: M.zero() 0 sage: M.zero() + M.1 g2 sage: M.zero() * M.1 0 sage: M.zero().is_zero() True