Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/sage/rings/finite_rings/hom_finite_field.pyx
8820 views
1
"""
2
This file provides several classes implementing:
3
4
- embeddings between finite fields
5
6
- Frobenius isomorphism on finite fields
7
8
EXAMPLES::
9
10
sage: from sage.rings.finite_rings.hom_finite_field import FiniteFieldHomomorphism_generic
11
12
Construction of an embedding::
13
14
sage: k.<t> = GF(3^7)
15
sage: K.<T> = GF(3^21)
16
sage: f = FiniteFieldHomomorphism_generic(Hom(k, K)); f
17
Ring morphism:
18
From: Finite Field in t of size 3^7
19
To: Finite Field in T of size 3^21
20
Defn: t |--> T^20 + T^19 + T^18 + 2*T^17 + 2*T^16 + 2*T^12 + T^9 + T^6 + 2*T^5 + T^3 + 2*T^2 + T + 2
21
22
sage: f(t)
23
T^20 + T^19 + T^18 + 2*T^17 + 2*T^16 + 2*T^12 + T^9 + T^6 + 2*T^5 + T^3 + 2*T^2 + T + 2
24
25
The map `f` has a method ``section`` which returns a partially defined
26
map which is the inverse of `f` on the image of `f`::
27
28
sage: g = f.section(); g
29
Section of Ring morphism:
30
From: Finite Field in t of size 3^7
31
To: Finite Field in T of size 3^21
32
Defn: t |--> T^20 + T^19 + T^18 + 2*T^17 + 2*T^16 + 2*T^12 + T^9 + T^6 + 2*T^5 + T^3 + 2*T^2 + T + 2
33
sage: g(f(t^3+t^2+1))
34
t^3 + t^2 + 1
35
sage: g(T)
36
Traceback (most recent call last):
37
...
38
ValueError: T is not in the image of Ring morphism:
39
From: Finite Field in t of size 3^7
40
To: Finite Field in T of size 3^21
41
Defn: t |--> T^20 + T^19 + T^18 + 2*T^17 + 2*T^16 + 2*T^12 + T^9 + T^6 + 2*T^5 + T^3 + 2*T^2 + T + 2
42
43
There is no embedding of `GF(5^6)` into `GF(5^11)`::
44
45
sage: k.<t> = GF(5^6)
46
sage: K.<T> = GF(5^11)
47
sage: FiniteFieldHomomorphism_generic(Hom(k, K))
48
Traceback (most recent call last):
49
...
50
ValueError: No embedding of Finite Field in t of size 5^6 into Finite Field in T of size 5^11
51
52
53
Construction of Frobenius endomorphisms::
54
55
sage: k.<t> = GF(7^14)
56
sage: Frob = k.frobenius_endomorphism(); Frob
57
Frobenius endomorphism t |--> t^7 on Finite Field in t of size 7^14
58
sage: Frob(t)
59
t^7
60
61
Some basic arithmetics is supported::
62
63
sage: Frob^2
64
Frobenius endomorphism t |--> t^(7^2) on Finite Field in t of size 7^14
65
sage: f = k.frobenius_endomorphism(7); f
66
Frobenius endomorphism t |--> t^(7^7) on Finite Field in t of size 7^14
67
sage: f*Frob
68
Frobenius endomorphism t |--> t^(7^8) on Finite Field in t of size 7^14
69
70
sage: Frob.order()
71
14
72
sage: f.order()
73
2
74
75
Note that simplifications are made automatically::
76
77
sage: Frob^16
78
Frobenius endomorphism t |--> t^(7^2) on Finite Field in t of size 7^14
79
sage: Frob^28
80
Identity endomorphism of Finite Field in t of size 7^14
81
82
And that comparisons work::
83
84
sage: Frob == Frob^15
85
True
86
sage: Frob^14 == Hom(k, k).identity()
87
True
88
89
AUTHOR:
90
91
- Xavier Caruso (2012-06-29)
92
"""
93
94
#############################################################################
95
# Copyright (C) 2012 Xavier Caruso <[email protected]>
96
#
97
# Distributed under the terms of the GNU General Public License (GPL)
98
#
99
# http://www.gnu.org/licenses/
100
#****************************************************************************
101
102
103
from sage.rings.integer cimport Integer
104
105
from sage.categories.homset import Hom
106
from sage.structure.element cimport Element
107
108
from sage.rings.finite_rings.finite_field_base import is_FiniteField
109
from sage.rings.morphism cimport RingHomomorphism, RingHomomorphism_im_gens, FrobeniusEndomorphism_generic
110
from sage.rings.finite_rings.constructor import FiniteField
111
112
from sage.categories.map cimport Section
113
from sage.categories.morphism cimport Morphism
114
115
from sage.misc.cachefunc import cached_method
116
117
118
cdef class SectionFiniteFieldHomomorphism_generic(Section):
119
"""
120
A class implementing sections of embeddings between finite fields.
121
"""
122
cpdef Element _call_(self, x): # Not optimized
123
"""
124
TESTS::
125
126
sage: from sage.rings.finite_rings.hom_finite_field import FiniteFieldHomomorphism_generic
127
sage: k.<t> = GF(3^7)
128
sage: K.<T> = GF(3^21)
129
sage: f = FiniteFieldHomomorphism_generic(Hom(k, K))
130
sage: g = f.section()
131
sage: g(f(t^3+t^2+1))
132
t^3 + t^2 + 1
133
134
sage: g(T)
135
Traceback (most recent call last):
136
...
137
ValueError: T is not in the image of Ring morphism:
138
From: Finite Field in t of size 3^7
139
To: Finite Field in T of size 3^21
140
Defn: t |--> T^20 + T^19 + T^18 + 2*T^17 + 2*T^16 + 2*T^12 + T^9 + T^6 + 2*T^5 + T^3 + 2*T^2 + T + 2
141
"""
142
for root, _ in x.minimal_polynomial().roots(ring=self.codomain()):
143
if self._inverse(root) == x:
144
return root
145
raise ValueError("%s is not in the image of %s" % (x, self._inverse))
146
147
148
def _repr_(self):
149
"""
150
Return a string representation of this section.
151
152
EXAMPLES::
153
154
sage: from sage.rings.finite_rings.hom_finite_field import FiniteFieldHomomorphism_generic
155
sage: k.<t> = GF(3^7)
156
sage: K.<T> = GF(3^21)
157
sage: f = FiniteFieldHomomorphism_generic(Hom(k, K))
158
sage: g = f.section()
159
sage: g._repr_()
160
'Section of Ring morphism:\n From: Finite Field in t of size 3^7\n To: Finite Field in T of size 3^21\n Defn: t |--> T^20 + T^19 + T^18 + 2*T^17 + 2*T^16 + 2*T^12 + T^9 + T^6 + 2*T^5 + T^3 + 2*T^2 + T + 2'
161
"""
162
return "Section of %s" % self._inverse
163
164
165
def _latex_(self):
166
r"""
167
Return a latex representation of this section.
168
169
EXAMPLES::
170
171
sage: from sage.rings.finite_rings.hom_finite_field import FiniteFieldHomomorphism_generic
172
sage: k.<t> = GF(3^7)
173
sage: K.<T> = GF(3^21)
174
sage: f = FiniteFieldHomomorphism_generic(Hom(k, K))
175
sage: g = f.section()
176
sage: g._latex_()
177
'\\verb"Section of "\\Bold{F}_{3^{7}} \\hookrightarrow \\Bold{F}_{3^{21}}'
178
"""
179
return '\\verb"Section of "' + self._inverse._latex_()
180
181
182
183
cdef class FiniteFieldHomomorphism_generic(RingHomomorphism_im_gens):
184
"""
185
A class implementing embeddings between finite fields.
186
"""
187
def __init__(self, parent, im_gens=None, check=True, section_class=None):
188
"""
189
TESTS::
190
191
sage: from sage.rings.finite_rings.hom_finite_field import FiniteFieldHomomorphism_generic
192
sage: k.<t> = GF(3^7)
193
sage: K.<T> = GF(3^21)
194
sage: f = FiniteFieldHomomorphism_generic(Hom(k, K)); f
195
Ring morphism:
196
From: Finite Field in t of size 3^7
197
To: Finite Field in T of size 3^21
198
Defn: t |--> T^20 + T^19 + T^18 + 2*T^17 + 2*T^16 + 2*T^12 + T^9 + T^6 + 2*T^5 + T^3 + 2*T^2 + T + 2
199
200
sage: k.<t> = GF(3^6)
201
sage: K.<t> = GF(3^9)
202
sage: FiniteFieldHomomorphism_generic(Hom(k, K))
203
Traceback (most recent call last):
204
...
205
ValueError: No embedding of Finite Field in t of size 3^6 into Finite Field in t of size 3^9
206
207
sage: FiniteFieldHomomorphism_generic(Hom(ZZ, QQ))
208
Traceback (most recent call last):
209
...
210
TypeError: The domain is not a finite field
211
212
sage: R.<x> = k[]
213
sage: FiniteFieldHomomorphism_generic(Hom(k, R))
214
Traceback (most recent call last):
215
...
216
TypeError: The codomain is not a finite field
217
"""
218
domain = parent.domain()
219
codomain = parent.codomain()
220
if not is_FiniteField(domain):
221
raise TypeError("The domain is not a finite field")
222
if not is_FiniteField(codomain):
223
raise TypeError("The codomain is not a finite field")
224
if domain.characteristic() != codomain.characteristic() or codomain.degree() % domain.degree() != 0:
225
raise ValueError("No embedding of %s into %s" % (domain, codomain))
226
if im_gens is None:
227
im_gens = domain.modulus().any_root(codomain)
228
check=False
229
RingHomomorphism_im_gens.__init__(self, parent, im_gens, check)
230
if section_class == None:
231
self._section_class = SectionFiniteFieldHomomorphism_generic
232
else:
233
self._section_class = section_class
234
235
236
def _latex_(self):
237
r"""
238
Return a latex representation of this embedding.
239
240
EXAMPLES::
241
242
sage: from sage.rings.finite_rings.hom_finite_field import FiniteFieldHomomorphism_generic
243
sage: k.<t> = GF(3^7)
244
sage: K.<T> = GF(3^21)
245
sage: f = FiniteFieldHomomorphism_generic(Hom(k, K))
246
sage: f._latex_()
247
'\\Bold{F}_{3^{7}} \\hookrightarrow \\Bold{F}_{3^{21}}'
248
"""
249
return self.domain()._latex_() + " \\hookrightarrow " + self.codomain()._latex_()
250
251
252
cpdef Element _call_(self, x):
253
"""
254
TESTS::
255
256
sage: from sage.rings.finite_rings.hom_finite_field import FiniteFieldHomomorphism_generic
257
sage: k.<t> = GF(3^3)
258
sage: K.<T> = GF(3^9)
259
sage: f = FiniteFieldHomomorphism_generic(Hom(k, K))
260
sage: f(t)
261
2*T^6 + 2*T^4 + T^2 + T
262
263
sage: a = k.random_element()
264
sage: b = k.random_element()
265
sage: f(a+b) == f(a) + f(b)
266
True
267
sage: f(a*b) == f(a) * f(b)
268
True
269
"""
270
if not self.domain().has_coerce_map_from(x.parent()):
271
raise TypeError("%s does not coerce to %s" % (x, self.domain()))
272
return x.polynomial()(self.im_gens()[0])
273
274
275
def is_injective(self):
276
"""
277
Return True since a embedding between finite fields is
278
always injective.
279
280
EXAMPLES::
281
282
sage: from sage.rings.finite_rings.hom_finite_field import FiniteFieldHomomorphism_generic
283
sage: k.<t> = GF(3^3)
284
sage: K.<T> = GF(3^9)
285
sage: f = FiniteFieldHomomorphism_generic(Hom(k, K))
286
sage: f.is_injective()
287
True
288
"""
289
return True
290
291
292
def is_surjective(self):
293
"""
294
Return true if this embedding is surjective (and hence an
295
isomorphism.
296
297
EXAMPLES::
298
299
sage: from sage.rings.finite_rings.hom_finite_field import FiniteFieldHomomorphism_generic
300
sage: k.<t> = GF(3^3)
301
sage: K.<T> = GF(3^9)
302
sage: f = FiniteFieldHomomorphism_generic(Hom(k, K))
303
sage: f.is_surjective()
304
False
305
sage: g = FiniteFieldHomomorphism_generic(Hom(k, k))
306
sage: g.is_surjective()
307
True
308
"""
309
return self.domain().cardinality() == self.codomain().cardinality()
310
311
312
@cached_method
313
def section(self):
314
"""
315
Return the ``inverse`` of this embedding.
316
317
It is a partially defined map whose domain is the codomain
318
of the embedding, but which is only defined on the image of
319
the embedding.
320
321
EXAMPLES::
322
323
sage: from sage.rings.finite_rings.hom_finite_field import FiniteFieldHomomorphism_generic
324
sage: k.<t> = GF(3^7)
325
sage: K.<T> = GF(3^21)
326
sage: f = FiniteFieldHomomorphism_generic(Hom(k, K));
327
sage: g = f.section(); g
328
Section of Ring morphism:
329
From: Finite Field in t of size 3^7
330
To: Finite Field in T of size 3^21
331
Defn: t |--> T^20 + T^19 + T^18 + 2*T^17 + 2*T^16 + 2*T^12 + T^9 + T^6 + 2*T^5 + T^3 + 2*T^2 + T + 2
332
sage: g(f(t^3+t^2+1))
333
t^3 + t^2 + 1
334
sage: g(T)
335
Traceback (most recent call last):
336
...
337
ValueError: T is not in the image of Ring morphism:
338
From: Finite Field in t of size 3^7
339
To: Finite Field in T of size 3^21
340
Defn: t |--> T^20 + T^19 + T^18 + 2*T^17 + 2*T^16 + 2*T^12 + T^9 + T^6 + 2*T^5 + T^3 + 2*T^2 + T + 2
341
"""
342
return self._section_class(self)
343
344
345
def __richcmp__(left, right, int op):
346
return (<Element>left)._richcmp(right, op)
347
348
349
def __hash__(self):
350
return Morphism.__hash__(self)
351
352
353
354
cdef class FrobeniusEndomorphism_finite_field(FrobeniusEndomorphism_generic):
355
"""
356
A class implementing Frobenius endomorphisms on finite fields.
357
"""
358
def __init__(self, domain, n=1):
359
"""
360
INPUT:
361
362
- ``domain`` -- a finite field
363
364
- ``n`` -- an integer (default: 1)
365
366
.. NOTE::
367
368
`n` may be negative.
369
370
OUTPUT:
371
372
The `n`-th power of the absolute (arithmetic) Frobenius
373
endomorphism on ``domain``
374
375
TESTS::
376
377
sage: from sage.rings.finite_rings.hom_finite_field import FrobeniusEndomorphism_finite_field
378
sage: k.<t> = GF(5^3)
379
sage: FrobeniusEndomorphism_finite_field(k)
380
Frobenius endomorphism t |--> t^5 on Finite Field in t of size 5^3
381
sage: FrobeniusEndomorphism_finite_field(k, 2)
382
Frobenius endomorphism t |--> t^(5^2) on Finite Field in t of size 5^3
383
384
sage: FrobeniusEndomorphism_finite_field(k, t)
385
Traceback (most recent call last):
386
...
387
TypeError: n (=t) is not an integer
388
389
sage: FrobeniusEndomorphism_finite_field(k['x'])
390
Traceback (most recent call last):
391
...
392
TypeError: The domain must be a finite field
393
"""
394
if not is_FiniteField(domain):
395
raise TypeError("The domain must be a finite field")
396
try:
397
n = Integer(n)
398
except TypeError:
399
raise TypeError("n (=%s) is not an integer" % n)
400
401
if domain.is_finite():
402
self._degree = domain.degree()
403
self._power = n % self._degree
404
self._degree_fixed = domain.degree().gcd(self._power)
405
self._order = self._degree / self._degree_fixed
406
self._q = domain.characteristic() ** self._power
407
RingHomomorphism.__init__(self, Hom(domain, domain))
408
409
410
def _repr_(self):
411
"""
412
Return a string representation of this endomorphism.
413
414
EXAMPLES::
415
416
sage: k.<t> = GF(5^3)
417
sage: Frob = k.frobenius_endomorphism(); Frob
418
Frobenius endomorphism t |--> t^5 on Finite Field in t of size 5^3
419
420
sage: Frob._repr_()
421
'Frobenius endomorphism t |--> t^5 on Finite Field in t of size 5^3'
422
"""
423
name = self.domain().variable_name()
424
if self._power == 0:
425
s = "Identity endomorphism of"
426
elif self._power == 1:
427
s = "Frobenius endomorphism %s |--> %s^%s on" % (name, name, self.domain().characteristic())
428
else:
429
s = "Frobenius endomorphism %s |--> %s^(%s^%s) on" % (name, name, self.domain().characteristic(), self._power)
430
s += " %s" % self.domain()
431
return s
432
433
434
def _repr_short(self):
435
"""
436
Return a short string representation of this endomorphism.
437
438
EXAMPLES::
439
440
sage: k.<t> = GF(5^3)
441
sage: Frob = k.frobenius_endomorphism(); Frob
442
Frobenius endomorphism t |--> t^5 on Finite Field in t of size 5^3
443
444
sage: Frob._repr_short()
445
't |--> t^5'
446
"""
447
name = self.domain().variable_name()
448
if self._power == 0:
449
s = "Identity"
450
elif self._power == 1:
451
s = "%s |--> %s^%s" % (name, name, self.domain().characteristic())
452
else:
453
s = "%s |--> %s^(%s^%s)" % (name, name, self.domain().characteristic(), self._power)
454
return s
455
456
457
def _latex_(self):
458
r"""
459
Return a latex representation of this endomorphism.
460
461
EXAMPLES::
462
463
sage: k.<t> = GF(5^3)
464
sage: Frob = k.frobenius_endomorphism()
465
sage: Frob._latex_()
466
't \\mapsto t^{5}'
467
"""
468
try:
469
name = self.domain().latex_variable_names()[0]
470
except IndexError:
471
name = "x"
472
if self._power == 0:
473
s = '\\verb"id"'
474
elif self._power == 1:
475
s = "%s \\mapsto %s^{%s}" % (name, name, self.domain().characteristic())
476
else:
477
s = "%s \\mapsto %s^{%s^{%s}}" % (name, name, self.domain().characteristic(), self._power)
478
return s
479
480
481
cpdef Element _call_(self, x):
482
"""
483
TESTS::
484
485
sage: k.<t> = GF(5^3)
486
sage: Frob = k.frobenius_endomorphism()
487
sage: Frob(t)
488
2*t^2 + 4*t + 4
489
sage: Frob(t) == t^5
490
True
491
"""
492
return x ** self._q
493
494
495
def order(self):
496
"""
497
Return the order of this endomorphism.
498
499
EXAMPLES::
500
501
sage: k.<t> = GF(5^12)
502
sage: Frob = k.frobenius_endomorphism()
503
sage: Frob.order()
504
12
505
sage: (Frob^2).order()
506
6
507
sage: (Frob^9).order()
508
4
509
"""
510
if self._order == 0:
511
from sage.rings.infinity import Infinity
512
return Infinity
513
else:
514
return Integer(self._order)
515
516
def power(self):
517
"""
518
Return an integer `n` such that this endormorphism
519
is the `n`-th power of the absolute (arithmetic)
520
Frobenius.
521
522
EXAMPLES::
523
524
sage: k.<t> = GF(5^12)
525
sage: Frob = k.frobenius_endomorphism()
526
sage: Frob.power()
527
1
528
sage: (Frob^9).power()
529
9
530
sage: (Frob^13).power()
531
1
532
"""
533
return self._power
534
535
536
def __pow__(self, n, modulus):
537
"""
538
Return the `n`-th iterate of this endomorphism.
539
540
EXAMPLES::
541
542
sage: k.<t> = GF(5^12)
543
sage: Frob = k.frobenius_endomorphism(); Frob
544
Frobenius endomorphism t |--> t^5 on Finite Field in t of size 5^12
545
sage: Frob^2
546
Frobenius endomorphism t |--> t^(5^2) on Finite Field in t of size 5^12
547
548
The result is simplified if possible::
549
550
sage: Frob^15
551
Frobenius endomorphism t |--> t^(5^3) on Finite Field in t of size 5^12
552
sage: Frob^36
553
Identity endomorphism of Finite Field in t of size 5^12
554
"""
555
return self.__class__(self.domain(), self.power()*n)
556
557
558
def _composition(self, right):
559
"""
560
Return self o right.
561
562
EXAMPLES::
563
564
sage: k.<t> = GF(5^12)
565
sage: f = k.frobenius_endomorphism(); f
566
Frobenius endomorphism t |--> t^5 on Finite Field in t of size 5^12
567
sage: g = k.frobenius_endomorphism(2); g
568
Frobenius endomorphism t |--> t^(5^2) on Finite Field in t of size 5^12
569
sage: f * g
570
Frobenius endomorphism t |--> t^(5^3) on Finite Field in t of size 5^12
571
572
The result is simplified if possible::
573
574
sage: f = k.frobenius_endomorphism(9)
575
sage: g = k.frobenius_endomorphism(10)
576
sage: f * g
577
Frobenius endomorphism t |--> t^(5^7) on Finite Field in t of size 5^12
578
"""
579
if isinstance(right, FrobeniusEndomorphism_finite_field):
580
return self.__class__(self.domain(), self._power + right.power())
581
else:
582
return RingHomomorphism._composition(self, right)
583
584
585
def fixed_field(self):
586
"""
587
Return the fixed field of ``self``.
588
589
OUTPUT:
590
591
- a tuple `(K, e)`, where `K` is the subfield of the domain
592
consisting of elements fixed by ``self`` and `e` is an
593
embedding of `K` into the domain.
594
595
.. NOTE::
596
597
The name of the variable used for the subfield (if it
598
is not a prime subfield) is suffixed by ``_fixed``.
599
600
EXAMPLES::
601
602
sage: k.<t> = GF(5^6)
603
sage: f = k.frobenius_endomorphism(2)
604
sage: kfixed, embed = f.fixed_field()
605
sage: kfixed
606
Finite Field in t_fixed of size 5^2
607
sage: embed
608
Ring morphism:
609
From: Finite Field in t_fixed of size 5^2
610
To: Finite Field in t of size 5^6
611
Defn: t_fixed |--> 4*t^5 + 2*t^4 + 4*t^2 + t
612
613
sage: tfixed = kfixed.gen()
614
sage: embed(tfixed)
615
4*t^5 + 2*t^4 + 4*t^2 + t
616
"""
617
if self._degree_fixed == 1:
618
k = FiniteField(self._domain.characteristic())
619
from hom_prime_finite_field import FiniteFieldHomomorphism_prime
620
f = FiniteFieldHomomorphism_prime(Hom(k, self._domain))
621
else:
622
k = FiniteField(self._domain.characteristic()**self._degree_fixed,
623
name=self._domain.variable_name() + "_fixed")
624
f = FiniteFieldHomomorphism_generic(Hom(k, self._domain))
625
return k, f
626
627
628
def is_injective(self):
629
"""
630
Return true since any power of the Frobenius endomorphism
631
over a finite field is always injective.
632
633
EXAMPLES::
634
635
sage: k.<t> = GF(5^3)
636
sage: Frob = k.frobenius_endomorphism()
637
sage: Frob.is_injective()
638
True
639
"""
640
return True
641
642
643
def is_surjective(self):
644
"""
645
Return true since any power of the Frobenius endomorphism
646
over a finite field is always surjective.
647
648
EXAMPLES::
649
650
sage: k.<t> = GF(5^3)
651
sage: Frob = k.frobenius_endomorphism()
652
sage: Frob.is_surjective()
653
True
654
"""
655
return True
656
657
658
def is_identity(self):
659
"""
660
Return true if this morphism is the identity morphism.
661
662
EXAMPLES::
663
664
sage: k.<t> = GF(5^3)
665
sage: Frob = k.frobenius_endomorphism()
666
sage: Frob.is_identity()
667
False
668
sage: (Frob^3).is_identity()
669
True
670
"""
671
return self.power() == 0
672
673
674
def __richcmp__(left, right, int op):
675
return (<Element>left)._richcmp(right, op)
676
677
678
def __hash__(self):
679
return Morphism.__hash__(self)
680
681
682
from sage.structure.sage_object import register_unpickle_override
683
register_unpickle_override('sage.rings.finite_field_morphism', 'FiniteFieldHomomorphism_generic', FiniteFieldHomomorphism_generic)
684
685