@@ -424,86 +424,109 @@ def goss_polynomial(self, n, var='X'):
424424class 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