Skip to content

Commit 21f46a6

Browse files
committedJan 3, 2025·
remove computation of Taelman's unit (will be for another PR)
1 parent 421bbe5 commit 21f46a6

File tree

1 file changed

+101
-139
lines changed

1 file changed

+101
-139
lines changed
 

‎src/sage/rings/function_field/drinfeld_modules/charzero_drinfeld_module.py

+101-139
Original file line numberDiff line numberDiff line change
@@ -424,86 +424,109 @@ def goss_polynomial(self, n, var='X'):
424424
class DrinfeldModule_rational(DrinfeldModule_charzero):
425425
"""
426426
A class for Drinfeld modules defined over the fraction
427-
field of the underlying function field
427+
field of the underlying function field.
428+
429+
TESTS::
430+
431+
sage: q = 9
432+
sage: Fq = GF(q)
433+
sage: A = Fq['T']
434+
sage: K.<T> = Frac(A)
435+
sage: C = DrinfeldModule(A, [T, 1]); C
436+
Drinfeld module defined by T |--> t + T
437+
sage: type(C)
438+
<class 'sage.rings.function_field.drinfeld_modules.charzero_drinfeld_module.DrinfeldModule_rational_with_category'>
428439
"""
429-
def _phiT_matrix(self, polynomial_part):
440+
def coefficient_in_function_ring(self, n):
430441
r"""
431-
Return the matrix giving the action of `\phi_T` modulo `u^s`
432-
where `u = 1/T` is the uniformizer at infinity `s` is chosen
433-
such that `u^s` is in the domain of convergence of the logarithm.
434-
435-
It is an helper function; do not call it directly.
442+
Return the `n`-th coefficient of this Drinfeld module as
443+
an element of the underlying function ring.
436444
437445
INPUT:
438446
439-
- ``polynomial_part`` -- boolean; if ``False``, omit the
440-
part with negative powers of `u`; if ``True``, return this
441-
part as a polynomial vector in `T`
447+
- ``n`` -- an integer
442448
443449
EXAMPLES::
444450
445451
sage: q = 5
446452
sage: Fq = GF(q)
447453
sage: A = Fq['T']
448-
sage: K.<T> = Frac(A)
449-
sage: phi = DrinfeldModule(A, [T, T^20])
450-
sage: phi._phiT_matrix(False)
451-
[0 0 0 0 0]
452-
[1 0 0 0 0]
453-
[0 1 0 0 0]
454-
[0 0 1 0 0]
455-
[0 0 0 1 1]
456-
sage: phi._phiT_matrix(True)
457-
(
458-
[0 0 0 0 0]
459-
[1 0 0 0 0]
460-
[0 1 0 0 0]
461-
[0 0 1 0 0]
462-
[0 0 0 1 1], (T^15 + 1, T^10, T^5, 1, 0)
463-
)
464-
465-
::
466-
467-
sage: psi = DrinfeldModule(A, [T, 1/T])
468-
sage: psi._phiT_matrix(False)
454+
sage: R = Fq['U']
455+
sage: K.<U> = Frac(R)
456+
sage: phi = DrinfeldModule(A, [U, 0, U^2, U^3])
457+
sage: phi.coefficient_in_function_ring(2)
458+
T^2
459+
460+
Compare with the method meth:`coefficient`::
461+
462+
sage: phi.coefficient(2)
463+
U^2
464+
465+
If the required coefficient is not a polynomials,
466+
an error is raised::
467+
468+
sage: psi = DrinfeldModule(A, [U, 1/U])
469+
sage: psi.coefficient_in_function_ring(0)
470+
T
471+
sage: psi.coefficient_in_function_ring(1)
469472
Traceback (most recent call last):
470473
...
471-
ValueError: the Drinfeld module must have polynomial coefficients
474+
ValueError: coefficient is not polynomial
472475
"""
473476
A = self.function_ring()
474-
Fq = A.base_ring()
475-
q = Fq.cardinality()
476-
r = self.rank()
477+
g = self.coefficient(n)
478+
g = g.backend(force=True)
479+
if g.denominator().is_one():
480+
return A(g.numerator().list())
481+
else:
482+
raise ValueError("coefficient is not polynomial")
483+
484+
def coefficients_in_function_ring(self, sparse=True):
485+
r"""
486+
Return the coefficients of this Drinfeld module as elements
487+
of the underlying function ring.
488+
489+
INPUT:
490+
491+
- ``sparse`` -- a boolean (default: ``True``); if ``True``,
492+
only return the nonzero coefficients; otherwise, return
493+
all of them.
494+
495+
EXAMPLES::
496+
497+
sage: q = 5
498+
sage: Fq = GF(q)
499+
sage: A = Fq['T']
500+
sage: R = Fq['U']
501+
sage: K.<U> = Frac(R)
502+
sage: phi = DrinfeldModule(A, [U, 0, U^2, U^3])
503+
sage: phi.coefficients_in_function_ring()
504+
[T, T^2, T^3]
505+
sage: phi.coefficients_in_function_ring(sparse=False)
506+
[T, 0, T^2, T^3]
477507
508+
Compare with the method meth:`coefficients`::
509+
510+
sage: phi.coefficients()
511+
[U, U^2, U^3]
512+
513+
If the coefficients are not polynomials, an error is raised::
514+
515+
sage: psi = DrinfeldModule(A, [U, 1/U])
516+
sage: psi.coefficients_in_function_ring()
517+
Traceback (most recent call last):
518+
...
519+
ValueError: coefficients are not polynomials
520+
"""
521+
A = self.function_ring()
478522
gs = []
479-
for g in self.coefficients(sparse=False):
523+
for g in self.coefficients(sparse):
480524
g = g.backend(force=True)
481525
if g.denominator().is_one():
482526
gs.append(A(g.numerator().list()))
483527
else:
484-
raise ValueError("the Drinfeld module must have polynomial coefficients")
485-
s = max(gs[i].degree() // (q**i - 1) for i in range(1, r+1))
486-
487-
M = matrix(Fq, s)
488-
if polynomial_part:
489-
P = vector(A, s)
490-
qk = 1
491-
for k in range(r+1):
492-
for i in range(s):
493-
e = (i+1)*qk
494-
if polynomial_part:
495-
P[i] += gs[k] >> e
496-
for j in range(s):
497-
e -= 1
498-
if e < 0:
499-
break
500-
M[i, j] += gs[k][e]
501-
qk *= q
502-
503-
if polynomial_part:
504-
return M, P
505-
else:
506-
return M
528+
raise ValueError("coefficients are not polynomials")
529+
return gs
507530

508531
def class_polynomial(self):
509532
r"""
@@ -547,16 +570,32 @@ def class_polynomial(self):
547570
sage: phi.class_polynomial()
548571
Traceback (most recent call last):
549572
...
550-
ValueError: the Drinfeld module must have polynomial coefficients
573+
ValueError: coefficients are not polynomials
551574
"""
552575
A = self.function_ring()
553576
Fq = A.base_ring()
554-
M = self._phiT_matrix(False)
555-
s = M.nrows()
577+
q = Fq.cardinality()
578+
r = self.rank()
579+
580+
gs = self.coefficients_in_function_ring(sparse=False)
581+
582+
s = max(gs[i].degree() // (q**i - 1) for i in range(1, r+1))
556583
if s == 0:
557584
# small case
558585
return A.one()
559586

587+
M = matrix(Fq, s)
588+
qk = 1
589+
for k in range(r+1):
590+
for i in range(s):
591+
e = (i+1)*qk
592+
for j in range(s):
593+
e -= 1
594+
if e < 0:
595+
break
596+
M[i, j] += gs[k][e]
597+
qk *= q
598+
560599
v = vector(Fq, s)
561600
v[s-1] = 1
562601
vs = [v]
@@ -577,80 +616,3 @@ def class_polynomial(self):
577616

578617
N = (V * M * ~V).submatrix(dim, dim)
579618
return A(N.charpoly())
580-
581-
def taelman_exponential_unit(self):
582-
r"""
583-
Return the exponential of a fundamental Taelman's unit
584-
of this Drinfeld module.
585-
586-
A Taelman's unit is by definition an element `x \in
587-
\mathbb F_q((1/T))` whose exponential falls in `\mathbb F_q[T]`.
588-
589-
Taelman's units form a `\mathbb F_q[T]`-line in `\mathbb F_q((1/T))`;
590-
a fundamental unit is by definition a generator of this line.
591-
592-
We refer to [Tae2012]_ for more details about this construction.
593-
594-
EXAMPLES:
595-
596-
The Taelman exponential unit of The Carlitz module is `1`::
597-
598-
sage: q = 7
599-
sage: Fq = GF(q)
600-
sage: A = Fq['T']
601-
sage: K.<T> = Frac(A)
602-
sage: C = DrinfeldModule(A, [T, 1]); C
603-
Drinfeld module defined by T |--> t + T
604-
sage: C.taelman_exponential_unit()
605-
1
606-
607-
The same occurs more generally when the coefficients of the
608-
Drinfeld module have small enough degrees::
609-
610-
sage: gs = [T] + [A.random_element(degree = q^i - 1)
611-
....: for i in range(1, 5)]
612-
sage: phi = DrinfeldModule(A, gs)
613-
sage: phi.taelman_exponential_unit()
614-
1
615-
616-
Usually, as soon as we leave the world of small Drinfeld modules,
617-
Taelman's exponential units are highly non trivial::
618-
619-
sage: phi = DrinfeldModule(A, [T, T^(2*q+1), T^3])
620-
sage: phi.taelman_exponential_unit()
621-
T^52 + T^22 + T^8 + T^2 + 1
622-
"""
623-
A = self.function_ring()
624-
Fq = A.base_ring()
625-
q = Fq.cardinality()
626-
M, P = self._phiT_matrix(True)
627-
s = M.nrows()
628-
if s == 0:
629-
# small case
630-
return self.base().one()
631-
632-
gs = self.coefficients(sparse=False)
633-
v = vector(Fq, s)
634-
v[s-1] = 1
635-
p = A.zero()
636-
vs = [v]
637-
ps = [p]
638-
for i in range(s):
639-
pq = p
640-
p = v * P
641-
for j in range(len(gs) - 1):
642-
p += gs[j] * pq
643-
pq = pq ** q
644-
p += gs[-1] * pq
645-
v = v * M
646-
vs.append(v)
647-
ps.append(p)
648-
vs.reverse()
649-
ps.reverse()
650-
V = matrix(vs)
651-
652-
unit = V.left_kernel().basis()[0]
653-
expunit = sum(unit[i]*ps[i] for i in range(s+1))
654-
if expunit:
655-
expunit /= expunit.numerator().leading_coefficient()
656-
return expunit

0 commit comments

Comments
 (0)
Please sign in to comment.