Skip to content

Commit 8c96045

Browse files
author
Release Manager
committed
gh-40436: Remove useless limitations in Drinfeld modules (1) We authorize Drinfeld modules with constant coefficient zero (which is definitely not discarded by the theory). (2) We automatically coerce the given coefficients to the field of fractions; this avoids one step when creating a Drinfeld module. ### 📝 Checklist <!-- Put an `x` in all the boxes that apply. --> - [x] The title is concise and informative. - [x] The description explains in detail what this PR is about. - [ ] I have linked a relevant issue or discussion. - [x] I have created tests covering the changes. - [x] I have updated the documentation and checked the documentation preview. URL: #40436 Reported by: Xavier Caruso Reviewer(s): Antoine Leudière
2 parents 2046b1a + c6632da commit 8c96045

File tree

4 files changed

+45
-82
lines changed

4 files changed

+45
-82
lines changed

src/sage/categories/drinfeld_modules.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -438,7 +438,7 @@ def characteristic(self):
438438
439439
::
440440
441-
sage: psi = DrinfeldModule(A, [Frac(A).gen(), 1])
441+
sage: psi = DrinfeldModule(A, [T, 1])
442442
sage: C = psi.category()
443443
sage: C.characteristic()
444444
0
@@ -639,7 +639,7 @@ def base(self):
639639
640640
The base can be infinite::
641641
642-
sage: sigma = DrinfeldModule(A, [Frac(A).gen(), 1])
642+
sage: sigma = DrinfeldModule(A, [T, 1])
643643
sage: sigma.base()
644644
Fraction Field of Univariate Polynomial Ring in T over Finite Field in z2 of size 5^2 over its base
645645
"""
@@ -664,7 +664,7 @@ def base_morphism(self):
664664
665665
The base field can be infinite::
666666
667-
sage: sigma = DrinfeldModule(A, [Frac(A).gen(), 1])
667+
sage: sigma = DrinfeldModule(A, [T, 1])
668668
sage: sigma.base_morphism()
669669
Coercion map:
670670
From: Univariate Polynomial Ring in T over Finite Field in z2 of size 5^2
@@ -711,8 +711,7 @@ def characteristic(self):
711711
::
712712
713713
sage: B.<Y> = Fq[]
714-
sage: L = Frac(B)
715-
sage: psi = DrinfeldModule(A, [L(1), 0, 0, L(1)])
714+
sage: psi = DrinfeldModule(A, [B(1), 0, 0, 1])
716715
sage: psi.characteristic()
717716
Traceback (most recent call last):
718717
...

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

Lines changed: 19 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,7 @@ class DrinfeldModule_charzero(DrinfeldModule):
5656
responsible for instantiating the right class depending on the
5757
input::
5858
59-
sage: A = GF(3)['T']
60-
sage: K.<T> = Frac(A)
59+
sage: A.<T> = GF(3)[]
6160
sage: phi = DrinfeldModule(A, [T, 1])
6261
sage: phi
6362
Drinfeld module defined by T |--> t + T
@@ -75,8 +74,7 @@ class DrinfeldModule_charzero(DrinfeldModule):
7574
It is possible to calculate the logarithm and the exponential of
7675
any Drinfeld modules of characteristic zero::
7776
78-
sage: A = GF(2)['T']
79-
sage: K.<T> = Frac(A)
77+
sage: A.<T> = GF(2)[]
8078
sage: phi = DrinfeldModule(A, [T, 1])
8179
sage: phi.exponential()
8280
z + ((1/(T^2+T))*z^2) + ((1/(T^8+T^6+T^5+T^3))*z^4) + O(z^8)
@@ -89,8 +87,7 @@ class DrinfeldModule_charzero(DrinfeldModule):
8987
analytic theory of Drinfeld module. They provide a function field
9088
analogue of certain classical trigonometric functions::
9189
92-
sage: A = GF(2)['T']
93-
sage: K.<T> = Frac(A)
90+
sage: A.<T> = GF(2)[]
9491
sage: phi = DrinfeldModule(A, [T, 1])
9592
sage: phi.goss_polynomial(1)
9693
X
@@ -133,8 +130,7 @@ def _compute_coefficient_exp(self, k):
133130
134131
TESTS::
135132
136-
sage: A = GF(2)['T']
137-
sage: K.<T> = Frac(A)
133+
sage: A.<T> = GF(2)[]
138134
sage: phi = DrinfeldModule(A, [T, 1])
139135
sage: q = A.base_ring().cardinality()
140136
sage: phi._compute_coefficient_exp(0)
@@ -175,8 +171,7 @@ def exponential(self, prec=Infinity, name='z'):
175171
176172
EXAMPLES::
177173
178-
sage: A = GF(2)['T']
179-
sage: K.<T> = Frac(A)
174+
sage: A.<T> = GF(2)[]
180175
sage: phi = DrinfeldModule(A, [T, 1])
181176
sage: q = A.base_ring().cardinality()
182177
@@ -199,8 +194,7 @@ def exponential(self, prec=Infinity, name='z'):
199194
200195
Example in higher rank::
201196
202-
sage: A = GF(5)['T']
203-
sage: K.<T> = Frac(A)
197+
sage: A.<T> = GF(5)[]
204198
sage: phi = DrinfeldModule(A, [T, T^2, T + T^2 + T^4, 1])
205199
sage: exp = phi.exponential(); exp
206200
z + ((T/(T^4+4))*z^5) + O(z^8)
@@ -217,8 +211,7 @@ def exponential(self, prec=Infinity, name='z'):
217211
218212
TESTS::
219213
220-
sage: A = GF(2)['T']
221-
sage: K.<T> = Frac(A)
214+
sage: A.<T> = GF(2)[]
222215
sage: phi = DrinfeldModule(A, [T, 1])
223216
sage: exp = phi.exponential()
224217
sage: exp[2] == 1/(T**q - T) # expected value
@@ -259,8 +252,7 @@ def _compute_coefficient_log(self, k):
259252
260253
TESTS::
261254
262-
sage: A = GF(2)['T']
263-
sage: K.<T> = Frac(A)
255+
sage: A.<T> = GF(2)[]
264256
sage: phi = DrinfeldModule(A, [T, 1])
265257
sage: q = A.base_ring().cardinality()
266258
sage: phi._compute_coefficient_log(0)
@@ -305,8 +297,7 @@ def logarithm(self, prec=Infinity, name='z'):
305297
306298
EXAMPLES::
307299
308-
sage: A = GF(2)['T']
309-
sage: K.<T> = Frac(A)
300+
sage: A.<T> = GF(2)[]
310301
sage: phi = DrinfeldModule(A, [T, 1])
311302
312303
When ``prec`` is ``Infinity`` (which is the default),
@@ -328,16 +319,14 @@ def logarithm(self, prec=Infinity, name='z'):
328319
329320
Example in higher rank::
330321
331-
sage: A = GF(5)['T']
332-
sage: K.<T> = Frac(A)
322+
sage: A.<T> = GF(5)[]
333323
sage: phi = DrinfeldModule(A, [T, T^2, T + T^2 + T^4, 1])
334324
sage: phi.logarithm()
335325
z + ((4*T/(T^4+4))*z^5) + O(z^8)
336326
337327
TESTS::
338328
339-
sage: A = GF(2)['T']
340-
sage: K.<T> = Frac(A)
329+
sage: A.<T> = GF(2)[]
341330
sage: phi = DrinfeldModule(A, [T, 1])
342331
sage: q = 2
343332
sage: log[2] == -1/((T**q - T)) # expected value
@@ -374,8 +363,7 @@ def _compute_goss_polynomial(self, n, q, poly_ring, X):
374363
375364
TESTS::
376365
377-
sage: A = GF(2^2)['T']
378-
sage: K.<T> = Frac(A)
366+
sage: A.<T> = GF(2^2)[]
379367
sage: phi = DrinfeldModule(A, [T, T+1, T^2, 1])
380368
sage: poly_ring = phi.base()['X']
381369
sage: X = poly_ring.gen()
@@ -423,8 +411,7 @@ def goss_polynomial(self, n, var='X'):
423411
424412
EXAMPLES::
425413
426-
sage: A = GF(3)['T']
427-
sage: K.<T> = Frac(A)
414+
sage: A.<T> = GF(3)[]
428415
sage: phi = DrinfeldModule(A, [T, 1]) # Carlitz module
429416
sage: phi.goss_polynomial(1)
430417
X
@@ -459,8 +446,7 @@ class DrinfeldModule_rational(DrinfeldModule_charzero):
459446
460447
sage: q = 9
461448
sage: Fq = GF(q)
462-
sage: A = Fq['T']
463-
sage: K.<T> = Frac(A)
449+
sage: A.<T> = Fq[]
464450
sage: C = DrinfeldModule(A, [T, 1]); C
465451
Drinfeld module defined by T |--> t + T
466452
sage: type(C)
@@ -479,9 +465,8 @@ def coefficient_in_function_ring(self, n):
479465
480466
sage: q = 5
481467
sage: Fq = GF(q)
482-
sage: A = Fq['T']
483-
sage: R = Fq['U']
484-
sage: K.<U> = Frac(R)
468+
sage: A.<T> = Fq[]
469+
sage: R.<U> = Fq[]
485470
sage: phi = DrinfeldModule(A, [U, 0, U^2, U^3])
486471
sage: phi.coefficient_in_function_ring(2)
487472
T^2
@@ -524,9 +509,8 @@ def coefficients_in_function_ring(self, sparse=True):
524509
525510
sage: q = 5
526511
sage: Fq = GF(q)
527-
sage: A = Fq['T']
528-
sage: R = Fq['U']
529-
sage: K.<U> = Frac(R)
512+
sage: A.<T> = Fq[]
513+
sage: R.<U> = Fq[]
530514
sage: phi = DrinfeldModule(A, [U, 0, U^2, U^3])
531515
sage: phi.coefficients_in_function_ring()
532516
[T, T^2, T^3]
@@ -570,8 +554,7 @@ def class_polynomial(self):
570554
571555
sage: q = 5
572556
sage: Fq = GF(q)
573-
sage: A = Fq['T']
574-
sage: K.<T> = Frac(A)
557+
sage: A.<T> = Fq[]
575558
sage: C = DrinfeldModule(A, [T, 1]); C
576559
Drinfeld module defined by T |--> t + T
577560
sage: C.class_polynomial()

src/sage/rings/function_field/drinfeld_modules/drinfeld_module.py

Lines changed: 21 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -92,14 +92,16 @@ class DrinfeldModule(Parent, UniqueRepresentation):
9292
sage: phi
9393
Drinfeld module defined by T |--> t^2 + 4*t + z
9494
95-
::
95+
When the given coefficients naturally live in a ring, the
96+
Drinfeld module is constructed over the fraction field::
9697
9798
sage: Fq = GF(49)
9899
sage: A.<T> = Fq[]
99-
sage: K = Frac(A)
100-
sage: psi = DrinfeldModule(A, [K(T), T+1])
100+
sage: psi = DrinfeldModule(A, [T, T+1])
101101
sage: psi
102102
Drinfeld module defined by T |--> (T + 1)*t + T
103+
sage: psi.base()
104+
Fraction Field of Univariate Polynomial Ring in T over Finite Field in z2 of size 7^2 over its base
103105
104106
.. NOTE::
105107
@@ -150,8 +152,7 @@ class DrinfeldModule(Parent, UniqueRepresentation):
150152
151153
The above Drinfeld module is finite; it can also be infinite::
152154
153-
sage: L = Frac(A)
154-
sage: psi = DrinfeldModule(A, [L(T), 1, T^3 + T + 1])
155+
sage: psi = DrinfeldModule(A, [T, 1, T^3 + T + 1])
155156
sage: psi
156157
Drinfeld module defined by T |--> (T^3 + T + 1)*t^2 + t + T
157158
@@ -434,16 +435,6 @@ class DrinfeldModule(Parent, UniqueRepresentation):
434435
...
435436
ValueError: generator must have positive degree
436437
437-
The constant coefficient must be nonzero::
438-
439-
sage: Fq = GF(2)
440-
sage: K.<z> = Fq.extension(2)
441-
sage: A.<T> = Fq[]
442-
sage: DrinfeldModule(A, [K(0), K(1)])
443-
Traceback (most recent call last):
444-
...
445-
ValueError: constant coefficient must be nonzero
446-
447438
The coefficients of the generator must lie in an
448439
`\mathbb{F}_q[T]`-field, where `\mathbb{F}_q[T]` is the function
449440
ring of the Drinfeld module::
@@ -551,8 +542,7 @@ def __classcall_private__(cls, function_ring, gen, name='t'):
551542
552543
::
553544
554-
sage: K = Frac(A)
555-
sage: phi = DrinfeldModule(A, [K(T), 1])
545+
sage: phi = DrinfeldModule(A, [T, 1])
556546
sage: isinstance(psi, DrinfeldModule_finite)
557547
False
558548
"""
@@ -583,12 +573,13 @@ def __classcall_private__(cls, function_ring, gen, name='t'):
583573
ore_polring = None
584574
# Base ring without morphism structure:
585575
base_field = Sequence(gen).universe()
576+
try:
577+
base_field = base_field.fraction_field()
578+
except AttributeError:
579+
pass
586580
else:
587581
raise TypeError('generator must be list of coefficients or Ore '
588582
'polynomial')
589-
# Constant coefficient must be nonzero:
590-
if gen[0].is_zero():
591-
raise ValueError('constant coefficient must be nonzero')
592583
# The coefficients are in a base field that has coercion from Fq:
593584
if not (hasattr(base_field, 'has_coerce_map_from') and
594585
base_field.has_coerce_map_from(function_ring.base_ring())):
@@ -913,8 +904,7 @@ def basic_j_invariant_parameters(self, coeff_indices=None, nonzero=False):
913904
914905
EXAMPLES::
915906
916-
sage: A = GF(5)['T']
917-
sage: K.<T> = Frac(A)
907+
sage: A.<T> = GF(5)[]
918908
sage: phi = DrinfeldModule(A, [T, 0, T+1, T^2 + 1])
919909
sage: phi.basic_j_invariant_parameters()
920910
[((1,), (31, 1)),
@@ -948,8 +938,7 @@ def basic_j_invariant_parameters(self, coeff_indices=None, nonzero=False):
948938
One can specify the list of coefficients indices to be
949939
considered in the computation::
950940
951-
sage: A = GF(2)['T']
952-
sage: K.<T> = Frac(A)
941+
sage: A.<T> = GF(2)[]
953942
sage: phi = DrinfeldModule(A, [T, T, 1, T])
954943
sage: phi.basic_j_invariant_parameters([1, 2])
955944
[((1,), (7, 1)),
@@ -962,8 +951,7 @@ def basic_j_invariant_parameters(self, coeff_indices=None, nonzero=False):
962951
963952
TESTS::
964953
965-
sage: A = GF(5)['T']
966-
sage: K.<T> = Frac(A)
954+
sage: A.<T> = GF(5)[]
967955
sage: phi = DrinfeldModule(A, [T, 0, T+1, T^2 + 1])
968956
sage: phi.basic_j_invariant_parameters([1, 'x'])
969957
Traceback (most recent call last):
@@ -1100,8 +1088,7 @@ def basic_j_invariants(self, nonzero=False):
11001088
11011089
::
11021090
1103-
sage: A = GF(5)['T']
1104-
sage: K.<T> = Frac(A)
1091+
sage: A.<T> = GF(5)[]
11051092
sage: phi = DrinfeldModule(A, [T, T + 2, T+1, 1])
11061093
sage: J_phi = phi.basic_j_invariants(); J_phi
11071094
{((1,), (31, 1)): T^31 + 2*T^30 + 2*T^26 + 4*T^25 + 2*T^6 + 4*T^5 + 4*T + 3,
@@ -1267,8 +1254,7 @@ def height(self):
12671254
characteristic; that is why an error is raised::
12681255
12691256
sage: B.<Y> = Fq[]
1270-
sage: L = Frac(B)
1271-
sage: phi = DrinfeldModule(A, [L(2), L(1)])
1257+
sage: phi = DrinfeldModule(A, [B(2), B(1)])
12721258
sage: phi.height()
12731259
Traceback (most recent call last):
12741260
...
@@ -1458,8 +1444,7 @@ def is_finite(self) -> bool:
14581444
sage: phi.is_finite()
14591445
True
14601446
sage: B.<Y> = Fq[]
1461-
sage: L = Frac(B)
1462-
sage: psi = DrinfeldModule(A, [L(2), L(1)])
1447+
sage: psi = DrinfeldModule(A, [B(2), B(1)])
14631448
sage: psi.is_finite()
14641449
False
14651450
"""
@@ -1564,8 +1549,7 @@ def j_invariant(self, parameter=None, check=True):
15641549
15651550
::
15661551
1567-
sage: A = GF(5)['T']
1568-
sage: K.<T> = Frac(A)
1552+
sage: A.<T> = GF(5)[]
15691553
sage: phi = DrinfeldModule(A, [T, T^2, 1, T + 1, T^3])
15701554
sage: phi.j_invariant(1)
15711555
T^309
@@ -1591,8 +1575,7 @@ def j_invariant(self, parameter=None, check=True):
15911575
The list of all basic `j`-invariant parameters can be retrieved
15921576
using the method :meth:`basic_j_invariant_parameters`::
15931577
1594-
sage: A = GF(3)['T']
1595-
sage: K.<T> = Frac(A)
1578+
sage: A.<T> = GF(3)[]
15961579
sage: phi = DrinfeldModule(A, [T, T^2 + T + 1, 0, T^4 + 1, T - 1])
15971580
sage: param = phi.basic_j_invariant_parameters(nonzero=True)
15981581
sage: phi.j_invariant(param[1])
@@ -1602,8 +1585,7 @@ def j_invariant(self, parameter=None, check=True):
16021585
16031586
TESTS::
16041587
1605-
sage: A = GF(5)['T']
1606-
sage: K.<T> = Frac(A)
1588+
sage: A.<T> = GF(5)[]
16071589
sage: phi = DrinfeldModule(A, [T, T^2, 1, T + 1, T^3])
16081590
sage: phi.j_invariant()
16091591
Traceback (most recent call last):
@@ -1743,8 +1725,7 @@ def jk_invariants(self):
17431725
17441726
EXAMPLES::
17451727
1746-
sage: A = GF(3)['T']
1747-
sage: K.<T> = Frac(A)
1728+
sage: A.<T> = GF(3)[]
17481729
sage: phi = DrinfeldModule(A, [T, 1, T+1, T^3, T^6])
17491730
sage: jk_inv = phi.jk_invariants(); jk_inv
17501731
{1: 1/T^6, 2: (T^10 + T^9 + T + 1)/T^6, 3: T^42}

src/sage/rings/function_field/drinfeld_modules/homset.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ class DrinfeldModuleHomset(Homset):
167167
The domain and codomain must have the same Drinfeld modules
168168
category::
169169
170-
sage: rho = DrinfeldModule(A, [Frac(A)(T), 1])
170+
sage: rho = DrinfeldModule(A, [T, 1])
171171
sage: Hom(phi, rho)
172172
Traceback (most recent call last):
173173
...

0 commit comments

Comments
 (0)