Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/sage/rings/finite_rings/finite_field_ntl_gf2e.py
8820 views
1
"""
2
Finite Fields of Characteristic 2
3
"""
4
5
from sage.rings.finite_rings.finite_field_base import FiniteField
6
from sage.libs.pari.all import pari
7
from finite_field_ext_pari import FiniteField_ext_pari
8
from sage.rings.integer_ring import ZZ
9
from sage.rings.integer import Integer
10
from sage.rings.finite_rings.integer_mod_ring import IntegerModRing_generic
11
12
def late_import():
13
"""
14
Imports various modules after startup.
15
16
EXAMPLES::
17
18
sage: sage.rings.finite_rings.finite_field_ntl_gf2e.late_import()
19
sage: sage.rings.finite_rings.finite_field_ntl_gf2e.GF2 is None # indirect doctest
20
False
21
"""
22
if globals().has_key("GF2"):
23
return
24
global ResidueField_generic, is_FiniteField, exists_conway_polynomial, conway_polynomial, Cache_ntl_gf2e, GF, GF2, is_Polynomial
25
import sage.rings.residue_field
26
ResidueField_generic = sage.rings.residue_field.ResidueField_generic
27
28
import sage.rings.finite_rings.finite_field_base
29
is_FiniteField = sage.rings.finite_rings.finite_field_base.is_FiniteField
30
31
import sage.rings.finite_rings.conway_polynomials
32
exists_conway_polynomial = sage.rings.finite_rings.conway_polynomials.exists_conway_polynomial
33
conway_polynomial = sage.rings.finite_rings.conway_polynomials.conway_polynomial
34
35
import sage.rings.finite_rings.element_ntl_gf2e
36
Cache_ntl_gf2e = sage.rings.finite_rings.element_ntl_gf2e.Cache_ntl_gf2e
37
38
import sage.rings.finite_rings.constructor
39
GF = sage.rings.finite_rings.constructor.GF
40
GF2 = GF(2)
41
42
import sage.rings.polynomial.polynomial_element
43
is_Polynomial = sage.rings.polynomial.polynomial_element.is_Polynomial
44
45
class FiniteField_ntl_gf2e(FiniteField):
46
"""
47
Finite Field of characteristic 2 and order `2^n`.
48
49
INPUT:
50
51
- ``q`` -- `2^n` (must be 2 power)
52
53
- ``names`` -- variable used for poly_repr (default: ``'a'``)
54
55
- ``modulus`` -- you may provide a polynomial to use for reduction or
56
a string:
57
58
- ``'conway'`` -- force the use of a Conway polynomial, will
59
raise a ``RuntimeError`` if ``None`` is found in the database;
60
- ``'minimal_weight'`` -- use a minimal weight polynomial, should
61
result in faster arithmetic;
62
- ``'random'`` -- use a random irreducible polynomial.
63
- ``'default'`` -- a Conway polynomial is used if found. Otherwise
64
a sparse polynomial is used.
65
66
- ``repr`` -- controls the way elements are printed to the user:
67
(default: ``'poly'``)
68
69
- ``'poly'``: polynomial representation
70
71
OUTPUT:
72
73
Finite field with characteristic 2 and cardinality `2^n`.
74
75
EXAMPLES::
76
77
sage: k.<a> = GF(2^16)
78
sage: type(k)
79
<class 'sage.rings.finite_rings.finite_field_ntl_gf2e.FiniteField_ntl_gf2e_with_category'>
80
sage: k.<a> = GF(2^1024)
81
sage: k.modulus()
82
x^1024 + x^19 + x^6 + x + 1
83
sage: set_random_seed(0)
84
sage: k.<a> = GF(2^17, modulus='random')
85
sage: k.modulus()
86
x^17 + x^16 + x^15 + x^10 + x^8 + x^6 + x^4 + x^3 + x^2 + x + 1
87
sage: k.modulus().is_irreducible()
88
True
89
sage: k.<a> = GF(2^211, modulus='minimal_weight')
90
sage: k.modulus()
91
x^211 + x^11 + x^10 + x^8 + 1
92
sage: k.<a> = GF(2^211, modulus='conway')
93
sage: k.modulus()
94
x^211 + x^9 + x^6 + x^5 + x^3 + x + 1
95
sage: k.<a> = GF(2^23, modulus='conway')
96
sage: a.multiplicative_order() == k.order() - 1
97
True
98
"""
99
100
def __init__(self, q, names="a", modulus=None, repr="poly"):
101
"""
102
Initialize ``self``.
103
104
TESTS::
105
106
sage: k.<a> = GF(2^100, modulus='strangeinput')
107
Traceback (most recent call last):
108
...
109
ValueError: no such algorithm for finding an irreducible polynomial: strangeinput
110
sage: k.<a> = GF(2^20) ; type(k)
111
<class 'sage.rings.finite_rings.finite_field_ntl_gf2e.FiniteField_ntl_gf2e_with_category'>
112
sage: loads(dumps(k)) is k
113
True
114
sage: k1.<a> = GF(2^16)
115
sage: k2.<a> = GF(2^17)
116
sage: k1 == k2
117
False
118
sage: k3 = k1._finite_field_ext_pari_()
119
sage: k1 == k3
120
False
121
122
sage: TestSuite(k).run()
123
124
sage: k.<a> = GF(2^64)
125
sage: k._repr_option('element_is_atomic')
126
False
127
sage: P.<x> = PolynomialRing(k)
128
sage: (a+1)*x # indirect doctest
129
(a + 1)*x
130
"""
131
late_import()
132
q = Integer(q)
133
if q < 2:
134
raise ValueError("q must be a 2-power")
135
k = q.exact_log(2)
136
if q != 1 << k:
137
raise ValueError("q must be a 2-power")
138
p = Integer(2)
139
FiniteField.__init__(self, GF(p), names, normalize=True)
140
141
self._kwargs = {'repr':repr}
142
143
if modulus is None or modulus == 'default':
144
if exists_conway_polynomial(p, k):
145
modulus = "conway"
146
else:
147
modulus = "minimal_weight"
148
if modulus == "conway":
149
modulus = conway_polynomial(p, k)
150
if is_Polynomial(modulus):
151
modulus = modulus.list()
152
self._cache = Cache_ntl_gf2e(self, k, modulus)
153
self._polynomial = {}
154
155
def characteristic(self):
156
"""
157
Return the characteristic of ``self`` which is 2.
158
159
EXAMPLES::
160
161
sage: k.<a> = GF(2^16,modulus='random')
162
sage: k.characteristic()
163
2
164
"""
165
return Integer(2)
166
167
def order(self):
168
"""
169
Return the cardinality of this field.
170
171
EXAMPLES::
172
173
sage: k.<a> = GF(2^64)
174
sage: k.order()
175
18446744073709551616
176
"""
177
return self._cache.order()
178
179
def degree(self):
180
r"""
181
If this field has cardinality `2^n` this method returns `n`.
182
183
EXAMPLES::
184
185
sage: k.<a> = GF(2^64)
186
sage: k.degree()
187
64
188
"""
189
return self._cache.degree()
190
191
def _element_constructor_(self, e):
192
"""
193
Coerces several data types to ``self``.
194
195
INPUT:
196
197
- ``e`` -- data to coerce
198
199
EXAMPLES::
200
201
sage: k.<a> = GF(2^20)
202
sage: k(1) # indirect doctest
203
1
204
sage: k(int(2))
205
0
206
207
sage: k('a+1')
208
a + 1
209
sage: k('b+1')
210
Traceback (most recent call last):
211
...
212
NameError: name 'b' is not defined
213
214
sage: R.<x>=GF(2)[]
215
sage: k(1+x+x^10+x^55)
216
a^19 + a^17 + a^16 + a^15 + a^12 + a^11 + a^8 + a^6 + a^4 + a^2 + 1
217
218
sage: V = k.vector_space()
219
sage: v = V.random_element(); v
220
(1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1)
221
sage: k(v)
222
a^19 + a^15 + a^14 + a^13 + a^11 + a^10 + a^9 + a^6 + a^5 + a^4 + 1
223
sage: vector(k(v)) == v
224
True
225
226
sage: k(pari('Mod(1,2)*a^20'))
227
a^10 + a^9 + a^7 + a^6 + a^5 + a^4 + a + 1
228
"""
229
return self._cache.import_data(e)
230
231
def gen(self, ignored=None):
232
r"""
233
Return a generator of ``self``.
234
235
EXAMPLES::
236
237
sage: k.<a> = GF(2^19)
238
sage: k.gen() == a
239
True
240
sage: a
241
a
242
"""
243
return self._cache._gen
244
245
def prime_subfield(self):
246
r"""
247
Return the prime subfield `\GF{p}` of ``self`` if ``self`` is
248
`\GF{p^n}`.
249
250
EXAMPLES::
251
252
sage: F.<a> = GF(2^16)
253
sage: F.prime_subfield()
254
Finite Field of size 2
255
"""
256
return GF2
257
258
def fetch_int(self, number):
259
r"""
260
Given an integer `n` less than :meth:`cardinality` with base `2`
261
representation `a_0 + 2 \cdot a_1 + \cdots + 2^k a_k`, returns
262
`a_0 + a_1 \cdot x + \cdots + a_k x^k`, where `x` is the
263
generator of this finite field.
264
265
INPUT:
266
267
- ``number`` -- an integer
268
269
EXAMPLES::
270
271
sage: k.<a> = GF(2^48)
272
sage: k.fetch_int(2^43 + 2^15 + 1)
273
a^43 + a^15 + 1
274
sage: k.fetch_int(33793)
275
a^15 + a^10 + 1
276
sage: 33793.digits(2) # little endian
277
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]
278
"""
279
return self._cache.fetch_int(number)
280
281
def polynomial(self, name=None):
282
"""
283
Return the defining polynomial of this field as an element of
284
:class:`PolynomialRing`.
285
286
This is the same as the characteristic polynomial of the
287
generator of ``self``.
288
289
INPUT:
290
291
``name`` -- optional variable name
292
293
EXAMPLES::
294
295
sage: k.<a> = GF(2^20)
296
sage: k.polynomial()
297
a^20 + a^10 + a^9 + a^7 + a^6 + a^5 + a^4 + a + 1
298
sage: k.polynomial('FOO')
299
FOO^20 + FOO^10 + FOO^9 + FOO^7 + FOO^6 + FOO^5 + FOO^4 + FOO + 1
300
sage: a^20
301
a^10 + a^9 + a^7 + a^6 + a^5 + a^4 + a + 1
302
303
"""
304
try:
305
return self._polynomial[name]
306
except KeyError:
307
R = self.polynomial_ring(name)
308
f = R(self._cache.polynomial())
309
self._polynomial[name] = f
310
return f
311
312
def _finite_field_ext_pari_(self):
313
"""
314
Return a :class:`FiniteField_ext_pari` isomorphic to ``self`` with
315
the same defining polynomial.
316
317
.. NOTE::
318
319
This method will vanish eventually because that implementation of
320
finite fields will be deprecated.
321
322
EXAMPLES::
323
324
sage: k.<a> = GF(2^20)
325
sage: kP = k._finite_field_ext_pari_()
326
sage: kP
327
Finite Field in a of size 2^20
328
sage: type(kP)
329
<class 'sage.rings.finite_rings.finite_field_ext_pari.FiniteField_ext_pari_with_category'>
330
"""
331
f = self.polynomial()
332
return FiniteField_ext_pari(self.order(), self.variable_name(), f)
333
334
def __hash__(self):
335
"""
336
Return the hash value of ``self``.
337
338
EXAMPLES::
339
340
sage: k1.<a> = GF(2^16)
341
sage: {k1:1} # indirect doctest
342
{Finite Field in a of size 2^16: 1}
343
"""
344
try:
345
return self._hash
346
except AttributeError:
347
self._hash = hash((self.characteristic(),self.polynomial(),self.variable_name(),"ntl_gf2e"))
348
return self._hash
349
350
def _pari_modulus(self):
351
"""
352
Return PARI object which is equivalent to the
353
polynomial/modulus of ``self``.
354
355
EXAMPLES::
356
357
sage: k1.<a> = GF(2^16)
358
sage: k1._pari_modulus()
359
Mod(1, 2)*a^16 + Mod(1, 2)*a^5 + Mod(1, 2)*a^3 + Mod(1, 2)*a^2 + Mod(1, 2)
360
"""
361
f = pari(str(self.modulus()))
362
return f.subst('x', 'a') * pari("Mod(1,%s)"%self.characteristic())
363
364