Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/sage/rings/finite_rings/finite_field_givaro.py
8820 views
1
"""
2
Givaro Finite Field
3
4
Finite fields that are implemented using Zech logs and the
5
cardinality must be less than `2^{16}`. By default, conway polynomials are
6
used as minimal polynomial.
7
"""
8
9
from sage.rings.finite_rings.finite_field_base import FiniteField, is_FiniteField
10
from sage.rings.integer import Integer
11
from sage.rings.finite_rings.element_givaro import Cache_givaro
12
from sage.rings.integer_ring import ZZ
13
from sage.databases.conway import ConwayPolynomials
14
from sage.rings.finite_rings.integer_mod_ring import IntegerModRing_generic
15
from sage.libs.pari.all import pari
16
17
class FiniteField_givaro(FiniteField):
18
"""
19
Finite field implemented using Zech logs and the cardinality must be
20
less than `2^{16}`. By default, conway polynomials are used as minimal
21
polynomials.
22
23
INPUT:
24
25
- ``q`` -- `p^n` (must be prime power)
26
27
- ``name`` -- (default: ``'a'``) variable used for
28
:meth:`~sage.rings.finite_rings.element_givaro.FiniteField_givaroElement.poly_repr()`
29
30
- ``modulus`` -- (default: ``None``, a conway polynomial is used if found.
31
Otherwise a random polynomial is used) A minimal polynomial to use for
32
reduction or ``'random'`` to force a random irreducible polynomial.
33
34
- ``repr`` -- (default: ``'poly'``) controls the way elements are printed
35
to the user:
36
37
- 'log': repr is
38
:meth:`~sage.rings.finite_rings.element_givaro.FiniteField_givaroElement.log_repr()`
39
- 'int': repr is
40
:meth:`~sage.rings.finite_rings.element_givaro.FiniteField_givaroElement.int_repr()`
41
- 'poly': repr is
42
:meth:`~sage.rings.finite_rings.element_givaro.FiniteField_givaroElement.poly_repr()`
43
44
- cache -- (default: ``False``) if ``True`` a cache of all elements of
45
this field is created. Thus, arithmetic does not create new elements
46
which speeds calculations up. Also, if many elements are needed during a
47
calculation this cache reduces the memory requirement as at most
48
:meth:`order` elements are created.
49
50
OUTPUT:
51
52
Givaro finite field with characteristic `p` and cardinality `p^n`.
53
54
EXAMPLES:
55
56
By default conway polynomials are used::
57
58
sage: k.<a> = GF(2**8)
59
sage: -a ^ k.degree()
60
a^4 + a^3 + a^2 + 1
61
sage: f = k.modulus(); f
62
x^8 + x^4 + x^3 + x^2 + 1
63
64
You may enforce a modulus::
65
66
sage: P.<x> = PolynomialRing(GF(2))
67
sage: f = x^8 + x^4 + x^3 + x + 1 # Rijndael Polynomial
68
sage: k.<a> = GF(2^8, modulus=f)
69
sage: k.modulus()
70
x^8 + x^4 + x^3 + x + 1
71
sage: a^(2^8)
72
a
73
74
You may enforce a random modulus::
75
76
sage: k = GF(3**5, 'a', modulus='random')
77
sage: k.modulus() # random polynomial
78
x^5 + 2*x^4 + 2*x^3 + x^2 + 2
79
80
Three different representations are possible::
81
82
sage: sage.rings.finite_rings.finite_field_givaro.FiniteField_givaro(9,repr='poly').gen()
83
a
84
sage: sage.rings.finite_rings.finite_field_givaro.FiniteField_givaro(9,repr='int').gen()
85
3
86
sage: sage.rings.finite_rings.finite_field_givaro.FiniteField_givaro(9,repr='log').gen()
87
1
88
"""
89
def __init__(self, q, name="a", modulus=None, repr="poly", cache=False):
90
"""
91
Initialize ``self``.
92
93
EXAMPLES::
94
95
sage: k.<a> = GF(2^3)
96
sage: j.<b> = GF(3^4)
97
sage: k == j
98
False
99
100
sage: GF(2^3,'a') == copy(GF(2^3,'a'))
101
True
102
sage: TestSuite(GF(2^3, 'a')).run()
103
"""
104
self._kwargs = {}
105
106
if repr not in ['int', 'log', 'poly']:
107
raise ValueError, "Unknown representation %s"%repr
108
109
q = Integer(q)
110
if q < 2:
111
raise ValueError, "q must be a prime power"
112
F = q.factor()
113
if len(F) > 1:
114
raise ValueError, "q must be a prime power"
115
p = F[0][0]
116
k = F[0][1]
117
118
if q >= 1<<16:
119
raise ValueError, "q must be < 2^16"
120
121
import constructor
122
FiniteField.__init__(self, constructor.FiniteField(p), name, normalize=False)
123
124
self._kwargs['repr'] = repr
125
self._kwargs['cache'] = cache
126
127
if modulus is None or modulus == 'conway':
128
if k == 1:
129
modulus = 'random' # this will use the gfq_factory_pk function.
130
elif ConwayPolynomials().has_polynomial(p, k):
131
from sage.rings.finite_rings.conway_polynomials import conway_polynomial
132
modulus = conway_polynomial(p, k)
133
elif modulus is None:
134
modulus = 'random'
135
else:
136
raise ValueError, "Conway polynomial not found"
137
138
from sage.rings.polynomial.all import is_Polynomial
139
if is_Polynomial(modulus):
140
modulus = modulus.list()
141
142
self._cache = Cache_givaro(self, p, k, modulus, repr, cache)
143
144
def characteristic(self):
145
"""
146
Return the characteristic of this field.
147
148
EXAMPLES::
149
150
sage: p = GF(19^5,'a').characteristic(); p
151
19
152
sage: type(p)
153
<type 'sage.rings.integer.Integer'>
154
"""
155
return Integer(self._cache.characteristic())
156
157
def order(self):
158
"""
159
Return the cardinality of this field.
160
161
OUTPUT:
162
163
Integer -- the number of elements in ``self``.
164
165
EXAMPLES::
166
167
sage: n = GF(19^5,'a').order(); n
168
2476099
169
sage: type(n)
170
<type 'sage.rings.integer.Integer'>
171
"""
172
return self._cache.order()
173
174
def degree(self):
175
r"""
176
If the cardinality of ``self`` is `p^n`, then this returns `n`.
177
178
OUTPUT:
179
180
Integer -- the degree
181
182
EXAMPLES::
183
184
sage: GF(3^4,'a').degree()
185
4
186
"""
187
return Integer(self._cache.exponent())
188
189
def _repr_option(self, key):
190
"""
191
Metadata about the :meth:`_repr_` output.
192
193
See :meth:`sage.structure.parent._repr_option` for details.
194
195
EXAMPLES::
196
197
sage: GF(23**3, 'a', repr='log')._repr_option('element_is_atomic')
198
True
199
sage: GF(23**3, 'a', repr='int')._repr_option('element_is_atomic')
200
True
201
sage: GF(23**3, 'a', repr='poly')._repr_option('element_is_atomic')
202
False
203
"""
204
if key == 'element_is_atomic':
205
return self._cache.repr != 0 # 0 means repr='poly'
206
return super(FiniteField_givaro, self)._repr_option(key)
207
208
def random_element(self, *args, **kwds):
209
"""
210
Return a random element of ``self``.
211
212
EXAMPLES::
213
214
sage: k = GF(23**3, 'a')
215
sage: e = k.random_element(); e
216
2*a^2 + 14*a + 21
217
sage: type(e)
218
<type 'sage.rings.finite_rings.element_givaro.FiniteField_givaroElement'>
219
220
sage: P.<x> = PowerSeriesRing(GF(3^3, 'a'))
221
sage: P.random_element(5)
222
2*a + 2 + (a^2 + a + 2)*x + (2*a + 1)*x^2 + (2*a^2 + a)*x^3 + 2*a^2*x^4 + O(x^5)
223
"""
224
return self._cache.random_element()
225
226
def _element_constructor_(self, e):
227
"""
228
Coerces several data types to ``self``.
229
230
INPUT:
231
232
- ``e`` -- data to coerce
233
234
EXAMPLES:
235
236
:class:`FiniteField_givaroElement` are accepted where the parent
237
is either ``self``, equals ``self`` or is the prime subfield::
238
239
sage: k = GF(2**8, 'a')
240
sage: k.gen() == k(k.gen())
241
True
242
243
Floats, ints, longs, Integer are interpreted modulo characteristic::
244
245
sage: k(2) # indirect doctest
246
0
247
248
Floats coerce in:
249
sage: k(float(2.0))
250
0
251
252
Rational are interpreted as ``self(numerator)/self(denominator)``.
253
Both may not be greater than :meth:characteristic()`.
254
::
255
256
sage: k = GF(3**8, 'a')
257
sage: k(1/2) == k(1)/k(2)
258
True
259
260
Free module elements over :meth:`prime_subfield()` are interpreted
261
'little endian'::
262
263
sage: k = GF(2**8, 'a')
264
sage: e = k.vector_space().gen(1); e
265
(0, 1, 0, 0, 0, 0, 0, 0)
266
sage: k(e)
267
a
268
269
``None`` yields zero::
270
271
sage: k(None)
272
0
273
274
Strings are evaluated as polynomial representation of elements in
275
``self``::
276
277
sage: k('a^2+1')
278
a^2 + 1
279
280
Univariate polynomials coerce into finite fields by evaluating
281
the polynomial at the field's generator::
282
283
sage: from sage.rings.finite_rings.finite_field_givaro import FiniteField_givaro
284
sage: R.<x> = QQ[]
285
sage: k, a = FiniteField_givaro(5^2, 'a').objgen()
286
sage: k(R(2/3))
287
4
288
sage: k(x^2)
289
a + 3
290
sage: R.<x> = GF(5)[]
291
sage: k(x^3-2*x+1)
292
2*a + 4
293
294
sage: x = polygen(QQ)
295
sage: k(x^25)
296
a
297
298
sage: Q, q = FiniteField_givaro(5^3,'q').objgen()
299
sage: L = GF(5)
300
sage: LL.<xx> = L[]
301
sage: Q(xx^2 + 2*xx + 4)
302
q^2 + 2*q + 4
303
304
305
Multivariate polynomials only coerce if constant::
306
307
sage: R = k['x,y,z']; R
308
Multivariate Polynomial Ring in x, y, z over Finite Field in a of size 5^2
309
sage: k(R(2))
310
2
311
sage: R = QQ['x,y,z']
312
sage: k(R(1/5))
313
Traceback (most recent call last):
314
...
315
ZeroDivisionError: division by zero in finite field.
316
317
318
PARI elements are interpreted as finite field elements; this PARI
319
flexibility is (absurdly!) liberal::
320
321
sage: k = GF(2**8, 'a')
322
sage: k(pari('Mod(1,2)'))
323
1
324
sage: k(pari('Mod(2,3)'))
325
0
326
sage: k(pari('Mod(1,3)*a^20'))
327
a^7 + a^5 + a^4 + a^2
328
329
GAP elements need to be finite field elements::
330
331
sage: from sage.rings.finite_rings.finite_field_givaro import FiniteField_givaro
332
sage: x = gap('Z(13)')
333
sage: F = FiniteField_givaro(13)
334
sage: F(x)
335
2
336
sage: F(gap('0*Z(13)'))
337
0
338
sage: F = FiniteField_givaro(13^2)
339
sage: x = gap('Z(13)')
340
sage: F(x)
341
2
342
sage: x = gap('Z(13^2)^3')
343
sage: F(x)
344
12*a + 11
345
sage: F.multiplicative_generator()^3
346
12*a + 11
347
348
sage: k.<a> = GF(29^3)
349
sage: k(48771/1225)
350
28
351
352
sage: F9 = FiniteField(9, impl='givaro', conway=True, prefix='a')
353
sage: F81 = FiniteField(81, impl='givaro', conway=True, prefix='a')
354
sage: F81(F9.gen())
355
2*a4^3 + 2*a4^2 + 1
356
"""
357
return self._cache.element_from_data(e)
358
359
def gen(self, n=0):
360
r"""
361
Return a generator of ``self``.
362
363
All elements ``x`` of ``self`` are expressed as `\log_{g}(p)`
364
internally where `g` is the generator of ``self``.
365
366
This generator might differ between different runs or
367
different architectures.
368
369
.. WARNING::
370
371
The generator is not guaranteed to be a generator for
372
the multiplicative group. To obtain the latter, use
373
:meth:`~sage.rings.finite_rings.finite_field_base.FiniteFields.multiplicative_generator`.
374
375
EXAMPLES::
376
377
sage: k = GF(3^4, 'b'); k.gen()
378
b
379
sage: k.gen(1)
380
Traceback (most recent call last):
381
...
382
IndexError: only one generator
383
sage: F = sage.rings.finite_rings.finite_field_givaro.FiniteField_givaro(31)
384
sage: F.gen()
385
1
386
"""
387
if n > 0:
388
raise IndexError, "only one generator"
389
return self._cache.gen()
390
391
def prime_subfield(self):
392
r"""
393
Return the prime subfield `\GF{p}` of self if ``self`` is `\GF{p^n}`.
394
395
EXAMPLES::
396
397
sage: GF(3^4, 'b').prime_subfield()
398
Finite Field of size 3
399
400
sage: S.<b> = GF(5^2); S
401
Finite Field in b of size 5^2
402
sage: S.prime_subfield()
403
Finite Field of size 5
404
sage: type(S.prime_subfield())
405
<class 'sage.rings.finite_rings.finite_field_prime_modn.FiniteField_prime_modn_with_category'>
406
"""
407
try:
408
return self._prime_subfield
409
except AttributeError:
410
import constructor
411
self._prime_subfield = constructor.FiniteField(self.characteristic())
412
return self._prime_subfield
413
414
def log_to_int(self, n):
415
r"""
416
Given an integer `n` this method returns ``i`` where ``i``
417
satisfies `g^n = i` where `g` is the generator of ``self``; the
418
result is interpreted as an integer.
419
420
INPUT:
421
422
- ``n`` -- log representation of a finite field element
423
424
OUTPUT:
425
426
integer representation of a finite field element.
427
428
EXAMPLES::
429
430
sage: k = GF(2**8, 'a')
431
sage: k.log_to_int(4)
432
16
433
sage: k.log_to_int(20)
434
180
435
"""
436
return self._cache.log_to_int(n)
437
438
def int_to_log(self, n):
439
r"""
440
Given an integer `n` this method returns `i` where `i` satisfies
441
`g^i = n \mod p` where `g` is the generator and `p` is the
442
characteristic of ``self``.
443
444
INPUT:
445
446
- ``n`` -- integer representation of an finite field element
447
448
OUTPUT:
449
450
log representation of ``n``
451
452
EXAMPLES::
453
454
sage: k = GF(7**3, 'a')
455
sage: k.int_to_log(4)
456
228
457
sage: k.int_to_log(3)
458
57
459
sage: k.gen()^57
460
3
461
"""
462
return self._cache.int_to_log(n)
463
464
def fetch_int(self, n):
465
r"""
466
Given an integer `n` return a finite field element in ``self``
467
which equals `n` under the condition that :meth:`gen()` is set to
468
:meth:`characteristic()`.
469
470
EXAMPLES::
471
472
sage: k.<a> = GF(2^8)
473
sage: k.fetch_int(8)
474
a^3
475
sage: e = k.fetch_int(151); e
476
a^7 + a^4 + a^2 + a + 1
477
sage: 2^7 + 2^4 + 2^2 + 2 + 1
478
151
479
"""
480
return self._cache.fetch_int(n)
481
482
def polynomial(self, name=None):
483
"""
484
Return the defining polynomial of this field as an element of
485
:class:`PolynomialRing`.
486
487
This is the same as the characteristic polynomial of the
488
generator of ``self``.
489
490
INPUT:
491
492
- ``name`` -- optional name of the generator
493
494
EXAMPLES::
495
496
sage: k = GF(3^4, 'a')
497
sage: k.polynomial()
498
a^4 + 2*a^3 + 2
499
"""
500
if name is not None:
501
try:
502
return self._polynomial
503
except AttributeError:
504
pass
505
quo = (-(self.gen()**(self.degree()))).integer_representation()
506
b = int(self.characteristic())
507
508
ret = []
509
for i in range(self.degree()):
510
ret.append(quo%b)
511
quo = quo/b
512
ret = ret + [1]
513
R = self.polynomial_ring(name)
514
if name is None:
515
self._polynomial = R(ret)
516
return self._polynomial
517
else:
518
return R(ret)
519
520
def __hash__(self):
521
"""
522
The hash of a Givaro finite field is a hash over it's
523
characteristic polynomial and the string 'givaro'.
524
525
EXAMPLES::
526
527
sage: {GF(3^4, 'a'):1} # indirect doctest
528
{Finite Field in a of size 3^4: 1}
529
"""
530
try:
531
return self._hash
532
except AttributeError:
533
if self.degree() > 1:
534
self._hash = hash((self.characteristic(), self.polynomial(), self.variable_name(), "givaro"))
535
else:
536
self._hash = hash((self.characteristic(), self.variable_name(), "givaro"))
537
return self._hash
538
539
def _pari_modulus(self):
540
"""
541
Return the modulus of ``self`` in a format for PARI.
542
543
EXAMPLES::
544
545
sage: GF(3^4,'a')._pari_modulus()
546
Mod(1, 3)*a^4 + Mod(2, 3)*a^3 + Mod(2, 3)
547
"""
548
f = pari(str(self.modulus()))
549
return f.subst('x', 'a') * pari("Mod(1,%s)"%self.characteristic())
550
551
def _finite_field_ext_pari_(self): # todo -- cache
552
"""
553
Return a :class:`FiniteField_ext_pari` isomorphic to ``self`` with
554
the same defining polynomial.
555
556
EXAMPLES::
557
558
sage: GF(3^4,'z')._finite_field_ext_pari_()
559
Finite Field in z of size 3^4
560
"""
561
f = self.polynomial()
562
import finite_field_ext_pari
563
return finite_field_ext_pari.FiniteField_ext_pari(self.order(),
564
self.variable_name(), f)
565
566
def __iter__(self):
567
"""
568
Finite fields may be iterated over.
569
570
EXAMPLES::
571
572
sage: list(GF(2**2, 'a'))
573
[0, a, a + 1, 1]
574
"""
575
from element_givaro import FiniteField_givaro_iterator
576
return FiniteField_givaro_iterator(self._cache)
577
578
def a_times_b_plus_c(self, a, b, c):
579
"""
580
Return ``a*b + c``. This is faster than multiplying ``a`` and ``b``
581
first and adding ``c`` to the result.
582
583
INPUT:
584
585
- ``a,b,c`` -- :class:`~~sage.rings.finite_rings.element_givaro.FiniteField_givaroElement`
586
587
EXAMPLES::
588
589
sage: k.<a> = GF(2**8)
590
sage: k.a_times_b_plus_c(a,a,k(1))
591
a^2 + 1
592
"""
593
return self._cache.a_times_b_plus_c(a, b, c)
594
595
def a_times_b_minus_c(self, a, b, c):
596
"""
597
Return ``a*b - c``.
598
599
INPUT:
600
601
- ``a,b,c`` -- :class:`~sage.rings.finite_rings.element_givaro.FiniteField_givaroElement`
602
603
EXAMPLES::
604
605
sage: k.<a> = GF(3**3)
606
sage: k.a_times_b_minus_c(a,a,k(1))
607
a^2 + 2
608
"""
609
return self._cache.a_times_b_minus_c(a, b, c)
610
611
def c_minus_a_times_b(self, a, b, c):
612
"""
613
Return ``c - a*b``.
614
615
INPUT:
616
617
- ``a,b,c`` -- :class:`~sage.rings.finite_rings.element_givaro.FiniteField_givaroElement`
618
619
EXAMPLES::
620
621
sage: k.<a> = GF(3**3)
622
sage: k.c_minus_a_times_b(a,a,k(1))
623
2*a^2 + 1
624
"""
625
return self._cache.c_minus_a_times_b(a, b, c)
626
627
def frobenius_endomorphism(self, n=1):
628
"""
629
INPUT:
630
631
- ``n`` -- an integer (default: 1)
632
633
OUTPUT:
634
635
The `n`-th power of the absolute arithmetic Frobenius
636
endomorphism on this finite field.
637
638
EXAMPLES::
639
640
sage: k.<t> = GF(3^5)
641
sage: Frob = k.frobenius_endomorphism(); Frob
642
Frobenius endomorphism t |--> t^3 on Finite Field in t of size 3^5
643
644
sage: a = k.random_element()
645
sage: Frob(a) == a^3
646
True
647
648
We can specify a power::
649
650
sage: k.frobenius_endomorphism(2)
651
Frobenius endomorphism t |--> t^(3^2) on Finite Field in t of size 3^5
652
653
The result is simplified if possible::
654
655
sage: k.frobenius_endomorphism(6)
656
Frobenius endomorphism t |--> t^3 on Finite Field in t of size 3^5
657
sage: k.frobenius_endomorphism(5)
658
Identity endomorphism of Finite Field in t of size 3^5
659
660
Comparisons work::
661
662
sage: k.frobenius_endomorphism(6) == Frob
663
True
664
sage: from sage.categories.morphism import IdentityMorphism
665
sage: k.frobenius_endomorphism(5) == IdentityMorphism(k)
666
True
667
668
AUTHOR:
669
670
- Xavier Caruso (2012-06-29)
671
"""
672
from sage.rings.finite_rings.hom_finite_field_givaro import FrobeniusEndomorphism_givaro
673
return FrobeniusEndomorphism_givaro(self, n)
674
675