Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/sage/rings/finite_rings/element_ntl_gf2e.pyx
8820 views
1
r"""
2
Finite Fields of characteristic 2 and order strictly greater than 2.
3
4
This implementation uses NTL's GF2E class to perform the arithmetic
5
and is the standard implementation for ``GF(2^n)`` for ``n >= 16``.
6
7
AUTHORS:
8
9
- Martin Albrecht <[email protected]> (2007-10)
10
"""
11
12
#*****************************************************************************
13
#
14
# Sage: System for Algebra and Geometry Experimentation
15
#
16
# Copyright (C) 2007 Martin Albrecht <[email protected]>
17
#
18
# Distributed under the terms of the GNU General Public License (GPL)
19
#
20
# This code is distributed in the hope that it will be useful,
21
# but WITHOUT ANY WARRANTY; without even the implied warranty of
22
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23
# General Public License for more details.
24
#
25
# The full text of the GPL is available at:
26
#
27
# http://www.gnu.org/licenses/
28
#*****************************************************************************
29
include "sage/libs/ntl/decl.pxi"
30
include "sage/ext/interrupt.pxi"
31
include "sage/ext/stdsage.pxi"
32
include "sage/ext/cdefs.pxi"
33
34
from sage.structure.sage_object cimport SageObject
35
from sage.structure.element cimport Element, ModuleElement, RingElement
36
37
from sage.structure.parent cimport Parent
38
from sage.structure.parent_base cimport ParentWithBase
39
from sage.structure.parent_gens cimport ParentWithGens
40
41
from sage.rings.ring cimport Ring
42
43
from sage.rings.finite_rings.finite_field_base cimport FiniteField
44
45
from sage.libs.pari.all import pari
46
from sage.libs.pari.gen import gen
47
48
from sage.interfaces.gap import is_GapElement
49
50
from sage.misc.randstate import current_randstate
51
52
from finite_field_ext_pari import FiniteField_ext_pari
53
from element_ext_pari import FiniteField_ext_pariElement
54
from finite_field_ntl_gf2e import FiniteField_ntl_gf2e
55
56
from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
57
58
cdef object is_IntegerMod
59
cdef object IntegerModRing_generic
60
cdef object Integer
61
cdef object Rational
62
cdef object is_Polynomial
63
cdef object ConwayPolynomials
64
cdef object conway_polynomial
65
cdef object MPolynomial
66
cdef object Polynomial
67
cdef object FreeModuleElement
68
cdef object GF
69
cdef object GF2, GF2_0, GF2_1
70
71
cdef int late_import() except -1:
72
"""
73
Import a bunch of objects to the module name space late,
74
i.e. after the module was loaded. This is needed to avoid circular
75
imports.
76
"""
77
global is_IntegerMod, \
78
IntegerModRing_generic, \
79
Integer, \
80
Rational, \
81
is_Polynomial, \
82
ConwayPolynomials, \
83
conway_polynomial, \
84
MPolynomial, \
85
Polynomial, \
86
FreeModuleElement, \
87
GF, \
88
GF2, GF2_0, GF2_1
89
90
if is_IntegerMod is not None:
91
return 0
92
93
import sage.rings.finite_rings.integer_mod
94
is_IntegerMod = sage.rings.finite_rings.integer_mod.is_IntegerMod
95
96
import sage.rings.finite_rings.integer_mod_ring
97
IntegerModRing_generic = sage.rings.finite_rings.integer_mod_ring.IntegerModRing_generic
98
99
import sage.rings.integer
100
Integer = sage.rings.integer.Integer
101
102
import sage.rings.rational
103
Rational = sage.rings.rational.Rational
104
105
import sage.rings.polynomial.polynomial_element
106
is_Polynomial = sage.rings.polynomial.polynomial_element.is_Polynomial
107
108
import sage.databases.conway
109
ConwayPolynomials = sage.databases.conway.ConwayPolynomials
110
111
import sage.rings.finite_rings.conway_polynomials
112
conway_polynomial = sage.rings.finite_rings.conway_polynomials.conway_polynomial
113
114
import sage.rings.polynomial.multi_polynomial_element
115
MPolynomial = sage.rings.polynomial.multi_polynomial_element.MPolynomial
116
117
import sage.rings.polynomial.polynomial_element
118
Polynomial = sage.rings.polynomial.polynomial_element.Polynomial
119
120
import sage.modules.free_module_element
121
FreeModuleElement = sage.modules.free_module_element.FreeModuleElement
122
123
import sage.rings.finite_rings.constructor
124
GF = sage.rings.finite_rings.constructor.FiniteField
125
GF2 = GF(2)
126
GF2_0 = GF2(0)
127
GF2_1 = GF2(1)
128
129
cdef extern from "arpa/inet.h":
130
unsigned int htonl(unsigned int)
131
132
cdef little_endian():
133
return htonl(1) != 1
134
135
cdef unsigned int switch_endianess(unsigned int i):
136
cdef int j
137
cdef unsigned int ret = 0
138
for j from 0 <= j < sizeof(int):
139
(<unsigned char*>&ret)[j] = (<unsigned char*>&i)[sizeof(int)-j-1]
140
return ret
141
142
cdef class Cache_ntl_gf2e(SageObject):
143
"""
144
This class stores information for an NTL finite field in a Cython
145
class so that elements can access it quickly.
146
147
It's modeled on
148
:class:`~sage.rings.finite_rings.integer_mod.NativeIntStruct`,
149
but includes many functions that were previously included in
150
the parent (see :trac:`12062`).
151
"""
152
def __init__(self, parent, k, modulus):
153
"""
154
Initialization.
155
156
TESTS::
157
158
sage: k.<a> = GF(2^8)
159
"""
160
cdef GF2X_c ntl_m, ntl_tmp
161
cdef GF2_c c
162
cdef Py_ssize_t i
163
164
late_import()
165
if isinstance(modulus,str):
166
if modulus == "minimal_weight":
167
GF2X_BuildSparseIrred(ntl_m, k)
168
elif modulus == "first_lexicographic":
169
GF2X_BuildIrred(ntl_m, k)
170
elif modulus == "random":
171
current_randstate().set_seed_ntl(False)
172
GF2X_BuildSparseIrred(ntl_tmp, k)
173
GF2X_BuildRandomIrred(ntl_m, ntl_tmp)
174
else:
175
raise ValueError("Modulus parameter not understood")
176
elif PY_TYPE_CHECK(modulus, list) or PY_TYPE_CHECK(modulus, tuple):
177
for i from 0 <= i < len(modulus):
178
GF2_conv_long(c, int(modulus[i]))
179
GF2X_SetCoeff(ntl_m, i, c)
180
else:
181
raise ValueError("Modulus parameter not understood")
182
GF2EContext_construct_GF2X(&self.F, &ntl_m)
183
184
self._parent = <FiniteField?>parent
185
self._zero_element = self._new()
186
GF2E_conv_long((<FiniteField_ntl_gf2eElement>self._zero_element).x,0)
187
self._one_element = self._new()
188
GF2E_conv_long((<FiniteField_ntl_gf2eElement>self._one_element).x,1)
189
self._gen = self._new()
190
GF2E_from_str(&self._gen.x, "[0 1]")
191
192
def __dealloc__(self):
193
GF2EContext_destruct(&self.F)
194
195
def _doctest_for_5340(self):
196
r"""
197
Every bug fix should have a doctest. But :trac:`5340` only happens
198
when a garbage collection happens between restoring the modulus and
199
using it, so it can't be reliably doctested using any of the
200
existing Cython functions in this module. The sole purpose of
201
this method is to doctest the fix for :trac:`5340`.
202
203
EXAMPLES::
204
205
sage: k.<a> = GF(2^20)
206
sage: k._cache._doctest_for_5340()
207
[1 1 0 0 1 1 1 1 0 1 1 0 0 0 0 0 0 0 0 0 1]
208
[1 1 0 0 1 1 1 1 0 1 1 0 0 0 0 0 0 0 0 0 1]
209
"""
210
import gc
211
212
# Do a garbage collection, so that this method is repeatable.
213
gc.collect()
214
215
# Create a new finite field.
216
new_fld = GF(1<<30, 'a', modulus='random')
217
# Create a garbage cycle.
218
cycle = [new_fld]
219
cycle.append(cycle)
220
# Make the cycle inaccessible.
221
new_fld = None
222
cycle = None
223
224
# Set the modulus.
225
self.F.restore()
226
# Print the current modulus.
227
cdef GF2XModulus_c modulus = GF2E_modulus()
228
cdef GF2X_c mod_poly = GF2XModulus_GF2X(modulus)
229
print GF2X_to_PyString(&mod_poly)
230
231
# do another garbage collection
232
gc.collect()
233
234
# and print the modulus again
235
modulus = GF2E_modulus()
236
mod_poly = GF2XModulus_GF2X(modulus)
237
print GF2X_to_PyString(&mod_poly)
238
239
cdef FiniteField_ntl_gf2eElement _new(self):
240
"""
241
Return a new element in ``self``. Use this method to construct
242
'empty' elements.
243
"""
244
cdef FiniteField_ntl_gf2eElement y
245
self.F.restore()
246
y = PY_NEW(FiniteField_ntl_gf2eElement)
247
y._parent = self._parent
248
y._cache = self
249
return y
250
251
def order(self):
252
"""
253
Return the cardinality of the field.
254
255
EXAMPLES::
256
257
sage: k.<a> = GF(2^64)
258
sage: k._cache.order()
259
18446744073709551616
260
"""
261
self.F.restore()
262
return Integer(1) << GF2E_degree()
263
264
def degree(self):
265
r"""
266
If the field has cardinality `2^n` this method returns `n`.
267
268
EXAMPLES::
269
270
sage: k.<a> = GF(2^64)
271
sage: k._cache.degree()
272
64
273
"""
274
self.F.restore()
275
return Integer(GF2E_degree())
276
277
def import_data(self, e):
278
"""
279
EXAMPLES::
280
281
sage: k.<a> = GF(2^17)
282
sage: V = k.vector_space()
283
sage: v = [1,0,0,0,0,1,0,0,1,0,0,0,0,1,0,0,0]
284
sage: k._cache.import_data(v)
285
a^13 + a^8 + a^5 + 1
286
sage: k._cache.import_data(V(v))
287
a^13 + a^8 + a^5 + 1
288
289
TESTS:
290
291
We check that :trac:`12584` is fixed::
292
293
sage: k(2^63)
294
0
295
"""
296
if PY_TYPE_CHECK(e, FiniteField_ntl_gf2eElement) and e.parent() is self._parent: return e
297
cdef FiniteField_ntl_gf2eElement res = self._new()
298
cdef FiniteField_ntl_gf2eElement x
299
cdef FiniteField_ntl_gf2eElement g
300
cdef Py_ssize_t i
301
302
if is_IntegerMod(e):
303
e = e.lift()
304
if PY_TYPE_CHECK(e, int) or \
305
PY_TYPE_CHECK(e, Integer) or \
306
PY_TYPE_CHECK(e, long):
307
GF2E_conv_long(res.x,int(e&1))
308
return res
309
310
elif PY_TYPE_CHECK(e, float):
311
GF2E_conv_long(res.x,int(e))
312
return res
313
314
elif PY_TYPE_CHECK(e, str):
315
return self._parent(eval(e.replace("^","**"),self._parent.gens_dict()))
316
317
elif PY_TYPE_CHECK(e, FreeModuleElement):
318
if self._parent.vector_space() != e.parent():
319
raise TypeError, "e.parent must match self.vector_space"
320
ztmp = Integer(e.list(),2)
321
# Can't do the following since we can't cimport Integer because of circular imports.
322
#for i from 0 <= i < len(e):
323
# if e[i]:
324
# mpz_setbit(ztmp.value, i)
325
return self.fetch_int(ztmp)
326
327
elif isinstance(e, (list, tuple)):
328
if len(e) > self.degree():
329
# could reduce here...
330
raise ValueError, "list is too long"
331
ztmp = Integer(e,2)
332
return self.fetch_int(ztmp)
333
334
elif PY_TYPE_CHECK(e, MPolynomial):
335
if e.is_constant():
336
return self._parent(e.constant_coefficient())
337
else:
338
raise TypeError, "no coercion defined"
339
340
elif PY_TYPE_CHECK(e, Polynomial):
341
if e.is_constant():
342
return self._parent(e.constant_coefficient())
343
else:
344
return e(self._parent.gen())
345
346
elif PY_TYPE_CHECK(e, Rational):
347
num = e.numer()
348
den = e.denom()
349
if den % 2:
350
if num % 2:
351
return self._one_element
352
return self._zero_element
353
raise ZeroDivisionError
354
355
elif PY_TYPE_CHECK(e, gen):
356
pass # handle this in next if clause
357
358
elif PY_TYPE_CHECK(e,FiniteField_ext_pariElement):
359
# reduce FiniteField_ext_pariElements to pari
360
e = e._pari_()
361
362
elif is_GapElement(e):
363
from sage.interfaces.gap import gfq_gap_to_sage
364
return gfq_gap_to_sage(e, self._parent)
365
else:
366
raise TypeError, "unable to coerce"
367
368
if PY_TYPE_CHECK(e, gen):
369
e = e.lift().lift()
370
try:
371
GF2E_conv_long(res.x, int(e[0]))
372
except TypeError:
373
GF2E_conv_long(res.x, int(e))
374
375
g = self._gen
376
x = self._new()
377
GF2E_conv_long(x.x,1)
378
379
for i from 0 < i <= e.poldegree():
380
GF2E_mul(x.x, x.x, g.x)
381
if e[i]:
382
GF2E_add(res.x, res.x, x.x )
383
return res
384
385
raise ValueError, "Cannot coerce element %s to this field."%(e)
386
387
cpdef FiniteField_ntl_gf2eElement fetch_int(self, number):
388
"""
389
Given an integer less than `p^n` with base `2`
390
representation `a_0 + a_1 \cdot 2 + \cdots + a_k 2^k`, this returns
391
`a_0 + a_1 x + \cdots + a_k x^k`, where `x` is the
392
generator of this finite field.
393
394
INPUT:
395
396
- ``number`` -- an integer, of size less than the cardinality
397
398
EXAMPLES::
399
400
sage: k.<a> = GF(2^48)
401
sage: k._cache.fetch_int(2^33 + 2 + 1)
402
a^33 + a + 1
403
"""
404
cdef FiniteField_ntl_gf2eElement a = self._new()
405
cdef GF2X_c _a
406
407
self.F.restore()
408
409
cdef unsigned char *p
410
cdef int i
411
412
if number < 0 or number >= self.order():
413
raise TypeError, "n must be between 0 and self.order()"
414
415
if PY_TYPE_CHECK(number, int) or PY_TYPE_CHECK(number, long):
416
from sage.misc.functional import log
417
n = int(log(number,2))/8 + 1
418
elif PY_TYPE_CHECK(number, Integer):
419
n = int(number.nbits())/8 + 1
420
else:
421
raise TypeError, "number %s is not an integer"%number
422
423
p = <unsigned char*>sage_malloc(n)
424
for i from 0 <= i < n:
425
p[i] = (number%256)
426
number = number >> 8
427
GF2XFromBytes(_a, p, n)
428
GF2E_conv_GF2X(a.x, _a)
429
sage_free(p)
430
return a
431
432
def polynomial(self):
433
"""
434
Returns the list of 0's and 1's giving the defining polynomial of the
435
field.
436
437
EXAMPLES::
438
439
sage: k.<a> = GF(2^20,modulus="minimal_weight")
440
sage: k._cache.polynomial()
441
[1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]
442
"""
443
cdef FiniteField_ntl_gf2eElement P
444
cdef GF2X_c _P
445
cdef GF2_c c
446
self.F.restore()
447
cdef int i
448
449
P = -(self._gen**(self.degree()))
450
_P = GF2E_rep(P.x)
451
452
ret = []
453
for i from 0 <= i < GF2E_degree():
454
c = GF2X_coeff(_P,i)
455
if not GF2_IsZero(c):
456
ret.append(1)
457
else:
458
ret.append(0)
459
ret.append(1)
460
return ret
461
462
cdef class FiniteField_ntl_gf2eElement(FinitePolyExtElement):
463
"""
464
An element of an NTL:GF2E finite field.
465
"""
466
467
def __init__(FiniteField_ntl_gf2eElement self, parent=None ):
468
"""
469
Initializes an element in parent. It's much better to use
470
parent(<value>) or any specialized method of parent
471
(one,zero,gen) instead. Do not call this constructor directly,
472
it doesn't make much sense.
473
474
INPUT:
475
476
- ``parent`` -- base field
477
478
OUTPUT:
479
480
A finite field element.
481
482
EXAMPLES::
483
484
sage: k.<a> = GF(2^16)
485
sage: from sage.rings.finite_rings.element_ntl_gf2e import FiniteField_ntl_gf2eElement
486
sage: FiniteField_ntl_gf2eElement(k)
487
0
488
sage: k.<a> = GF(2^20)
489
sage: a.parent() is k
490
True
491
"""
492
if parent is None:
493
raise ValueError, "You must provide a parent to construct a finite field element"
494
495
def __cinit__(FiniteField_ntl_gf2eElement self, parent=None ):
496
"""
497
Restores the cache and constructs the underlying NTL element.
498
499
EXAMPLES::
500
501
sage: k.<a> = GF(2^8) # indirect doctest
502
"""
503
if parent is None:
504
return
505
if PY_TYPE_CHECK(parent, FiniteField_ntl_gf2e):
506
self._parent = parent
507
(<Cache_ntl_gf2e>self._parent._cache).F.restore()
508
GF2E_construct(&self.x)
509
510
def __dealloc__(FiniteField_ntl_gf2eElement self):
511
GF2E_destruct(&self.x)
512
513
cdef FiniteField_ntl_gf2eElement _new(FiniteField_ntl_gf2eElement self):
514
cdef FiniteField_ntl_gf2eElement y
515
(<Cache_ntl_gf2e>self._parent._cache).F.restore()
516
y = PY_NEW(FiniteField_ntl_gf2eElement)
517
y._parent = self._parent
518
y._cache = self._cache
519
return y
520
521
def __repr__(FiniteField_ntl_gf2eElement self):
522
"""
523
Polynomial representation of ``self``.
524
525
EXAMPLES::
526
527
sage: k.<a> = GF(2^16)
528
sage: str(a^16) # indirect doctest
529
'a^5 + a^3 + a^2 + 1'
530
sage: k.<u> = GF(2^16)
531
sage: u
532
u
533
"""
534
(<Cache_ntl_gf2e>self._parent._cache).F.restore()
535
cdef GF2X_c rep = GF2E_rep(self.x)
536
cdef GF2_c c
537
cdef int i
538
539
if GF2E_IsZero(self.x):
540
return "0"
541
542
name = self._parent.variable_name()
543
_repr = []
544
545
c = GF2X_coeff(rep, 0)
546
if not GF2_IsZero(c):
547
_repr.append("1")
548
549
c = GF2X_coeff(rep, 1)
550
if not GF2_IsZero(c):
551
_repr.append(name)
552
553
for i from 1 < i <= GF2X_deg(rep):
554
c = GF2X_coeff(rep, i)
555
if not GF2_IsZero(c):
556
_repr.append("%s^%d"%(name,i))
557
558
return " + ".join(reversed(_repr))
559
560
def __nonzero__(FiniteField_ntl_gf2eElement self):
561
r"""
562
Return ``True`` if ``self != k(0)``.
563
564
EXAMPLES::
565
566
sage: k.<a> = GF(2^20)
567
sage: bool(a) # indirect doctest
568
True
569
sage: bool(k(0))
570
False
571
sage: a.is_zero()
572
False
573
"""
574
(<Cache_ntl_gf2e>self._parent._cache).F.restore()
575
return not bool(GF2E_IsZero(self.x))
576
577
def is_one(FiniteField_ntl_gf2eElement self):
578
r"""
579
Return ``True`` if ``self == k(1)``.
580
581
Equivalent to ``self != k(0)``.
582
583
EXAMPLES::
584
585
sage: k.<a> = GF(2^20)
586
sage: a.is_one() # indirect doctest
587
False
588
sage: k(1).is_one()
589
True
590
591
"""
592
(<Cache_ntl_gf2e>self._parent._cache).F.restore()
593
return bool(GF2E_equal(self.x,self._cache._one_element.x))
594
595
def is_unit(FiniteField_ntl_gf2eElement self):
596
"""
597
Return ``True`` if ``self`` is nonzero, so it is a unit as an element
598
of the finite field.
599
600
EXAMPLES::
601
602
sage: k.<a> = GF(2^17)
603
sage: a.is_unit()
604
True
605
sage: k(0).is_unit()
606
False
607
"""
608
(<Cache_ntl_gf2e>self._parent._cache).F.restore()
609
if not GF2E_IsZero(self.x):
610
return True
611
else:
612
return False
613
614
def is_square(FiniteField_ntl_gf2eElement self):
615
r"""
616
Return ``True`` as every element in `\GF{2^n}` is a square.
617
618
EXAMPLES::
619
620
sage: k.<a> = GF(2^18)
621
sage: e = k.random_element()
622
sage: e
623
a^15 + a^14 + a^13 + a^11 + a^10 + a^9 + a^6 + a^5 + a^4 + 1
624
sage: e.is_square()
625
True
626
sage: e.sqrt()
627
a^16 + a^15 + a^14 + a^11 + a^9 + a^8 + a^7 + a^6 + a^4 + a^3 + 1
628
sage: e.sqrt()^2 == e
629
True
630
"""
631
return True
632
633
def sqrt(FiniteField_ntl_gf2eElement self, all=False, extend=False):
634
"""
635
Return a square root of this finite field element in its parent.
636
637
EXAMPLES::
638
639
sage: k.<a> = GF(2^20)
640
sage: a.is_square()
641
True
642
sage: a.sqrt()
643
a^19 + a^15 + a^14 + a^12 + a^9 + a^7 + a^4 + a^3 + a + 1
644
sage: a.sqrt()^2 == a
645
True
646
647
This failed before :trac:`4899`::
648
649
sage: GF(2^16,'a')(1).sqrt()
650
1
651
652
"""
653
# this really should be handled special, its gf2 linear after
654
# all
655
a = self ** (self._cache.order() // 2)
656
if all:
657
return [a]
658
else:
659
return a
660
661
cpdef ModuleElement _add_(self, ModuleElement right):
662
"""
663
Add two elements.
664
665
EXAMPLES::
666
667
sage: k.<a> = GF(2^16)
668
sage: e = a^2 + a + 1 # indirect doctest
669
sage: f = a^15 + a^2 + 1
670
sage: e + f
671
a^15 + a
672
"""
673
cdef FiniteField_ntl_gf2eElement r = (<FiniteField_ntl_gf2eElement>self)._new()
674
GF2E_add(r.x, (<FiniteField_ntl_gf2eElement>self).x, (<FiniteField_ntl_gf2eElement>right).x)
675
return r
676
677
cpdef ModuleElement _iadd_(self, ModuleElement right):
678
"""
679
Add two elements.
680
681
EXAMPLES::
682
683
sage: k.<a> = GF(2^16)
684
sage: e = a^2 + a + 1 # indirect doctest
685
sage: f = a^15 + a^2 + 1
686
sage: e + f
687
a^15 + a
688
"""
689
GF2E_add((<FiniteField_ntl_gf2eElement>self).x, (<FiniteField_ntl_gf2eElement>self).x, (<FiniteField_ntl_gf2eElement>right).x)
690
return self
691
692
cpdef RingElement _mul_(self, RingElement right):
693
"""
694
Multiply two elements.
695
696
EXAMPLES::
697
698
sage: k.<a> = GF(2^16)
699
sage: e = a^2 + a + 1 # indirect doctest
700
sage: f = a^15 + a^2 + 1
701
sage: e * f
702
a^15 + a^6 + a^5 + a^3 + a^2
703
"""
704
cdef FiniteField_ntl_gf2eElement r = (<FiniteField_ntl_gf2eElement>self)._new()
705
GF2E_mul(r.x, (<FiniteField_ntl_gf2eElement>self).x, (<FiniteField_ntl_gf2eElement>right).x)
706
return r
707
708
cpdef RingElement _imul_(self, RingElement right):
709
"""
710
Multiply two elements.
711
712
EXAMPLES::
713
714
sage: k.<a> = GF(2^16)
715
sage: e = a^2 * a + 1 # indirect doctest
716
sage: f = a^15 * a^2 + 1
717
sage: e * f
718
a^9 + a^7 + a + 1
719
"""
720
GF2E_mul((<FiniteField_ntl_gf2eElement>self).x, (<FiniteField_ntl_gf2eElement>self).x, (<FiniteField_ntl_gf2eElement>right).x)
721
return self
722
723
cpdef RingElement _div_(self, RingElement right):
724
"""
725
Divide two elements.
726
727
EXAMPLES::
728
729
sage: k.<a> = GF(2^16)
730
sage: e = a^2 + a + 1 # indirect doctest
731
sage: f = a^15 + a^2 + 1
732
sage: e / f
733
a^11 + a^8 + a^7 + a^6 + a^5 + a^3 + a^2 + 1
734
sage: k(1) / k(0)
735
Traceback (most recent call last):
736
...
737
ZeroDivisionError: division by zero in finite field.
738
"""
739
cdef FiniteField_ntl_gf2eElement r = (<FiniteField_ntl_gf2eElement>self)._new()
740
if GF2E_IsZero((<FiniteField_ntl_gf2eElement>right).x):
741
raise ZeroDivisionError, 'division by zero in finite field.'
742
GF2E_div(r.x, (<FiniteField_ntl_gf2eElement>self).x, (<FiniteField_ntl_gf2eElement>right).x)
743
return r
744
745
cpdef RingElement _idiv_(self, RingElement right):
746
"""
747
Divide two elements.
748
749
EXAMPLES::
750
751
sage: k.<a> = GF(2^16)
752
sage: e = a^2 / a + 1 # indirect doctest
753
sage: f = a^15 / a^2 + 1
754
sage: e / f
755
a^15 + a^12 + a^10 + a^9 + a^6 + a^5 + a^3
756
"""
757
GF2E_div((<FiniteField_ntl_gf2eElement>self).x, (<FiniteField_ntl_gf2eElement>self).x, (<FiniteField_ntl_gf2eElement>right).x)
758
return self
759
760
cpdef ModuleElement _sub_(self, ModuleElement right):
761
"""
762
Subtract two elements.
763
764
EXAMPLES::
765
766
sage: k.<a> = GF(2^16)
767
sage: e = a^2 - a + 1 # indirect doctest
768
sage: f = a^15 - a^2 + 1
769
sage: e - f
770
a^15 + a
771
"""
772
cdef FiniteField_ntl_gf2eElement r = (<FiniteField_ntl_gf2eElement>self)._new()
773
GF2E_sub(r.x, (<FiniteField_ntl_gf2eElement>self).x, (<FiniteField_ntl_gf2eElement>right).x)
774
return r
775
776
cpdef ModuleElement _isub_(self, ModuleElement right):
777
"""
778
Subtract two elements.
779
780
EXAMPLES::
781
782
sage: k.<a> = GF(2^16)
783
sage: e = a^2 - a + 1 # indirect doctest
784
sage: f = a^15 - a^2 + 1
785
sage: e - f
786
a^15 + a
787
"""
788
GF2E_sub((<FiniteField_ntl_gf2eElement>self).x, (<FiniteField_ntl_gf2eElement>self).x, (<FiniteField_ntl_gf2eElement>right).x)
789
return self
790
791
def __neg__(FiniteField_ntl_gf2eElement self):
792
"""
793
Return this element.
794
795
EXAMPLES::
796
797
sage: k.<a> = GF(2^16)
798
sage: -a
799
a
800
"""
801
cdef FiniteField_ntl_gf2eElement r = (<FiniteField_ntl_gf2eElement>self)._new()
802
r.x = (<FiniteField_ntl_gf2eElement>self).x
803
return r
804
805
def __invert__(FiniteField_ntl_gf2eElement self):
806
"""
807
Return the multiplicative inverse of an element.
808
809
EXAMPLES::
810
811
sage: k.<a> = GF(2^16)
812
sage: ~a
813
a^15 + a^4 + a^2 + a
814
sage: a * ~a
815
1
816
"""
817
cdef FiniteField_ntl_gf2eElement r = (<FiniteField_ntl_gf2eElement>self)._new()
818
cdef FiniteField_ntl_gf2eElement o = (<FiniteField_ntl_gf2eElement>self)._parent._cache._one_element
819
GF2E_div(r.x, o.x, (<FiniteField_ntl_gf2eElement>self).x)
820
return r
821
822
def __pow__(FiniteField_ntl_gf2eElement self, exp, other):
823
"""
824
EXAMPLES::
825
826
sage: k.<a> = GF(2^63)
827
sage: a^2
828
a^2
829
sage: a^64
830
a^25 + a^24 + a^23 + a^18 + a^17 + a^16 + a^12 + a^10 + a^9 + a^5 + a^4 + a^3 + a^2 + a
831
sage: a^(2^64)
832
a^2
833
sage: a^(2^128)
834
a^4
835
"""
836
cdef int exp_int
837
cdef FiniteField_ntl_gf2eElement r = (<FiniteField_ntl_gf2eElement>self)._new()
838
839
try:
840
exp_int = exp
841
if exp != exp_int:
842
raise OverflowError
843
GF2E_power(r.x, (<FiniteField_ntl_gf2eElement>self).x, exp_int)
844
return r
845
except OverflowError:
846
# we could try to factor out the order first
847
from sage.groups.generic import power
848
return power(self,exp)
849
850
def __richcmp__(left, right, int op):
851
"""
852
Comparison of finite field elements.
853
854
EXAMPLES::
855
856
sage: k.<a> = GF(2^20)
857
sage: e = k.random_element()
858
sage: f = loads(dumps(e))
859
sage: e is f
860
False
861
sage: e == f
862
True
863
sage: e != (e + 1)
864
True
865
866
.. NOTE::
867
868
Finite fields are unordered. However, we adopt the convention that
869
an element ``e`` is bigger than element ``f`` if its polynomial
870
representation is bigger.
871
872
EXAMPLES::
873
874
sage: K.<a> = GF(2^100)
875
sage: a < a^2
876
True
877
sage: a > a^2
878
False
879
sage: a+1 > a^2
880
False
881
sage: a+1 < a^2
882
True
883
sage: a+1 < a
884
False
885
sage: a+1 == a
886
False
887
sage: a == a
888
True
889
"""
890
return (<Element>left)._richcmp(right, op)
891
892
cdef int _cmp_c_impl(left, Element right) except -2:
893
"""
894
Comparison of finite field elements.
895
"""
896
(<Cache_ntl_gf2e>left._parent._cache).F.restore()
897
c = GF2E_equal((<FiniteField_ntl_gf2eElement>left).x, (<FiniteField_ntl_gf2eElement>right).x)
898
if c == 1:
899
return 0
900
else:
901
r = cmp(GF2X_deg(GF2E_rep((<FiniteField_ntl_gf2eElement>left).x)), GF2X_deg(GF2E_rep((<FiniteField_ntl_gf2eElement>right).x)))
902
if r:
903
return r
904
li = left.integer_representation()
905
ri = right.integer_representation()
906
return cmp(li,ri)
907
908
def _integer_(FiniteField_ntl_gf2eElement self, Integer):
909
"""
910
Convert ``self`` to an integer if it is in the prime subfield.
911
912
EXAMPLES::
913
914
sage: k.<b> = GF(2^16); k
915
Finite Field in b of size 2^16
916
sage: ZZ(k(1))
917
1
918
sage: ZZ(k(0))
919
0
920
sage: ZZ(b)
921
Traceback (most recent call last):
922
...
923
TypeError: not in prime subfield
924
sage: GF(2)(b^(2^16-1)) # indirect doctest
925
1
926
"""
927
if self.is_zero(): return Integer(0)
928
elif self.is_one(): return Integer(1)
929
else:
930
raise TypeError, "not in prime subfield"
931
932
def __int__(FiniteField_ntl_gf2eElement self):
933
"""
934
Return the int representation of ``self``. When ``self`` is in the
935
prime subfield, the integer returned is equal to ``self`` and
936
otherwise raises an error.
937
938
EXAMPLES::
939
940
sage: k.<a> = GF(2^20)
941
sage: int(k(0))
942
0
943
sage: int(k(1))
944
1
945
sage: int(a)
946
Traceback (most recent call last):
947
...
948
TypeError: Cannot coerce element to an integer.
949
sage: int(a^2 + 1)
950
Traceback (most recent call last):
951
...
952
TypeError: Cannot coerce element to an integer.
953
954
"""
955
if self == 0:
956
return int(0)
957
elif self == 1:
958
return int(1)
959
else:
960
raise TypeError("Cannot coerce element to an integer.")
961
962
def integer_representation(FiniteField_ntl_gf2eElement self):
963
r"""
964
Return the int representation of ``self``. When ``self`` is in the
965
prime subfield, the integer returned is equal to ``self`` and not
966
to ``log_repr``.
967
968
Elements of this field are represented as ints in as follows:
969
for `e \in \GF{p}[x]` with `e = a_0 + a_1 x + a_2 x^2 + \cdots`,
970
`e` is represented as: `n = a_0 + a_1 p + a_2 p^2 + \cdots`.
971
972
EXAMPLES::
973
974
sage: k.<a> = GF(2^20)
975
sage: a.integer_representation()
976
2
977
sage: (a^2 + 1).integer_representation()
978
5
979
sage: k.<a> = GF(2^70)
980
sage: (a^65 + a^64 + 1).integer_representation()
981
55340232221128654849L
982
"""
983
cdef unsigned int i = 0
984
ret = int(0)
985
cdef unsigned long shift = 0
986
cdef GF2X_c r = GF2E_rep(self.x)
987
988
if GF2X_IsZero(r):
989
return 0
990
991
if little_endian():
992
while GF2X_deg(r) >= sizeof(int)*8:
993
BytesFromGF2X(<unsigned char *>&i, r, sizeof(int))
994
ret += int(i) << shift
995
shift += sizeof(int)*8
996
GF2X_RightShift(r,r,(sizeof(int)*8))
997
BytesFromGF2X(<unsigned char *>&i, r, sizeof(int))
998
ret += int(i) << shift
999
else:
1000
while GF2X_deg(r) >= sizeof(int)*8:
1001
BytesFromGF2X(<unsigned char *>&i, r, sizeof(int))
1002
ret += int(switch_endianess(i)) << shift
1003
shift += sizeof(int)*8
1004
GF2X_RightShift(r,r,(sizeof(int)*8))
1005
BytesFromGF2X(<unsigned char *>&i, r, sizeof(int))
1006
ret += int(switch_endianess(i)) << shift
1007
1008
return int(ret)
1009
1010
def polynomial(FiniteField_ntl_gf2eElement self, name=None):
1011
r"""
1012
Return ``self`` viewed as a polynomial over
1013
``self.parent().prime_subfield()``.
1014
1015
INPUT:
1016
1017
- ``name`` -- (optional) variable name
1018
1019
EXAMPLES::
1020
1021
sage: k.<a> = GF(2^17)
1022
sage: e = a^15 + a^13 + a^11 + a^10 + a^9 + a^8 + a^7 + a^6 + a^4 + a + 1
1023
sage: e.polynomial()
1024
a^15 + a^13 + a^11 + a^10 + a^9 + a^8 + a^7 + a^6 + a^4 + a + 1
1025
1026
sage: from sage.rings.polynomial.polynomial_element import is_Polynomial
1027
sage: is_Polynomial(e.polynomial())
1028
True
1029
1030
sage: e.polynomial('x')
1031
x^15 + x^13 + x^11 + x^10 + x^9 + x^8 + x^7 + x^6 + x^4 + x + 1
1032
"""
1033
cdef GF2X_c r = GF2E_rep(self.x)
1034
cdef int i
1035
1036
C = []
1037
for i from 0 <= i <= GF2X_deg(r):
1038
C.append(GF2_conv_to_long(GF2X_coeff(r,i)))
1039
return self._parent.polynomial_ring(name)(C)
1040
1041
def charpoly(self, var='x'):
1042
r"""
1043
Return the characteristic polynomial of ``self`` as a polynomial
1044
in var over the prime subfield.
1045
1046
INPUT:
1047
1048
- ``var`` -- string (default: ``'x'``)
1049
1050
OUTPUT:
1051
1052
polynomial
1053
1054
EXAMPLES::
1055
1056
sage: k.<a> = GF(2^8)
1057
sage: b = a^3 + a
1058
sage: b.minpoly()
1059
x^4 + x^3 + x^2 + x + 1
1060
sage: b.charpoly()
1061
x^8 + x^6 + x^4 + x^2 + 1
1062
sage: b.charpoly().factor()
1063
(x^4 + x^3 + x^2 + x + 1)^2
1064
sage: b.charpoly('Z')
1065
Z^8 + Z^6 + Z^4 + Z^2 + 1
1066
"""
1067
f = self.minpoly(var)
1068
cdef int d = f.degree(), n = self.parent().degree()
1069
cdef int pow = n/d
1070
return f if pow == 1 else f**pow
1071
1072
1073
def minpoly(self, var='x'):
1074
r"""
1075
Return the minimal polynomial of ``self``, which is the smallest
1076
degree polynomial `f \in \GF{2}[x]` such that ``f(self) == 0``.
1077
1078
INPUT:
1079
1080
- ``var`` -- string (default: ``'x'``)
1081
1082
OUTPUT:
1083
1084
polynomial
1085
1086
EXAMPLES::
1087
1088
sage: K.<a> = GF(2^100)
1089
sage: f = a.minpoly(); f
1090
x^100 + x^57 + x^56 + x^55 + x^52 + x^48 + x^47 + x^46 + x^45 + x^44 + x^43 + x^41 + x^37 + x^36 + x^35 + x^34 + x^31 + x^30 + x^27 + x^25 + x^24 + x^22 + x^20 + x^19 + x^16 + x^15 + x^11 + x^9 + x^8 + x^6 + x^5 + x^3 + 1
1091
sage: f(a)
1092
0
1093
sage: g = K.random_element()
1094
sage: g.minpoly()(g)
1095
0
1096
"""
1097
(<Cache_ntl_gf2e>self._parent._cache).F.restore()
1098
cdef GF2X_c r = GF2X_IrredPolyMod(GF2E_rep(self.x), GF2E_modulus())
1099
cdef int i
1100
C = []
1101
for i from 0 <= i <= GF2X_deg(r):
1102
C.append(GF2_conv_to_long(GF2X_coeff(r,i)))
1103
return self._parent.polynomial_ring(var)(C)
1104
1105
def trace(self):
1106
"""
1107
Return the trace of ``self``.
1108
1109
EXAMPLES::
1110
1111
sage: K.<a> = GF(2^25)
1112
sage: a.trace()
1113
0
1114
sage: a.charpoly()
1115
x^25 + x^8 + x^6 + x^2 + 1
1116
sage: parent(a.trace())
1117
Finite Field of size 2
1118
1119
sage: b = a+1
1120
sage: b.trace()
1121
1
1122
sage: b.charpoly()[1]
1123
1
1124
"""
1125
if GF2_IsOne(GF2E_trace(self.x)):
1126
return GF2_1
1127
else:
1128
return GF2_0
1129
1130
def weight(self):
1131
"""
1132
Returns the number of non-zero coefficients in the polynomial
1133
representation of ``self``.
1134
1135
EXAMPLES::
1136
1137
sage: K.<a> = GF(2^21)
1138
sage: a.weight()
1139
1
1140
sage: (a^5+a^2+1).weight()
1141
3
1142
sage: b = 1/(a+1); b
1143
a^20 + a^19 + a^18 + a^17 + a^16 + a^15 + a^14 + a^13 + a^12 + a^11 + a^10 + a^9 + a^8 + a^7 + a^6 + a^4 + a^3 + a^2
1144
sage: b.weight()
1145
18
1146
"""
1147
return GF2X_weight(GF2E_rep(self.x))
1148
1149
def _finite_field_ext_pari_element(FiniteField_ntl_gf2eElement self, k=None):
1150
r"""
1151
Return an element of ``k`` supposed to match this
1152
element.
1153
1154
.. WANRING::
1155
1156
No checks if ``k`` equals ``self.parent()`` are performed.
1157
1158
INPUT:
1159
1160
- ``k`` -- (optional) :class:`FiniteField_ext_pari`
1161
1162
OUTPUT:
1163
1164
equivalent of ``self in k``
1165
1166
EXAMPLES::
1167
1168
sage: k.<a> = GF(2^17)
1169
sage: a._finite_field_ext_pari_element()
1170
a
1171
"""
1172
if k is None:
1173
k = self.parent()._finite_field_ext_pari_()
1174
elif not PY_TYPE_CHECK(k, FiniteField_ext_pari):
1175
raise TypeError, "k must be a pari finite field."
1176
cdef GF2X_c r = GF2E_rep(self.x)
1177
cdef int i
1178
1179
g = k.gen()
1180
o = k(1)
1181
ret = k(0)
1182
for i from 0 <= i <= GF2X_deg(r):
1183
ret += GF2_conv_to_long(GF2X_coeff(r,i))*o
1184
o *= g
1185
return ret
1186
1187
def _magma_init_(self, magma):
1188
r"""
1189
Return a string representation of ``self`` that MAGMA can
1190
understand.
1191
1192
EXAMPLES::
1193
1194
sage: k.<a> = GF(2^16)
1195
sage: a._magma_init_(magma) # random; optional - magma
1196
'_sage_[...]'
1197
1198
.. NOTE::
1199
1200
This method calls MAGMA to setup the parent.
1201
"""
1202
km = magma(self.parent())
1203
vn_m = km.gen(1).name()
1204
vn_s = str(self.parent().polynomial_ring().gen())
1205
return str(self.polynomial()).replace(vn_s,vn_m)
1206
1207
def __copy__(self):
1208
"""
1209
Return a copy of this element. Actually just returns ``self``, since
1210
finite field elements are immutable.
1211
1212
EXAMPLES::
1213
1214
sage: k.<a> = GF(2^16)
1215
sage: copy(a) is a
1216
True
1217
"""
1218
return self
1219
1220
def _pari_(self, var=None):
1221
r"""
1222
Return PARI representation of this element.
1223
1224
INPUT:
1225
1226
- ``var`` -- (default: ``None``) optional variable string
1227
1228
EXAMPLES::
1229
1230
sage: k.<a> = GF(2^17)
1231
sage: e = a^3 + a + 1
1232
sage: e._pari_()
1233
Mod(Mod(1, 2)*a^3 + Mod(1, 2)*a + Mod(1, 2), Mod(1, 2)*a^17 + Mod(1, 2)*a^3 + Mod(1, 2))
1234
1235
sage: e._pari_('w')
1236
Mod(Mod(1, 2)*w^3 + Mod(1, 2)*w + Mod(1, 2), Mod(1, 2)*w^17 + Mod(1, 2)*w^3 + Mod(1, 2))
1237
1238
sage: t = a^5 + a + 4
1239
sage: t_string = t._pari_init_('y')
1240
sage: t_string
1241
'Mod(Mod(1, 2)*y^5 + Mod(1, 2)*y, Mod(1, 2)*y^17 + Mod(1, 2)*y^3 + Mod(1, 2))'
1242
sage: type(t_string)
1243
<type 'str'>
1244
sage: t_element = t._pari_('b')
1245
sage: t_element
1246
Mod(Mod(1, 2)*b^5 + Mod(1, 2)*b, Mod(1, 2)*b^17 + Mod(1, 2)*b^3 + Mod(1, 2))
1247
sage: t_element.parent()
1248
Interface to the PARI C library
1249
"""
1250
return pari(self._pari_init_(var))
1251
1252
def _gap_init_(self):
1253
r"""
1254
Return a string that evaluates to the GAP representation of
1255
this element.
1256
1257
A ``NotImplementedError`` is raised if
1258
``self.parent().modulus()`` is not a Conway polynomial, as
1259
the isomorphism of finite fields is not implemented yet.
1260
1261
EXAMPLES::
1262
1263
sage: k.<b> = GF(2^16)
1264
sage: b._gap_init_()
1265
'Z(65536)^1'
1266
"""
1267
F = self._parent
1268
if not F.is_conway():
1269
raise NotImplementedError, "conversion of (NTL) finite field element to GAP not implemented except for fields defined by Conway polynomials."
1270
if F.order() > 65536:
1271
raise TypeError, "order (=%s) must be at most 65536."%F.order()
1272
if self == 0:
1273
return '0*Z(%s)'%F.order()
1274
assert F.degree() > 1
1275
g = F.multiplicative_generator()
1276
n = self.log(g)
1277
return 'Z(%s)^%s'%(F.order(), n)
1278
1279
def __hash__(FiniteField_ntl_gf2eElement self):
1280
"""
1281
Return the hash of this finite field element. We hash the parent
1282
and the underlying integer representation of this element.
1283
1284
EXAMPLES::
1285
1286
sage: k.<a> = GF(2^18)
1287
sage: {a:1,a:0} # indirect doctest
1288
{a: 0}
1289
"""
1290
return hash(self.integer_representation()) # todo, come up with a faster version
1291
1292
def _vector_(FiniteField_ntl_gf2eElement self, reverse=False):
1293
r"""
1294
Return a vector in ``self.parent().vector_space()``
1295
matching ``self``. The most significant bit is to the
1296
right.
1297
1298
INPUT:
1299
1300
- ``reverse`` -- reverse the order of the bits from little endian to
1301
big endian.
1302
1303
EXAMPLES::
1304
1305
sage: k.<a> = GF(2^16)
1306
sage: e = a^14 + a^13 + 1
1307
sage: vector(e) # little endian
1308
(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0)
1309
1310
sage: e._vector_(reverse=True) # big endian
1311
(0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1)
1312
"""
1313
#vector(foo) might pass in ZZ
1314
if PY_TYPE_CHECK(reverse, Parent):
1315
raise TypeError, "Base field is fixed to prime subfield."
1316
1317
cdef GF2X_c r = GF2E_rep(self.x)
1318
cdef int i
1319
1320
(<Cache_ntl_gf2e>self._parent._cache).F.restore()
1321
1322
C = []
1323
for i from 0 <= i < GF2E_degree():
1324
C.append(GF2_conv_to_long(GF2X_coeff(r,i)))
1325
if reverse:
1326
C = list(reversed(C))
1327
return self._parent.vector_space()(C)
1328
1329
def __reduce__(FiniteField_ntl_gf2eElement self):
1330
"""
1331
Used for supporting pickling of finite field elements.
1332
1333
EXAMPLES::
1334
1335
sage: k.<a> = GF(2^16)
1336
sage: loads(dumps(a)) == a
1337
True
1338
"""
1339
return unpickleFiniteField_ntl_gf2eElement, (self._parent, str(self))
1340
1341
def log(self, base):
1342
"""
1343
Return `x` such that `b^x = a`, where `x` is `a` and `b`
1344
is the base.
1345
1346
INPUT:
1347
1348
- ``base`` -- finite field element that generates the multiplicative
1349
group.
1350
1351
OUTPUT:
1352
1353
Integer `x` such that `a^x = b`, if it exists.
1354
Raises a ``ValueError`` exception if no such `x` exists.
1355
1356
EXAMPLES::
1357
1358
sage: F = GF(17)
1359
sage: F(3^11).log(F(3))
1360
11
1361
sage: F = GF(113)
1362
sage: F(3^19).log(F(3))
1363
19
1364
sage: F = GF(next_prime(10000))
1365
sage: F(23^997).log(F(23))
1366
997
1367
1368
sage: F = FiniteField(2^10, 'a')
1369
sage: g = F.gen()
1370
sage: b = g; a = g^37
1371
sage: a.log(b)
1372
37
1373
sage: b^37; a
1374
a^8 + a^7 + a^4 + a + 1
1375
a^8 + a^7 + a^4 + a + 1
1376
1377
AUTHOR: David Joyner and William Stein (2005-11)
1378
"""
1379
from sage.groups.generic import discrete_log
1380
1381
b = self.parent()(base)
1382
return discrete_log(self, b)
1383
1384
def unpickleFiniteField_ntl_gf2eElement(parent, elem):
1385
"""
1386
EXAMPLES::
1387
1388
sage: k.<a> = GF(2^20)
1389
sage: e = k.random_element()
1390
sage: f = loads(dumps(e)) # indirect doctest
1391
sage: e == f
1392
True
1393
"""
1394
return parent(elem)
1395
1396
from sage.structure.sage_object import register_unpickle_override
1397
register_unpickle_override('sage.rings.finite_field_ntl_gf2e', 'unpickleFiniteField_ntl_gf2eElement', unpickleFiniteField_ntl_gf2eElement)
1398
1399