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