Skip to content
This repository has been archived by the owner on Jan 30, 2023. It is now read-only.

Commit

Permalink
Add methods to deal with complex multiplication in FiniteDrinfeldModule
Browse files Browse the repository at this point in the history
The added methods are:
    - frobenius_trace,
    - frobenius_norm,
    - invert (required by frobenius_norm),
    - is_ordinary,
    - is_supersingular,
    - characteristic_polynomial.
  • Loading branch information
kryzar committed May 12, 2022
1 parent 86348ff commit 2c24562
Showing 1 changed file with 68 additions and 1 deletion.
69 changes: 68 additions & 1 deletion src/sage/modules/finite_drinfeld_module.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,15 @@

from sage.categories.action import Action
from sage.categories.homset import Hom
from sage.matrix.constructor import Matrix
from sage.misc.latex import latex
from sage.modules.free_module_element import vector
from sage.rings.integer import Integer
from sage.rings.morphism import RingHomomorphism_im_gens
from sage.rings.polynomial.ore_polynomial_element import OrePolynomial
from sage.rings.polynomial.ore_polynomial_ring import OrePolynomialRing
from sage.rings.polynomial.polynomial_ring import PolynomialRing_dense_finite_field
from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing


class FiniteDrinfeldModule(RingHomomorphism_im_gens):
Expand All @@ -51,6 +54,10 @@ class FiniteDrinfeldModule(RingHomomorphism_im_gens):
- ``polring`` -- the base polynomial ring
- ``gen`` -- the image of `X`
- ``characteristic`` -- the Fq[X]-characteristic of the Drinfeld
module, i.e. an irreducible polynomial in `polring` that defines a
subextension of L (the base field of the Ore polynomial ring) and
for which the constant coefficient of `gen` is a root.
EXAMPLES:
Expand Down Expand Up @@ -173,10 +180,20 @@ def __init__(self, polring, gen, characteristic):
'must be a root of the characteristic')
if gen.is_constant():
raise ValueError('The generator must not be constant')
# Finally
# Work
self.__characteristic = characteristic
super().__init__(Hom(FqX, Ltau), gen)

#################
# Private utils #
#################

def _Fq(self):
return self.polring().base_ring()

def _L(self):
return self.ore_polring().base_ring()

###########
# Methods #
###########
Expand All @@ -196,11 +213,30 @@ def change_ring(self, R):
return FiniteDrinfeldModule(self.polring(),
new_ore_polring(self.gen()), self.characteristic())

def characteristic_polynomial(self):
FqXT = PolynomialRing(self.polring(), 'T')
return FqXT([self.frobenius_norm(), self.frobenius_trace(), 1])

def delta(self):
if self.rank() != 2:
raise ValueError('The rank must equal 2')
return self.gen()[2]

def frobenius_norm(self):
# Notations from Schost-Musleh:
n = self._L().over(self._Fq()).degree_over(self._Fq())
d = self.characteristic().degree()
m = n // d
norm = self._L().over(self._Fq())(self.delta()).norm()
return ((-1)**n) * (self.characteristic()**m) / norm

def frobenius_trace(self):
# Notations from Schost-Musleh:
n = self._L().over(self._Fq()).degree_over(self._Fq())
B = self.frobenius_norm()
t = self.ore_polring().gen()
return self.invert(t**n + (self(B) // t**n))

def g(self):
if self.rank() != 2:
raise ValueError('The rank must equal 2')
Expand All @@ -209,6 +245,37 @@ def g(self):
def height(self):
return Integer(1)

def invert(self, image):
"""
Given an Ore polynomial `image` of the form `phi(c)`, find c.
"""
if not image in self.ore_polring():
raise TypeError('The tested image should be in the Ore ' \
'polynomial ring')
if image in self._L(): # Only works if `image` is in the image of self
return self._Fq()(image)
r = self.rank()
X = self.polring().gen()
k = image.degree() // r
m_lines = [[0 for _ in range(k+1)] for _ in range(k+1)]
for i in range(k+1):
phi_X_i = self(X**i)
for j in range(i+1):
m_lines[j][i] = phi_X_i[r*j]
m = Matrix(m_lines)
v = vector([list(image)[r*j] for j in range(k+1)])
pre_image = self.polring()(list((m**(-1)) * v))
if self(pre_image) == image:
return pre_image
else:
return None

def is_supersingular(self):
return self.characteristic().divides(self.frobenius_trace())

def is_ordinary(self):
return not self.is_supersingular()

def j(self):
if self.rank() != 2:
raise ValueError('The j-invariant is only defined for rank 2 ' \
Expand Down

0 comments on commit 2c24562

Please sign in to comment.