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