# Elements of Drinfeld modular forms rings#

This module defines the elements of the class DrinfeldModularForms.

AUTHORS:

• David Ayotte (2022): initial version

class sage.modular.drinfeld_modform.element.DrinfeldModularFormsElement(parent, polynomial)[source]#

Bases: ModuleElement

Element class of rings of Drinfeld modular forms.

Recall that a graded Drinfeld form is a sum of Drinfeld modular forms having potentially different weights:

$F = f_{k_1} + f_{k_2} + \cdots + f_{k_n}$

where $$f_{k_i}$$ is a Drinfeld modular form of weight $$k_i$$. We also say that $$f_{k_i}$$ is an homogeneous component of weight $$k_i$$. If $$n=1$$, then we say that $$F$$ is homogeneous of weight $$k_1$$.

EXAMPLES: use the inject_variable method of the parent to quickly assign variables names to the generators:

sage: A = GF(3)['T']
sage: K.<T> = Frac(A)
sage: M = DrinfeldModularForms(K, 2)
sage: M.inject_variables()
Defining g1, g2
sage: g1 in M
True
sage: g2.parent()
Ring of Drinfeld modular forms of rank 2 over Fraction Field of Univariate Polynomial Ring in T over Finite Field of size 3

>>> from sage.all import *
>>> A = GF(Integer(3))['T']
>>> K = Frac(A, names=('T',)); (T,) = K._first_ngens(1)
>>> M = DrinfeldModularForms(K, Integer(2))
>>> M.inject_variables()
Defining g1, g2
>>> g1 in M
True
>>> g2.parent()
Ring of Drinfeld modular forms of rank 2 over Fraction Field of Univariate Polynomial Ring in T over Finite Field of size 3


Next, via algebraic combination of the generator, we may create any element of the ring:

sage: F = g1*g2 + g2
sage: F
g1*g2 + g2
sage: F.is_homogeneous()
False
sage: F.homogeneous_components()
{8: g2, 10: g1*g2}

>>> from sage.all import *
>>> F = g1*g2 + g2
>>> F
g1*g2 + g2
>>> F.is_homogeneous()
False
>>> F.homogeneous_components()
{8: g2, 10: g1*g2}


If the created form is homogeneous, we can ask for its weight in which case it will be a Drinfeld modular form:

sage: H = g1^4*g2^9 + T*g1^8*g2^8 + (T^2 - 1)*g1^28*g2^3
sage: H.is_homogeneous()
True
sage: H.weight()
80

>>> from sage.all import *
>>> H = g1**Integer(4)*g2**Integer(9) + T*g1**Integer(8)*g2**Integer(8) + (T**Integer(2) - Integer(1))*g1**Integer(28)*g2**Integer(3)
>>> H.is_homogeneous()
True
>>> H.weight()
80


You can also construct an element by simply passing a multivariate polynomial to the parent:

sage: f1, f2 = polygens(K, 2, 'f1, f2')
sage: M(f1)
g1
sage: M(f2)
g2
sage: M(T*f1 + f2^3 + T^2 + 1)
g2^3 + T*g1 + (T^2 + 1)

>>> from sage.all import *
>>> f1, f2 = polygens(K, Integer(2), 'f1, f2')
>>> M(f1)
g1
>>> M(f2)
g2
>>> M(T*f1 + f2**Integer(3) + T**Integer(2) + Integer(1))
g2^3 + T*g1 + (T^2 + 1)


Note

This class should not be directly instanciated, instead create an instance of the parent DrinfeldModularForms and access its elements using the relevant methods.

homogeneous_components()[source]#

Return the homogeneous components of this graded Drinfeld form.

EXAMPLES:

sage: A = GF(3)['T']; K = Frac(A)
sage: M = DrinfeldModularForms(K, 2)
sage: M.inject_variables()
Defining g1, g2
sage: F = g1 + g1^2 + g1*g2^2 + g2^4
sage: D = F.homogeneous_components(); D
{2: g1, 4: g1^2, 18: g1*g2^2, 32: g2^4}
sage: D[32]
g2^4

>>> from sage.all import *
>>> A = GF(Integer(3))['T']; K = Frac(A)
>>> M = DrinfeldModularForms(K, Integer(2))
>>> M.inject_variables()
Defining g1, g2
>>> F = g1 + g1**Integer(2) + g1*g2**Integer(2) + g2**Integer(4)
>>> D = F.homogeneous_components(); D
{2: g1, 4: g1^2, 18: g1*g2^2, 32: g2^4}
>>> D[Integer(32)]
g2^4

is_homogeneous()[source]#

Return whether the graded form is homogeneous in the weight.

We recall that elements of Drinfeld modular forms ring are not necessarily modular forms as they may have mixed weight components.

EXAMPLES:

sage: A = GF(3)['T']; K = Frac(A)
sage: M = DrinfeldModularForms(K, 2)
sage: M.inject_variables()
Defining g1, g2
sage: f = g1^5*g2^2  # homogeneous polynomial
sage: f.is_homogeneous()
True
sage: g = g1 + g2  # mixed weight components
sage: g.is_homogeneous()
False

>>> from sage.all import *
>>> A = GF(Integer(3))['T']; K = Frac(A)
>>> M = DrinfeldModularForms(K, Integer(2))
>>> M.inject_variables()
Defining g1, g2
>>> f = g1**Integer(5)*g2**Integer(2)  # homogeneous polynomial
>>> f.is_homogeneous()
True
>>> g = g1 + g2  # mixed weight components
>>> g.is_homogeneous()
False

is_one()[source]#

Return True whether this graded Drinfeld form is the multiplicative identity.

EXAMPLES:

sage: A = GF(3)['T']; K = Frac(A)
sage: M = DrinfeldModularForms(K, 2)
sage: u = M.one()
sage: u.is_one()
True
sage: (M.0).is_one()
False

>>> from sage.all import *
>>> A = GF(Integer(3))['T']; K = Frac(A)
>>> M = DrinfeldModularForms(K, Integer(2))
>>> u = M.one()
>>> u.is_one()
True
>>> (M.gen(0)).is_one()
False

is_zero()[source]#

Return True whether this graded Drinfeld form is the additive identity.

EXAMPLES:

sage: A = GF(3)['T']; K = Frac(A)
sage: M = DrinfeldModularForms(K, 2)
sage: z = M.zero()
sage: z.is_zero()
True
sage: f = M.0
sage: f.is_zero()
False
sage: (f - f).is_zero()
True
sage: (0 * M.0).is_zero()
True

>>> from sage.all import *
>>> A = GF(Integer(3))['T']; K = Frac(A)
>>> M = DrinfeldModularForms(K, Integer(2))
>>> z = M.zero()
>>> z.is_zero()
True
>>> f = M.gen(0)
>>> f.is_zero()
False
>>> (f - f).is_zero()
True
>>> (Integer(0) * M.gen(0)).is_zero()
True

polynomial()[source]#

Return this graded Drinfeld forms as a multivariate polynomial over the generators of the ring.

OUTPUT:

A multivariate polynomial over the base ring.

EXAMPLES:

sage: A = GF(3)['T']; K = Frac(A)
sage: M = DrinfeldModularForms(K, 2)
sage: M.inject_variables()
Defining g1, g2
sage: P1 = g1.polynomial();
sage: P2 = g2.polynomial();
sage: P2^2 + P1^2 + P1
g2^2 + g1^2 + g1
sage: P1.parent()
Multivariate Polynomial Ring in g1, g2 over Fraction Field of Univariate Polynomial Ring in T over Finite Field of size 3

>>> from sage.all import *
>>> A = GF(Integer(3))['T']; K = Frac(A)
>>> M = DrinfeldModularForms(K, Integer(2))
>>> M.inject_variables()
Defining g1, g2
>>> P1 = g1.polynomial();
>>> P2 = g2.polynomial();
>>> P2**Integer(2) + P1**Integer(2) + P1
g2^2 + g1^2 + g1
>>> P1.parent()
Multivariate Polynomial Ring in g1, g2 over Fraction Field of Univariate Polynomial Ring in T over Finite Field of size 3


The degree of each variables corresponds to the weight of the generator:

sage: P1.degree()
2
sage: P2.degree()
8

>>> from sage.all import *
>>> P1.degree()
2
>>> P2.degree()
8

rank()[source]#

Return the rank of this graded Drinfeld form.

Note that the rank is independent of the chosen form and depends only on the parent.

EXAMPLES:

sage: A = GF(3)['T']; K = Frac(A)
sage: M2 = DrinfeldModularForms(K, 2)
sage: (M2.0).rank()
2
sage: M5 = DrinfeldModularForms(K, 5)
sage: (M5.0 + M5.3).rank()
5

>>> from sage.all import *
>>> A = GF(Integer(3))['T']; K = Frac(A)
>>> M2 = DrinfeldModularForms(K, Integer(2))
>>> (M2.gen(0)).rank()
2
>>> M5 = DrinfeldModularForms(K, Integer(5))
>>> (M5.gen(0) + M5.gen(3)).rank()
5

type()[source]#

Return the type of this graded Drinfeld form.

Recall that the type is the integer $$0 \leq m \leq q-1$$ such that

$f(\gamma(w)) = \mathrm{det}(\gamma)^m j(\gamma, w)^k f(w).$

EXAMPLES:

sage: A = GF(11)['T']; K = Frac(A)
sage: M = DrinfeldModularForms(K, 2, has_type=True)
sage: M.inject_variables()
Defining g1, h2
sage: F = g1*h2^9
sage: F.type()
9
sage: (h2^11).type()
1
sage: g1.type()
0

>>> from sage.all import *
>>> A = GF(Integer(11))['T']; K = Frac(A)
>>> M = DrinfeldModularForms(K, Integer(2), has_type=True)
>>> M.inject_variables()
Defining g1, h2
>>> F = g1*h2**Integer(9)
>>> F.type()
9
>>> (h2**Integer(11)).type()
1
>>> g1.type()
0


The type only makes sense when the form is homogeneous:

sage: F = g1^4 + h2
sage: F.type()
Traceback (most recent call last):
...
ValueError: the graded form is not homogeneous

>>> from sage.all import *
>>> F = g1**Integer(4) + h2
>>> F.type()
Traceback (most recent call last):
...
ValueError: the graded form is not homogeneous

weight()[source]#

Return the weight of this graded Drinfeld modular form.

EXAMPLES:

sage: A = GF(3)['T']; K = Frac(A)
sage: M = DrinfeldModularForms(K, 2)
sage: M.inject_variables()
Defining g1, g2
sage: g1.weight()
2
sage: g2.weight()
8
sage: f = g1^5*g2^2
sage: f.weight()
26

>>> from sage.all import *
>>> A = GF(Integer(3))['T']; K = Frac(A)
>>> M = DrinfeldModularForms(K, Integer(2))
>>> M.inject_variables()
Defining g1, g2
>>> g1.weight()
2
>>> g2.weight()
8
>>> f = g1**Integer(5)*g2**Integer(2)
>>> f.weight()
26


If the form is not homogeneous, then the method returns an error:

sage: f = g1 + g2
sage: f.weight()
Traceback (most recent call last):
...
ValueError: the graded form is not homogeneous

>>> from sage.all import *
>>> f = g1 + g2
>>> f.weight()
Traceback (most recent call last):
...
ValueError: the graded form is not homogeneous