@@ -424,86 +424,109 @@ def goss_polynomial(self, n, var='X'):
424
424
class DrinfeldModule_rational (DrinfeldModule_charzero ):
425
425
"""
426
426
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'>
428
439
"""
429
- def _phiT_matrix (self , polynomial_part ):
440
+ def coefficient_in_function_ring (self , n ):
430
441
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.
436
444
437
445
INPUT:
438
446
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
442
448
443
449
EXAMPLES::
444
450
445
451
sage: q = 5
446
452
sage: Fq = GF(q)
447
453
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)
469
472
Traceback (most recent call last):
470
473
...
471
- ValueError: the Drinfeld module must have polynomial coefficients
474
+ ValueError: coefficient is not polynomial
472
475
"""
473
476
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]
477
507
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 ()
478
522
gs = []
479
- for g in self .coefficients (sparse = False ):
523
+ for g in self .coefficients (sparse ):
480
524
g = g .backend (force = True )
481
525
if g .denominator ().is_one ():
482
526
gs .append (A (g .numerator ().list ()))
483
527
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
507
530
508
531
def class_polynomial (self ):
509
532
r"""
@@ -547,16 +570,32 @@ def class_polynomial(self):
547
570
sage: phi.class_polynomial()
548
571
Traceback (most recent call last):
549
572
...
550
- ValueError: the Drinfeld module must have polynomial coefficients
573
+ ValueError: coefficients are not polynomials
551
574
"""
552
575
A = self .function_ring ()
553
576
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 ))
556
583
if s == 0 :
557
584
# small case
558
585
return A .one ()
559
586
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
+
560
599
v = vector (Fq , s )
561
600
v [s - 1 ] = 1
562
601
vs = [v ]
@@ -577,80 +616,3 @@ def class_polynomial(self):
577
616
578
617
N = (V * M * ~ V ).submatrix (dim , dim )
579
618
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