Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/rings/finite_rings/element_givaro.pyx
4108 views
1
r"""
2
Finite Extension Fields of cardinality up to $2^{16}$
3
4
Sage includes the Givaro finite field library, for highly optimized
5
arithmetic in finite fields.
6
7
NOTES:
8
9
The arithmetic is performed by the Givaro C++ library which uses Zech
10
logs internally to represent finite field elements. This
11
implementation is the default finite extension field implementation in
12
Sage for the cardinality $< 2^{16}$, as it is vastly faster than the
13
PARI implementation which uses polynomials to represent finite field
14
elements. Some functionality in this class however is implemented
15
using the PARI implementation.
16
17
EXAMPLES::
18
19
sage: k = GF(5); type(k)
20
<class 'sage.rings.finite_rings.finite_field_prime_modn.FiniteField_prime_modn_with_category'>
21
sage: k = GF(5^2,'c'); type(k)
22
<class 'sage.rings.finite_rings.finite_field_givaro.FiniteField_givaro_with_category'>
23
sage: k = GF(2^16,'c'); type(k)
24
<class 'sage.rings.finite_rings.finite_field_ntl_gf2e.FiniteField_ntl_gf2e_with_category'>
25
sage: k = GF(3^16,'c'); type(k)
26
<class 'sage.rings.finite_rings.finite_field_ext_pari.FiniteField_ext_pari_with_category'>
27
28
sage: n = previous_prime_power(2^16 - 1)
29
sage: while is_prime(n):
30
... n = previous_prime_power(n)
31
sage: factor(n)
32
251^2
33
sage: k = GF(n,'c'); type(k)
34
<class 'sage.rings.finite_rings.finite_field_givaro.FiniteField_givaro_with_category'>
35
36
AUTHORS:
37
38
- Martin Albrecht <[email protected]> (2006-06-05)
39
- William Stein (2006-12-07): editing, lots of docs, etc.
40
- Robert Bradshaw (2007-05-23): is_square/sqrt, pow.
41
42
"""
43
44
45
#*****************************************************************************
46
#
47
# Sage: System for Algebra and Geometry Experimentation
48
#
49
# Copyright (C) 2006 William Stein <[email protected]>
50
#
51
# Distributed under the terms of the GNU General Public License (GPL)
52
#
53
# This code is distributed in the hope that it will be useful,
54
# but WITHOUT ANY WARRANTY; without even the implied warranty of
55
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
56
# General Public License for more details.
57
#
58
# The full text of the GPL is available at:
59
#
60
# http://www.gnu.org/licenses/
61
#*****************************************************************************
62
63
include "../../libs/ntl/decl.pxi"
64
include "../../ext/interrupt.pxi"
65
include "../../ext/stdsage.pxi"
66
67
from sage.misc.randstate cimport randstate, current_randstate
68
from sage.rings.finite_rings.finite_field_base cimport FiniteField
69
from sage.rings.ring cimport Ring
70
from sage.rings.finite_rings.element_ext_pari import FiniteField_ext_pariElement
71
from sage.structure.sage_object cimport SageObject
72
import operator
73
import sage.rings.arith
74
import constructor as finite_field
75
import finite_field_ext_pari
76
77
import sage.interfaces.gap
78
from sage.libs.pari.all import pari
79
from sage.libs.pari.gen import gen
80
81
from sage.structure.parent cimport Parent
82
from sage.structure.parent_base cimport ParentWithBase
83
from sage.structure.parent_gens cimport ParentWithGens
84
85
cdef object is_IntegerMod
86
cdef object Integer
87
cdef object Rational
88
cdef object is_Polynomial
89
cdef object ConwayPolynomials
90
cdef object conway_polynomial
91
cdef object MPolynomial
92
cdef object Polynomial
93
cdef object FreeModuleElement
94
95
cdef void late_import():
96
"""
97
"""
98
global is_IntegerMod, \
99
Integer, \
100
Rational, \
101
is_Polynomial, \
102
ConwayPolynomials, \
103
conway_polynomial, \
104
MPolynomial, \
105
Polynomial, \
106
FreeModuleElement
107
108
if is_IntegerMod is not None:
109
return
110
111
import sage.rings.finite_rings.integer_mod
112
is_IntegerMod = sage.rings.finite_rings.integer_mod.is_IntegerMod
113
114
import sage.rings.integer
115
Integer = sage.rings.integer.Integer
116
117
import sage.rings.rational
118
Rational = sage.rings.rational.Rational
119
120
import sage.rings.polynomial.polynomial_element
121
is_Polynomial = sage.rings.polynomial.polynomial_element.is_Polynomial
122
123
import sage.databases.conway
124
ConwayPolynomials = sage.databases.conway.ConwayPolynomials
125
126
import sage.rings.finite_rings.constructor
127
conway_polynomial = sage.rings.finite_rings.constructor.conway_polynomial
128
129
import sage.rings.polynomial.multi_polynomial_element
130
MPolynomial = sage.rings.polynomial.multi_polynomial_element.MPolynomial
131
132
import sage.rings.polynomial.polynomial_element
133
Polynomial = sage.rings.polynomial.polynomial_element.Polynomial
134
135
import sage.modules.free_module_element
136
FreeModuleElement = sage.modules.free_module_element.FreeModuleElement
137
138
cdef class Cache_givaro(SageObject):
139
def __init__(self, parent, p, k, modulus=None, repr="poly", cache=False):
140
"""
141
Finite Field. These are implemented using Zech logs and the
142
cardinality must be < 2^16. By default conway polynomials are
143
used as minimal polynomial.
144
145
INPUT:
146
q -- p^n (must be prime power)
147
name -- variable used for poly_repr (default: 'a')
148
modulus -- you may provide a polynomial to use for reduction or
149
a string:
150
'conway': force the use of a Conway polynomial, will
151
raise a RuntimeError if none is found in the database;
152
'random': use a random irreducible polynomial.
153
'default':a Conway polynomial is used if found. Otherwise
154
a random polynomial is used.
155
156
Furthermore, for binary fields we allow two more options:
157
'minimal_weight': use a minimal weight polynomial, should
158
result in faster arithmetic;
159
'first_lexicographic': use the first irreducible polynomial
160
in lexicographic order.
161
repr -- controls the way elements are printed to the user:
162
(default: 'poly')
163
'log': repr is element.log_repr()
164
'int': repr is element.int_repr()
165
'poly': repr is element.poly_repr()
166
cache -- if True a cache of all elements of this field is
167
created. Thus, arithmetic does not create new
168
elements which speeds calculations up. Also, if
169
many elements are needed during a calculation
170
this cache reduces the memory requirement as at
171
most self.order() elements are created. (default: False)
172
173
OUTPUT:
174
Givaro finite field with characteristic p and cardinality p^n.
175
176
EXAMPLES:
177
178
By default Conway polynomials are used::
179
180
sage: k.<a> = GF(2**8)
181
sage: -a ^ k.degree()
182
a^4 + a^3 + a^2 + 1
183
sage: f = k.modulus(); f
184
x^8 + x^4 + x^3 + x^2 + 1
185
186
You may enforce a modulus::
187
188
sage: P.<x> = PolynomialRing(GF(2))
189
sage: f = x^8 + x^4 + x^3 + x + 1 # Rijndael polynomial
190
sage: k.<a> = GF(2^8, modulus=f)
191
sage: k.modulus()
192
x^8 + x^4 + x^3 + x + 1
193
sage: a^(2^8)
194
a
195
196
You may enforce a random modulus::
197
198
sage: k = GF(3**5, 'a', modulus='random')
199
sage: k.modulus() # random polynomial
200
x^5 + 2*x^4 + 2*x^3 + x^2 + 2
201
202
For binary fields, you may ask for a minimal weight polynomial::
203
204
sage: k = GF(2**10, 'a', modulus='minimal_weight')
205
sage: k.modulus()
206
x^10 + x^3 + 1
207
208
Three different representations are possible::
209
210
sage: sage.rings.finite_rings.finite_field_givaro.FiniteField_givaro(9,repr='poly').gen()
211
a
212
sage: sage.rings.finite_rings.finite_field_givaro.FiniteField_givaro(9,repr='int').gen()
213
3
214
sage: sage.rings.finite_rings.finite_field_givaro.FiniteField_givaro(9,repr='log').gen()
215
5
216
"""
217
# we are calling late_import here because this constructor is
218
# called at least once before any arithmetic is performed.
219
late_import()
220
221
cdef intvec cPoly
222
cdef GF2X_c ntl_m, ntl_tmp
223
cdef GF2_c c
224
225
self.parent = <Parent?> parent
226
227
if repr=='poly':
228
self.repr = 0
229
elif repr=='log':
230
self.repr = 1
231
elif repr=='int':
232
self.repr = 2
233
else:
234
raise RuntimeError
235
236
if isinstance(modulus,str) and p == 2:
237
if modulus == "minimal_weight":
238
GF2X_BuildSparseIrred(ntl_m, k)
239
elif modulus == "first_lexicographic":
240
GF2X_BuildIrred(ntl_m, k)
241
elif modulus == "random":
242
current_randstate().set_seed_ntl(False)
243
GF2X_BuildSparseIrred(ntl_tmp, k)
244
GF2X_BuildRandomIrred(ntl_m, ntl_tmp)
245
else:
246
raise ValueError, "Cannot understand modulus"
247
248
modulus = []
249
for i in range(k+1):
250
c = GF2X_coeff(ntl_m, i)
251
if not GF2_IsZero(c):
252
modulus.append(1)
253
else:
254
modulus.append(0)
255
256
if is_Polynomial(modulus):
257
modulus = modulus.list()
258
259
if PY_TYPE_CHECK(modulus, list) or PY_TYPE_CHECK(modulus, tuple):
260
for i in modulus:
261
cPoly.push_back(int( i % p ))
262
sig_on()
263
self.objectptr = gfq_factorypkp(p, k, cPoly)
264
elif modulus == "random":
265
sig_on()
266
self.objectptr = gfq_factorypk(p,k)
267
else:
268
raise ValueError, "Cannot understand modulus"
269
270
self._zero_element = make_FiniteField_givaroElement(self,self.objectptr.zero)
271
self._one_element = make_FiniteField_givaroElement(self,self.objectptr.one)
272
sig_off()
273
274
parent._zero_element = self._zero_element
275
parent._one_element = self._one_element
276
if cache:
277
self._array = self.gen_array()
278
self._has_array = True
279
280
cdef gen_array(self):
281
"""
282
Generates an array/list/tuple containing all elements of self indexed by their
283
power with respect to the internal generator.
284
"""
285
cdef int i
286
287
array = list()
288
for i from 0 <= i < self.order_c():
289
array.append(make_FiniteField_givaroElement(self,i) )
290
return tuple(array)
291
292
def __dealloc__(self):
293
"""
294
Free the memory occupied by this Givaro finite field.
295
"""
296
delete(self.objectptr)
297
298
cpdef int characteristic(self):
299
"""
300
Return the characteristic of this field.
301
302
EXAMPLES:
303
sage: p = GF(19^3,'a')._cache.characteristic(); p
304
19
305
"""
306
return self.objectptr.characteristic()
307
308
def order(self):
309
"""
310
Returns the order of this field.
311
312
EXAMPLES::
313
314
sage: K.<a> = GF(9)
315
sage: K._cache.order()
316
9
317
"""
318
return Integer(self.order_c())
319
320
cpdef int order_c(self):
321
"""
322
Returns the order of this field.
323
324
EXAMPLES::
325
326
sage: K.<a> = GF(9)
327
sage: K._cache.order_c()
328
9
329
"""
330
return self.objectptr.cardinality()
331
332
cpdef int exponent(self):
333
"""
334
Returns the degree of this field over GF(p).
335
336
EXAMPLES::
337
338
sage: K.<a> = GF(9); K._cache.exponent()
339
2
340
"""
341
return self.objectptr.exponent()
342
343
def random_element(self, *args, **kwds):
344
"""
345
Return a random element of self.
346
347
INPUT:
348
*args -- ignored
349
**kwds -- ignored
350
351
EXAMPLES:
352
sage: k = GF(23**3, 'a')
353
sage: e = k._cache.random_element(); e
354
9*a^2 + 10*a + 3
355
sage: type(e)
356
<type 'sage.rings.finite_rings.element_givaro.FiniteField_givaroElement'>
357
358
sage: P.<x> = PowerSeriesRing(GF(3^3, 'a'))
359
sage: P.random_element(5)
360
a^2 + 2*a + 1 + (a + 1)*x + (a^2 + a + 1)*x^2 + (a^2 + 1)*x^3 + (2*a^2 + a)*x^4 + O(x^5)
361
"""
362
cdef int seed = current_randstate().c_random()
363
cdef int res
364
cdef GivRandom generator = GivRandomSeeded(seed)
365
res = self.objectptr.random(generator,res)
366
return make_FiniteField_givaroElement(self,res)
367
368
cpdef FiniteField_givaroElement element_from_data(self, e):
369
"""
370
Coerces several data types to self.
371
372
INPUT:
373
374
- ``e`` -- data to coerce in.
375
376
EXAMPLES::
377
378
sage: k = GF(2**8, 'a')
379
sage: e = k.vector_space().gen(1); e
380
(0, 1, 0, 0, 0, 0, 0, 0)
381
sage: k(e) #indirect doctest
382
a
383
384
For more examples, see sage.rings.finite_rings.finite_field_givaro.FiniteField_givaro._element_constructor_
385
"""
386
cdef int res
387
cdef int g
388
cdef int x
389
cdef int e_int
390
391
cdef FiniteField_givaroElement to_add
392
########
393
394
if PY_TYPE_CHECK(e, FiniteField_givaroElement):
395
if e.parent() is self.parent:
396
return e
397
if e.parent() == self.parent:
398
return make_FiniteField_givaroElement(self,(<FiniteField_givaroElement>e).element)
399
if e.parent() is self.parent.prime_subfield() or e.parent() == self.parent.prime_subfield():
400
res = self.int_to_log(int(e))
401
else:
402
raise TypeError, "unable to coerce from a finite field other than the prime subfield"
403
404
elif PY_TYPE_CHECK(e, int) or \
405
PY_TYPE_CHECK(e, Integer) or \
406
PY_TYPE_CHECK(e, long) or is_IntegerMod(e):
407
try:
408
e_int = e
409
if e != e_int: # overflow in Pyrex is often not detected correctly... but this is bullet proof.
410
# sometimes it is detected correctly, so we do have to use exceptions though.
411
# todo -- be more eloquent here!!
412
raise OverflowError
413
res = self.objectptr.initi(res,e_int)
414
except OverflowError:
415
e = e % self.characteristic()
416
res = self.objectptr.initi(res,int(e))
417
418
elif e is None:
419
e_int = 0
420
res = self.objectptr.initi(res,e_int)
421
422
elif PY_TYPE_CHECK(e, float):
423
res = self.objectptr.initd(res,e)
424
425
elif PY_TYPE_CHECK(e, str):
426
return self.parent(eval(e.replace("^","**"),self.parent.gens_dict()))
427
428
elif PY_TYPE_CHECK(e, FreeModuleElement):
429
if self.parent.vector_space() != e.parent():
430
raise TypeError, "e.parent must match self.vector_space"
431
ret = self._zero_element
432
for i in range(len(e)):
433
e_entry = e[i] % self.characteristic()
434
res = self.objectptr.initi(res, int(e_entry))
435
to_add = make_FiniteField_givaroElement(self, res)
436
ret = ret + to_add*self.parent.gen()**i
437
return ret
438
439
elif PY_TYPE_CHECK(e, MPolynomial):
440
if e.is_constant():
441
return self.parent(e.constant_coefficient())
442
else:
443
raise TypeError, "no coercion defined"
444
445
elif PY_TYPE_CHECK(e, Polynomial):
446
if e.is_constant():
447
return self.parent(e.constant_coefficient())
448
else:
449
return e.change_ring(self.parent)(self.parent.gen())
450
451
elif PY_TYPE_CHECK(e, Rational):
452
num = e.numer()
453
den = e.denom()
454
return self.parent(num)/self.parent(den)
455
456
elif PY_TYPE_CHECK(e, gen):
457
pass # handle this in next if clause
458
459
elif PY_TYPE_CHECK(e,FiniteField_ext_pariElement):
460
# reduce FiniteField_ext_pariElements to pari
461
e = e._pari_()
462
463
elif sage.interfaces.gap.is_GapElement(e):
464
from sage.interfaces.gap import gfq_gap_to_sage
465
return gfq_gap_to_sage(e, self.parent)
466
467
elif isinstance(e, list):
468
if len(e) > self.exponent():
469
# could reduce here...
470
raise ValueError, "list is too long"
471
ret = self._zero_element
472
for i in range(len(e)):
473
e_entry = e[i] % self.characteristic()
474
res = self.objectptr.initi(res, int(e_entry))
475
to_add = make_FiniteField_givaroElement(self, res)
476
ret = ret + to_add*self.parent.gen()**i
477
return ret
478
479
else:
480
raise TypeError, "unable to coerce"
481
482
if PY_TYPE_CHECK(e, gen):
483
e = e.lift().lift()
484
try:
485
res = self.int_to_log(e[0])
486
except TypeError:
487
res = self.int_to_log(e)
488
489
g = self.objectptr.sage_generator()
490
x = self.objectptr.one
491
492
for i from 0 < i <= e.poldegree():
493
x = self.objectptr.mul(x,x,g)
494
res = self.objectptr.axpyin( res, self.int_to_log(e[i]) , x)
495
496
return make_FiniteField_givaroElement(self,res)
497
498
cpdef FiniteField_givaroElement gen(self):
499
"""
500
Returns a generator of the field.
501
502
EXAMPLES::
503
504
sage: K.<a> = GF(625)
505
sage: K._cache.gen()
506
a
507
"""
508
return make_FiniteField_givaroElement(self, self.objectptr.sage_generator())
509
510
def log_to_int(self, int n):
511
r"""
512
Given an integer $n$ this method returns $i$ where $i$
513
satisfies \code{self.gen()^n == i}, if the result is
514
interpreted as an integer.
515
516
INPUT:
517
n -- log representation of a finite field element
518
519
OUTPUT:
520
integer representation of a finite field element.
521
522
EXAMPLE:
523
sage: k = GF(2**8, 'a')
524
sage: k._cache.log_to_int(4)
525
16
526
sage: k._cache.log_to_int(20)
527
180
528
"""
529
cdef int ret
530
531
if n<0:
532
raise ArithmeticError, "Cannot serve negative exponent %d"%n
533
elif n>=self.order_c():
534
raise IndexError, "n=%d must be < self.order()"%n
535
sig_on()
536
ret = int(self.objectptr.convert(ret, n))
537
sig_off()
538
return ret
539
540
def int_to_log(self, int n):
541
r"""
542
Given an integer $n$ this method returns $i$ where $i$ satisfies
543
\code{self.gen()^i==(n\%self.characteristic())}.
544
545
INPUT:
546
n -- integer representation of an finite field element
547
548
OUTPUT:
549
log representation of n
550
551
EXAMPLE:
552
sage: k = GF(7**3, 'a')
553
sage: k._cache.int_to_log(4)
554
228
555
sage: k._cache.int_to_log(3)
556
57
557
sage: k.gen()^57
558
3
559
"""
560
cdef int r
561
sig_on()
562
ret = int(self.objectptr.initi(r,n))
563
sig_off()
564
return ret
565
566
def fetch_int(self, int n):
567
r"""
568
Given an integer $n$ return a finite field element in self
569
which equals $n$ under the condition that self.gen() is set to
570
self.characteristic().
571
572
EXAMPLE:
573
sage: k.<a> = GF(2^8)
574
sage: k._cache.fetch_int(8)
575
a^3
576
sage: e = k._cache.fetch_int(151); e
577
a^7 + a^4 + a^2 + a + 1
578
sage: 2^7 + 2^4 + 2^2 + 2 + 1
579
151
580
"""
581
cdef GivaroGfq *k = self.objectptr
582
cdef int ret = k.zero
583
cdef int a = k.sage_generator()
584
cdef int at = k.one
585
cdef unsigned int ch = k.characteristic()
586
cdef int _n, t, i
587
588
if n<0 or n>k.cardinality():
589
raise TypeError, "n must be between 0 and self.order()"
590
591
_n = n
592
593
for i from 0 <= i < k.exponent():
594
t = k.initi(t, _n%ch)
595
ret = k.axpy(ret, t, at, ret)
596
at = k.mul(at,at,a)
597
_n = _n/ch
598
return make_FiniteField_givaroElement(self, ret)
599
600
def _element_repr(self, FiniteField_givaroElement e):
601
"""
602
Wrapper for log, int, and poly representations.
603
604
EXAMPLES:
605
sage: k.<a> = GF(3^4); k
606
Finite Field in a of size 3^4
607
sage: k._cache._element_repr(a^20)
608
'2*a^3 + 2*a^2 + 2'
609
610
sage: k = sage.rings.finite_rings.finite_field_givaro.FiniteField_givaro(3^4,'a', repr='int')
611
sage: a = k.gen()
612
sage: k._cache._element_repr(a^20)
613
'74'
614
615
sage: k = sage.rings.finite_rings.finite_field_givaro.FiniteField_givaro(3^4,'a', repr='log')
616
sage: a = k.gen()
617
sage: k._cache._element_repr(a^20)
618
'20'
619
"""
620
if self.repr==0:
621
return self._element_poly_repr(e)
622
elif self.repr==1:
623
return self._element_log_repr(e)
624
else:
625
return self._element_int_repr(e)
626
627
def _element_log_repr(self, FiniteField_givaroElement e):
628
r"""
629
Return str(i) where \code{base.gen()^i==self}.
630
631
TODO -- this isn't what it does -- see below.
632
633
EXAMPLES:
634
sage: k.<a> = GF(3^4); k
635
Finite Field in a of size 3^4
636
sage: k._cache._element_log_repr(a^20)
637
'20'
638
sage: k._cache._element_log_repr(a) # TODO -- why 41 ?? why not 1?
639
'41'
640
"""
641
return str(int(e.element))
642
643
def _element_int_repr(self, FiniteField_givaroElement e):
644
"""
645
Return integer representation of e.
646
647
Elements of this field are represented as ints in as follows:
648
for $e \in \FF_p[x]$ with $e = a_0 + a_1x + a_2x^2 + \cdots $, $e$ is
649
represented as: $n= a_0 + a_1 p + a_2 p^2 + \cdots$.
650
651
EXAMPLES:
652
sage: k.<a> = GF(3^4); k
653
Finite Field in a of size 3^4
654
sage: k._cache._element_int_repr(a^20)
655
'74'
656
"""
657
return str(e.integer_representation())
658
659
def _element_poly_repr(self, FiniteField_givaroElement e, varname = None):
660
"""
661
Return a polynomial expression in base.gen() of self.
662
663
EXAMPLES:
664
sage: k.<a> = GF(3^4); k
665
Finite Field in a of size 3^4
666
sage: k._cache._element_poly_repr(a^20)
667
'2*a^3 + 2*a^2 + 2'
668
"""
669
if varname is None:
670
variable = self.parent.variable_name()
671
else:
672
variable = varname
673
674
quo = self.log_to_int(e.element)
675
b = int(self.characteristic())
676
677
ret = ""
678
for i in range(self.exponent()):
679
coeff = quo%b
680
if coeff != 0:
681
if i>0:
682
if coeff==1:
683
coeff=""
684
else:
685
coeff=str(coeff)+"*"
686
if i>1:
687
ret = coeff + variable + "^" + str(i) + " + " + ret
688
else:
689
ret = coeff + variable + " + " + ret
690
else:
691
ret = str(coeff) + " + " + ret
692
quo = quo/b
693
if ret == '':
694
return "0"
695
return ret[:-3]
696
697
def a_times_b_plus_c(self,FiniteField_givaroElement a, FiniteField_givaroElement b, FiniteField_givaroElement c):
698
"""
699
Return r = a*b + c. This is faster than multiplying a and b
700
first and adding c to the result.
701
702
INPUT:
703
a -- FiniteField_givaroElement
704
b -- FiniteField_givaroElement
705
c -- FiniteField_givaroElement
706
707
EXAMPLE:
708
sage: k.<a> = GF(2**8)
709
sage: k._cache.a_times_b_plus_c(a,a,k(1))
710
a^2 + 1
711
"""
712
cdef int r
713
714
r = self.objectptr.axpy(r, a.element, b.element, c.element)
715
return make_FiniteField_givaroElement(self,r)
716
717
def a_times_b_minus_c(self,FiniteField_givaroElement a, FiniteField_givaroElement b, FiniteField_givaroElement c):
718
"""
719
Return r = a*b - c.
720
721
INPUT:
722
a -- FiniteField_givaroElement
723
b -- FiniteField_givaroElement
724
c -- FiniteField_givaroElement
725
726
EXAMPLE:
727
sage: k.<a> = GF(3**3)
728
sage: k._cache.a_times_b_minus_c(a,a,k(1))
729
a^2 + 2
730
"""
731
cdef int r
732
733
r = self.objectptr.axmy(r, a.element, b.element, c.element, )
734
return make_FiniteField_givaroElement(self,r)
735
736
def c_minus_a_times_b(self,FiniteField_givaroElement a,
737
FiniteField_givaroElement b, FiniteField_givaroElement c):
738
"""
739
Return r = c - a*b.
740
741
INPUT:
742
a -- FiniteField_givaroElement
743
b -- FiniteField_givaroElement
744
c -- FiniteField_givaroElement
745
746
EXAMPLE:
747
sage: k.<a> = GF(3**3)
748
sage: k._cache.c_minus_a_times_b(a,a,k(1))
749
2*a^2 + 1
750
"""
751
cdef int r
752
753
r = self.objectptr.amxy(r , a.element, b.element, c.element, )
754
return make_FiniteField_givaroElement(self,r)
755
756
def __reduce__(self):
757
"""
758
For pickling.
759
760
TESTS::
761
762
sage: k.<a> = GF(3^8)
763
sage: TestSuite(a).run()
764
"""
765
p, k = self.order().factor()[0]
766
if self.repr == 0:
767
rep = 'poly'
768
elif self.repr == 1:
769
rep = 'log'
770
elif self.repr == 2:
771
rep = 'int'
772
return unpickle_Cache_givaro, (self.parent, p, k, self.parent.polynomial(), rep, self._has_array)
773
774
cdef FiniteField_givaroElement _new_c(self, int value):
775
return make_FiniteField_givaroElement(self, value)
776
777
778
def unpickle_Cache_givaro(parent, p, k, modulus, rep, cache):
779
"""
780
EXAMPLE:
781
sage: k = GF(3**7, 'a')
782
sage: loads(dumps(k)) == k # indirect doctest
783
True
784
"""
785
return Cache_givaro(parent, p, k, modulus, rep, cache)
786
787
cdef class FiniteField_givaro_iterator:
788
"""
789
Iterator over :class:`FiniteField_givaro` elements. We iterate
790
multiplicatively, as powers of a fixed internal generator.
791
792
EXAMPLES::
793
794
sage: for x in GF(2^2,'a'): print x
795
0
796
a
797
a + 1
798
1
799
"""
800
801
def __init__(self, Cache_givaro cache):
802
"""
803
EXAMPLE::
804
805
sage: k.<a> = GF(3^4)
806
sage: i = iter(k) # indirect doctest
807
sage: i
808
Iterator over Finite Field in a of size 3^4
809
"""
810
self._cache = cache
811
self.iterator = -1
812
813
def __next__(self):
814
"""
815
EXAMPLE::
816
817
sage: k.<a> = GF(3^4)
818
sage: i = iter(k) # indirect doctest
819
sage: i.next()
820
0
821
sage: i.next()
822
2*a
823
"""
824
825
self.iterator=self.iterator+1
826
827
if self.iterator==self._cache.order_c():
828
self.iterator = -1
829
raise StopIteration
830
831
return make_FiniteField_givaroElement(self._cache,self.iterator)
832
833
def __repr__(self):
834
"""
835
EXAMPLE::
836
837
sage: k.<a> = GF(3^4)
838
sage: i = iter(k)
839
sage: i # indirect doctest
840
Iterator over Finite Field in a of size 3^4
841
"""
842
return "Iterator over %s"%self._cache.parent
843
844
def __iter__(self):
845
"""
846
EXAMPLE::
847
848
sage: K.<a> = GF(4)
849
sage: K.list() # indirect doctest
850
[0, a, a + 1, 1]
851
"""
852
return self
853
854
cdef class FiniteField_givaroElement(FinitePolyExtElement):
855
"""
856
An element of a (Givaro) finite field.
857
"""
858
859
def __init__(FiniteField_givaroElement self, parent ):
860
"""
861
Initializes an element in parent. It's much better to use
862
parent(<value>) or any specialized method of parent
863
like gen() instead. In general do not call this
864
constructor directly.
865
866
Alternatively you may provide a value which is directly
867
assigned to this element. So the value must represent the
868
log_g of the value you wish to assign.
869
870
INPUT:
871
parent -- base field
872
873
OUTPUT:
874
finite field element.
875
876
EXAMPLE:
877
sage: k.<a> = GF(5^2)
878
sage: from sage.rings.finite_rings.element_givaro import FiniteField_givaroElement
879
sage: FiniteField_givaroElement(k)
880
0
881
882
"""
883
FinitePolyExtElement.__init__(self, parent)
884
self._cache = parent._cache
885
self.element = 0
886
887
cdef FiniteField_givaroElement _new_c(self, int value):
888
return make_FiniteField_givaroElement(self._cache, value)
889
890
def __dealloc__(FiniteField_givaroElement self):
891
pass
892
893
def _repr_(FiniteField_givaroElement self):
894
"""
895
EXAMPLE:
896
sage: k.<FOOBAR> = GF(3^4)
897
sage: FOOBAR #indirect doctest
898
FOOBAR
899
900
sage: k.<FOOBAR> = GF(3^4,repr='log')
901
sage: FOOBAR
902
41
903
904
sage: k.<FOOBAR> = GF(3^4,repr='int')
905
sage: FOOBAR
906
3
907
"""
908
return self._cache._element_repr(self)
909
910
def _element(self):
911
"""
912
Returns the int interally representing this element.
913
914
EXAMPLES::
915
916
sage: k.<a> = GF(3^4)
917
sage: (a^2 + 1)._element()
918
58
919
"""
920
return self.element
921
922
def __nonzero__(FiniteField_givaroElement self):
923
r"""
924
Return True if \code{self != k(0)}.
925
926
EXAMPLES:
927
sage: k.<a> = GF(3^4); k
928
Finite Field in a of size 3^4
929
sage: a.is_zero()
930
False
931
sage: k(0).is_zero()
932
True
933
"""
934
return not self._cache.objectptr.isZero(self.element)
935
936
def is_one(FiniteField_givaroElement self):
937
r"""
938
Return True if \code{self == k(1)}.
939
940
EXAMPLES:
941
sage: k.<a> = GF(3^4); k
942
Finite Field in a of size 3^4
943
sage: a.is_one()
944
False
945
sage: k(1).is_one()
946
True
947
"""
948
return self._cache.objectptr.isOne(self.element)
949
950
def is_unit(FiniteField_givaroElement self):
951
"""
952
Return True if self is nonzero, so it is a unit as an element of the
953
finite field.
954
955
EXAMPLES:
956
sage: k.<a> = GF(3^4); k
957
Finite Field in a of size 3^4
958
sage: a.is_unit()
959
True
960
sage: k(0).is_unit()
961
False
962
"""
963
return not (<Cache_givaro>self._cache).objectptr.isZero(self.element)
964
# **WARNING** Givaro seems to define unit to mean in the prime field,
965
# which is totally wrong! It's a confusion with the underlying polynomial
966
# representation maybe?? That's why the following is commented out.
967
# return (<FiniteField_givaro>self._parent).objectptr.isunit(self.element)
968
969
970
def is_square(FiniteField_givaroElement self):
971
"""
972
Return True if self is a square in self.parent()
973
974
EXAMPLES:
975
sage: k.<a> = GF(9); k
976
Finite Field in a of size 3^2
977
sage: a.is_square()
978
False
979
sage: v = set([x^2 for x in k])
980
sage: [x.is_square() for x in v]
981
[True, True, True, True, True]
982
sage: [x.is_square() for x in k if not x in v]
983
[False, False, False, False]
984
985
ALGORITHM:
986
Elements are stored as powers of generators, so we simply check
987
to see if it is an even power of a generator.
988
989
TESTS:
990
sage: K = GF(27, 'a')
991
sage: set([a*a for a in K]) == set([a for a in K if a.is_square()])
992
True
993
sage: K = GF(25, 'a')
994
sage: set([a*a for a in K]) == set([a for a in K if a.is_square()])
995
True
996
sage: K = GF(16, 'a')
997
sage: set([a*a for a in K]) == set([a for a in K if a.is_square()])
998
True
999
"""
1000
cdef Cache_givaro cache = <Cache_givaro>self._cache
1001
if cache.objectptr.characteristic() == 2:
1002
return True
1003
elif self.element == cache.objectptr.one:
1004
return True
1005
else:
1006
return self.element % 2 == 0
1007
1008
def sqrt(FiniteField_givaroElement self, extend=False, all=False):
1009
"""
1010
Return a square root of this finite field element in its
1011
parent, if there is one. Otherwise, raise a ValueError.
1012
1013
INPUT:
1014
extend -- bool (default: True); if True, return a square
1015
root in an extension ring, if necessary. Otherwise,
1016
raise a ValueError if the root is not in the base
1017
ring. Warning: this option is not implemented!
1018
all -- bool (default: False); if True, return all square
1019
roots of self, instead of just one.
1020
1021
WARNING:
1022
The 'extend' option is not implemented (yet).
1023
1024
EXAMPLES:
1025
sage: k.<a> = GF(7^2)
1026
sage: k(2).sqrt()
1027
3
1028
sage: k(3).sqrt()
1029
2*a + 6
1030
sage: k(3).sqrt()**2
1031
3
1032
sage: k(4).sqrt()
1033
2
1034
sage: k.<a> = GF(7^3)
1035
sage: k(3).sqrt()
1036
Traceback (most recent call last):
1037
...
1038
ValueError: must be a perfect square.
1039
1040
ALGORITHM:
1041
Self is stored as $a^k$ for some generator $a$.
1042
Return $a^(k/2)$ for even $k$.
1043
1044
TESTS:
1045
sage: K = GF(49, 'a')
1046
sage: all([a.sqrt()*a.sqrt() == a for a in K if a.is_square()])
1047
True
1048
sage: K = GF(27, 'a')
1049
sage: all([a.sqrt()*a.sqrt() == a for a in K if a.is_square()])
1050
True
1051
sage: K = GF(8, 'a')
1052
sage: all([a.sqrt()*a.sqrt() == a for a in K if a.is_square()])
1053
True
1054
"""
1055
if all:
1056
a = self.sqrt()
1057
return [a, -a] if -a != a else [a]
1058
cdef Cache_givaro cache = <Cache_givaro>self._cache
1059
if self.element == cache.objectptr.one:
1060
return make_FiniteField_givaroElement(cache, cache.objectptr.one)
1061
elif self.element % 2 == 0:
1062
return make_FiniteField_givaroElement(cache, self.element/2)
1063
elif cache.objectptr.characteristic() == 2:
1064
return make_FiniteField_givaroElement(cache, (cache.objectptr.cardinality() - 1 + self.element)/2)
1065
elif extend:
1066
raise NotImplementedError # TODO: fix this once we have nested embeddings of finite fields
1067
else:
1068
raise ValueError, "must be a perfect square."
1069
1070
cpdef ModuleElement _add_(self, ModuleElement right):
1071
"""
1072
Add two elements.
1073
1074
EXAMPLE:
1075
sage: k.<b> = GF(9**2)
1076
sage: b^10 + 2*b # indirect doctest
1077
2*b^3 + 2*b^2 + 2*b + 1
1078
"""
1079
cdef int r
1080
r = self._cache.objectptr.add(r, self.element ,
1081
(<FiniteField_givaroElement>right).element )
1082
return make_FiniteField_givaroElement(self._cache,r)
1083
1084
cpdef ModuleElement _iadd_(self, ModuleElement right):
1085
"""
1086
Add two elements inplace.
1087
1088
EXAMPLE:
1089
sage: k.<b> = GF(9**2)
1090
sage: b^10 + 2*b # indirect doctest
1091
2*b^3 + 2*b^2 + 2*b + 1
1092
"""
1093
cdef int r
1094
self.element = self._cache.objectptr.add(r, self.element ,
1095
(<FiniteField_givaroElement>right).element )
1096
return self
1097
1098
1099
cpdef RingElement _mul_(self, RingElement right):
1100
"""
1101
Multiply two elements:
1102
1103
EXAMPLE:
1104
sage: k.<c> = GF(7**4)
1105
sage: 3*c # indirect doctest
1106
3*c
1107
sage: c*c
1108
c^2
1109
"""
1110
cdef int r
1111
r = self._cache.objectptr.mul(r, self.element,
1112
(<FiniteField_givaroElement>right).element)
1113
return make_FiniteField_givaroElement(self._cache,r)
1114
1115
1116
cpdef RingElement _imul_(self, RingElement right):
1117
"""
1118
Multiply two elements inplace.
1119
1120
EXAMPLE:
1121
sage: k.<c> = GF(7**4)
1122
sage: 3*c # indirect doctest
1123
3*c
1124
sage: c*c
1125
c^2
1126
"""
1127
cdef int r
1128
self.element = self._cache.objectptr.mul(r, self.element,
1129
(<FiniteField_givaroElement>right).element)
1130
return self
1131
1132
cpdef RingElement _div_(self, RingElement right):
1133
"""
1134
Divide two elements
1135
1136
EXAMPLE:
1137
sage: k.<g> = GF(2**8)
1138
sage: g/g # indirect doctest
1139
1
1140
1141
sage: k(1) / k(0)
1142
Traceback (most recent call last):
1143
...
1144
ZeroDivisionError: division by zero in finite field.
1145
"""
1146
cdef int r
1147
if (<FiniteField_givaroElement>right).element == 0:
1148
raise ZeroDivisionError, 'division by zero in finite field.'
1149
r = self._cache.objectptr.div(r, self.element,
1150
(<FiniteField_givaroElement>right).element)
1151
return make_FiniteField_givaroElement(self._cache,r)
1152
1153
cpdef RingElement _idiv_(self, RingElement right):
1154
"""
1155
Divide two elements inplace
1156
1157
EXAMPLE:
1158
sage: k.<g> = GF(2**8)
1159
sage: g/g # indirect doctest
1160
1
1161
1162
sage: k(1) / k(0)
1163
Traceback (most recent call last):
1164
...
1165
ZeroDivisionError: division by zero in finite field.
1166
"""
1167
1168
cdef int r
1169
if (<FiniteField_givaroElement>right).element == 0:
1170
raise ZeroDivisionError, 'division by zero in finite field.'
1171
self.element = self._cache.objectptr.div(r, self.element,
1172
(<FiniteField_givaroElement>right).element)
1173
return self
1174
1175
cpdef ModuleElement _sub_(self, ModuleElement right):
1176
"""
1177
Subtract two elements
1178
1179
EXAMPLE:
1180
sage: k.<a> = GF(3**4)
1181
sage: k(3) - k(1) # indirect doctest
1182
2
1183
sage: 2*a - a^2
1184
2*a^2 + 2*a
1185
"""
1186
cdef int r
1187
r = self._cache.objectptr.sub(r, self.element,
1188
(<FiniteField_givaroElement>right).element)
1189
return make_FiniteField_givaroElement(self._cache,r)
1190
1191
cpdef ModuleElement _isub_(self, ModuleElement right):
1192
"""
1193
Subtract two elements inplace
1194
1195
EXAMPLE:
1196
sage: k.<a> = GF(3**4)
1197
sage: k(3) - k(1) # indirect doctest
1198
2
1199
sage: 2*a - a^2
1200
2*a^2 + 2*a
1201
"""
1202
cdef int r
1203
self.element = self._cache.objectptr.sub(r, self.element,
1204
(<FiniteField_givaroElement>right).element)
1205
return self
1206
1207
def __neg__(FiniteField_givaroElement self):
1208
"""
1209
Negative of an element.
1210
1211
EXAMPLES:
1212
sage: k.<a> = GF(9); k
1213
Finite Field in a of size 3^2
1214
sage: -a
1215
2*a
1216
"""
1217
cdef int r
1218
1219
r = self._cache.objectptr.neg(r, self.element)
1220
return make_FiniteField_givaroElement(self._cache,r)
1221
1222
def __invert__(FiniteField_givaroElement self):
1223
"""
1224
Return the multiplicative inverse of an element.
1225
1226
EXAMPLES:
1227
sage: k.<a> = GF(9); k
1228
Finite Field in a of size 3^2
1229
sage: ~a
1230
a + 2
1231
sage: ~a*a
1232
1
1233
"""
1234
cdef int r
1235
1236
self._cache.objectptr.inv(r, self.element)
1237
return make_FiniteField_givaroElement(self._cache,r)
1238
1239
def __pow__(FiniteField_givaroElement self, exp, other):
1240
"""
1241
EXAMPLES::
1242
1243
sage: K.<a> = GF(3^3, 'a')
1244
sage: a^3 == a*a*a
1245
True
1246
sage: b = a+1
1247
sage: b^5 == b^2 * b^3
1248
True
1249
sage: b^(-1) == 1/b
1250
True
1251
sage: b = K(-1)
1252
sage: b^2 == 1
1253
True
1254
1255
TESTS:
1256
1257
The following checks that #7923 is resolved::
1258
1259
sage: K.<a> = GF(3^10)
1260
sage: b = a^9 + a^7 + 2*a^6 + a^4 + a^3 + 2*a^2 + a + 2
1261
sage: b^(71*7381) == (b^71)^7381
1262
True
1263
1264
ALGORITHM:
1265
1266
Givaro objects are stored as integers $i$ such that $self=a^i$, where
1267
$a$ is a generator of $K$ (though not necessarily the one returned by K.gens()).
1268
Now it is trivial to compute $(a^i)^exp = a^(i*exp)$, and reducing the exponent
1269
mod the multiplicative order of $K$.
1270
1271
AUTHOR:
1272
1273
- Robert Bradshaw
1274
"""
1275
if not isinstance(exp, (int, Integer)):
1276
_exp = Integer(exp)
1277
if _exp != exp:
1278
raise ValueError, "exponent must be an integer"
1279
exp = _exp
1280
1281
cdef Cache_givaro cache = self._cache
1282
1283
if (cache.objectptr).isOne(self.element):
1284
return self
1285
1286
elif exp == 0:
1287
if (cache.objectptr).isZero(self.element):
1288
raise ArithmeticError, "0^0 is undefined."
1289
return make_FiniteField_givaroElement(cache, cache.objectptr.one)
1290
1291
elif (cache.objectptr).isZero(self.element):
1292
if exp < 0:
1293
raise ZeroDivisionError
1294
return make_FiniteField_givaroElement(cache, cache.objectptr.zero)
1295
1296
cdef int order = (cache.order_c()-1)
1297
cdef int r = exp % order
1298
1299
if r == 0:
1300
return make_FiniteField_givaroElement(cache, cache.objectptr.one)
1301
1302
cdef unsigned int r_unsigned
1303
if r < 0:
1304
r_unsigned = <unsigned int> r + order
1305
else:
1306
r_unsigned = <unsigned int>r
1307
cdef unsigned int elt_unsigned = <unsigned int>self.element
1308
cdef unsigned int order_unsigned = <unsigned int>order
1309
r = <int>(r_unsigned * elt_unsigned) % order_unsigned
1310
if r == 0:
1311
return make_FiniteField_givaroElement(cache, cache.objectptr.one)
1312
return make_FiniteField_givaroElement(cache, r)
1313
1314
def __richcmp__(left, right, int op):
1315
"""
1316
EXAMPLE:
1317
sage: k.<a> = GF(9); k
1318
Finite Field in a of size 3^2
1319
sage: a == k('a') # indirect doctest
1320
True
1321
sage: a == a + 1
1322
False
1323
"""
1324
return (<Element>left)._richcmp(right, op)
1325
1326
cdef int _cmp_c_impl(left, Element right) except -2:
1327
"""
1328
Comparison of finite field elements is correct or equality
1329
tests and somewhat random for < and > type of
1330
comparisons. This implementation performs these tests by
1331
comparing the underlying int representations.
1332
1333
EXAMPLES:
1334
sage: k.<a> = GF(9); k
1335
Finite Field in a of size 3^2
1336
sage: a == k('a')
1337
True
1338
sage: a == a + 1
1339
False
1340
1341
Even though inequality tests do return answers, they
1342
really make no sense as finite fields are unordered. Thus,
1343
you cannot rely on the result as it is implementation specific.
1344
1345
sage: a < a^2
1346
True
1347
sage: a^2 < a
1348
False
1349
"""
1350
cdef Cache_givaro cache = (<FiniteField_givaroElement>left)._cache
1351
1352
return cmp(cache.log_to_int(left.element), cache.log_to_int((<FiniteField_givaroElement>right).element) )
1353
1354
def __int__(FiniteField_givaroElement self):
1355
"""
1356
Return the int representation of self. When self is in the
1357
prime subfield, the integer returned is equal to self, otherwise
1358
an error is raised.
1359
1360
EXAMPLES:
1361
sage: k.<b> = GF(5^2); k
1362
Finite Field in b of size 5^2
1363
sage: int(k(4))
1364
4
1365
sage: int(b)
1366
Traceback (most recent call last):
1367
...
1368
TypeError: Cannot coerce element to an integer.
1369
1370
"""
1371
cdef int self_int = self._cache.log_to_int(self.element)
1372
if self_int%self._cache.characteristic() != self_int:
1373
raise TypeError("Cannot coerce element to an integer.")
1374
return self_int
1375
1376
def integer_representation(FiniteField_givaroElement self):
1377
"""
1378
Return the integer representation of self. When self is in the
1379
prime subfield, the integer returned is equal to self and not
1380
to \code{log_repr}.
1381
1382
Elements of this field are represented as ints in as follows:
1383
for $e \in \FF_p[x]$ with $e = a_0 + a_1x + a_2x^2 + \cdots $, $e$ is
1384
represented as: $n= a_0 + a_1 p + a_2 p^2 + \cdots$.
1385
1386
EXAMPLES:
1387
sage: k.<b> = GF(5^2); k
1388
Finite Field in b of size 5^2
1389
sage: k(4).integer_representation()
1390
4
1391
sage: b.integer_representation()
1392
5
1393
sage: type(b.integer_representation())
1394
<type 'int'>
1395
"""
1396
return self._cache.log_to_int(self.element)
1397
1398
def _integer_(FiniteField_givaroElement self, ZZ=None):
1399
"""
1400
Convert self to an integer if it is in the prime subfield.
1401
1402
EXAMPLES::
1403
1404
sage: k.<b> = GF(5^2); k
1405
Finite Field in b of size 5^2
1406
sage: k(4)._integer_()
1407
4
1408
sage: ZZ(b)
1409
Traceback (most recent call last):
1410
...
1411
TypeError: not in prime subfield
1412
"""
1413
cdef int a = self._cache.log_to_int(self.element)
1414
if a < self._cache.objectptr.characteristic():
1415
return Integer(a)
1416
raise TypeError, "not in prime subfield"
1417
1418
def log_to_int(FiniteField_givaroElement self):
1419
r"""
1420
Returns the int representation of self, as a Sage integer. Use
1421
int(self) to directly get a Python int.
1422
1423
Elements of this field are represented as ints in as follows:
1424
for $e \in \FF_p[x]$ with $e = a_0 + a_1x + a_2x^2 + \cdots $, $e$ is
1425
represented as: $n= a_0 + a_1 p + a_2 p^2 + \cdots$.
1426
1427
EXAMPLES:
1428
sage: k.<b> = GF(5^2); k
1429
Finite Field in b of size 5^2
1430
sage: k(4).log_to_int()
1431
4
1432
sage: b.log_to_int()
1433
5
1434
sage: type(b.log_to_int())
1435
<type 'sage.rings.integer.Integer'>
1436
"""
1437
return Integer(self._cache.log_to_int(self.element))
1438
1439
def log(FiniteField_givaroElement self, base):
1440
"""
1441
Return the log to the base b of self, i.e., an integer n
1442
such that b^n = self.
1443
1444
WARNING: TODO -- This is currently implemented by solving the discrete
1445
log problem -- which shouldn't be needed because of how finite field
1446
elements are represented.
1447
1448
EXAMPLES:
1449
sage: k.<b> = GF(5^2); k
1450
Finite Field in b of size 5^2
1451
sage: a = b^7
1452
sage: a.log(b)
1453
7
1454
"""
1455
b = self.parent()(base)
1456
return sage.groups.generic.discrete_log(self, b)
1457
1458
def int_repr(FiniteField_givaroElement self):
1459
r"""
1460
Return the string representation of self as an int (as returned
1461
by \code{log_to_int}).
1462
1463
EXAMPLES:
1464
sage: k.<b> = GF(5^2); k
1465
Finite Field in b of size 5^2
1466
sage: (b+1).int_repr()
1467
'6'
1468
"""
1469
return self._cache._element_int_repr(self)
1470
1471
def log_repr(FiniteField_givaroElement self):
1472
r"""
1473
Return the log representation of self as a string. See the
1474
documentation of the \code{_element_log_repr} function of the
1475
parent field.
1476
1477
EXAMPLES:
1478
sage: k.<b> = GF(5^2); k
1479
Finite Field in b of size 5^2
1480
sage: (b+2).log_repr()
1481
'3'
1482
"""
1483
return self._cache._element_log_repr(self)
1484
1485
def poly_repr(FiniteField_givaroElement self):
1486
r"""
1487
Return representation of this finite field element as a polynomial
1488
in the generator.
1489
1490
EXAMPLES:
1491
sage: k.<b> = GF(5^2); k
1492
Finite Field in b of size 5^2
1493
sage: (b+2).poly_repr()
1494
'b + 2'
1495
"""
1496
return self._cache._element_poly_repr(self)
1497
1498
def polynomial(FiniteField_givaroElement self, name=None):
1499
"""
1500
Return self viewed as a polynomial over self.parent().prime_subfield().
1501
1502
EXAMPLES:
1503
sage: k.<b> = GF(5^2); k
1504
Finite Field in b of size 5^2
1505
sage: f = (b^2+1).polynomial(); f
1506
b + 4
1507
sage: type(f)
1508
<type 'sage.rings.polynomial.polynomial_zmod_flint.Polynomial_zmod_flint'>
1509
sage: parent(f)
1510
Univariate Polynomial Ring in b over Finite Field of size 5
1511
"""
1512
cdef Cache_givaro cache = self._cache
1513
K = self.parent()
1514
quo = cache.log_to_int(self.element)
1515
b = int(cache.characteristic())
1516
ret = []
1517
for i in range(K.degree()):
1518
coeff = quo%b
1519
ret.append(coeff)
1520
quo = quo/b
1521
if not name is None and K.variable_name() != name:
1522
from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
1523
return PolynomialRing(K.prime_subfield(), name)(ret)
1524
else:
1525
return K.polynomial_ring()(ret)
1526
1527
def _finite_field_ext_pari_element(FiniteField_givaroElement self, k=None):
1528
"""
1529
Return an element of k supposed to match this element. No
1530
checks if k equals self.parent() are performed.
1531
1532
INPUT:
1533
k -- (optional) FiniteField_ext_pari
1534
1535
OUTPUT:
1536
k.gen()^(self.log_repr())
1537
1538
EXAMPLES:
1539
sage: S.<b> = GF(5^2); S
1540
Finite Field in b of size 5^2
1541
sage: b.charpoly('x')
1542
x^2 + 4*x + 2
1543
sage: P = S._finite_field_ext_pari_(); type(P)
1544
<class 'sage.rings.finite_rings.finite_field_ext_pari.FiniteField_ext_pari_with_category'>
1545
sage: c = b._finite_field_ext_pari_element(P); c
1546
b
1547
sage: type(c)
1548
<class 'sage.rings.finite_rings.element_ext_pari.FiniteField_ext_pariElement_with_category'>
1549
sage: c.charpoly('x')
1550
x^2 + 4*x + 2
1551
1552
The PARI field is automatically determined if it is not given:
1553
sage: d = b._finite_field_ext_pari_element(); d
1554
b
1555
sage: type(d)
1556
<class 'sage.rings.finite_rings.element_ext_pari.FiniteField_ext_pariElement_with_category'>
1557
"""
1558
if k is None:
1559
k = self.parent()._finite_field_ext_pari_()
1560
elif not isinstance(k, finite_field_ext_pari.FiniteField_ext_pari):
1561
raise TypeError, "k must be a pari finite field."
1562
1563
variable = k.gen()._pari_()
1564
1565
quo = self.integer_representation()
1566
b = int(self._cache.characteristic())
1567
1568
ret = k._pari_one() - k._pari_one() # TODO -- weird
1569
i = 0
1570
while quo!=0:
1571
coeff = quo%b
1572
if coeff != 0:
1573
ret = coeff * variable ** i + ret
1574
quo = quo/b
1575
i = i+1
1576
return k(ret)
1577
1578
def _pari_(FiniteField_givaroElement self, var=None):
1579
r"""
1580
Return PARI representation of this finite field element.
1581
1582
INPUT:
1583
1584
``var`` -- optional variable string (default: ``None``)
1585
1586
EXAMPLES::
1587
1588
sage: k.<a> = GF(5^3)
1589
sage: a._pari_()
1590
Mod(Mod(1, 5)*a, Mod(1, 5)*a^3 + Mod(3, 5)*a + Mod(3, 5))
1591
1592
sage: a._pari_('b')
1593
Mod(Mod(1, 5)*b, Mod(1, 5)*b^3 + Mod(3, 5)*b + Mod(3, 5))
1594
1595
sage: t = 3*a^2 + 2*a + 4
1596
sage: t_string = t._pari_init_('y')
1597
sage: t_string
1598
'Mod(Mod(3, 5)*y^2 + Mod(2, 5)*y + Mod(4, 5), Mod(1, 5)*y^3 + Mod(3, 5)*y + Mod(3, 5))'
1599
sage: type(t_string)
1600
<type 'str'>
1601
sage: t_element = t._pari_('b')
1602
sage: t_element
1603
Mod(Mod(3, 5)*b^2 + Mod(2, 5)*b + Mod(4, 5), Mod(1, 5)*b^3 + Mod(3, 5)*b + Mod(3, 5))
1604
sage: t_element.parent()
1605
Interface to the PARI C library
1606
"""
1607
return pari(self._pari_init_(var))
1608
1609
def _magma_init_(self, magma):
1610
"""
1611
Return a string representation of self that MAGMA can
1612
understand.
1613
1614
EXAMPLE:
1615
sage: k.<a> = GF(3^5)
1616
1617
String rep of parent:
1618
sage: k._magma_init_(magma) # optional - magma
1619
'SageCreateWithNames(ext<GF(3)|_sage_[...]![GF(3)!1,GF(3)!2,GF(3)!0,GF(3)!0,GF(3)!0,GF(3)!1]>,["a"])'
1620
1621
Magma repr of element:
1622
sage: a._magma_init_(magma) # optional - magma
1623
'_sage_[...]!(_sage_[...])'
1624
1625
Because of caching the string representation of an element must not change:
1626
sage: a._magma_init_(magma) == a._magma_init_(magma) # optional - magma
1627
True
1628
1629
We test a conversion back and forth:
1630
sage: k.<a> = GF(3^6)
1631
sage: b = magma(a^5 + 2*a^2 + 1) # optional - magma
1632
1633
Note that small fields print using a log representation in Magma (unlike Sage):
1634
sage: b # optional - magma
1635
a^436
1636
sage: b.sage() # optional - magma
1637
a^5 + 2*a^2 + 1
1638
"""
1639
R = magma(self.parent())
1640
a = R.gen(1).name()
1641
return '%s!(%s)'%(R.name(), self._cache._element_poly_repr(self, a))
1642
1643
def multiplicative_order(FiniteField_givaroElement self):
1644
"""
1645
Return the multiplicative order of this field element.
1646
1647
EXAMPLES:
1648
sage: S.<b> = GF(5^2); S
1649
Finite Field in b of size 5^2
1650
sage: b.multiplicative_order()
1651
24
1652
sage: (b^6).multiplicative_order()
1653
4
1654
"""
1655
# TODO -- I'm sure this can be made vastly faster
1656
# using how elements are represented as a power of the generator ??
1657
1658
# code copy'n'pasted from element_ext_pari.py
1659
import sage.rings.arith
1660
1661
if self._multiplicative_order is not None:
1662
return self._multiplicative_order
1663
else:
1664
if self.is_zero():
1665
raise ArithmeticError("Multiplicative order of 0 not defined.")
1666
n = (self._cache).order_c() - 1
1667
order = 1
1668
for p, e in sage.rings.arith.factor(n):
1669
# Determine the power of p that divides the order.
1670
a = self**(n/(p**e))
1671
while a != 1:
1672
order = order * p
1673
a = a**p
1674
1675
self._multiplicative_order = order
1676
return order
1677
1678
def __copy__(self):
1679
"""
1680
Return a copy of this element. Actually just returns self, since
1681
finite field elements are immutable.
1682
1683
EXAMPLES:
1684
sage: S.<b> = GF(5^2); S
1685
Finite Field in b of size 5^2
1686
sage: c = copy(b); c
1687
b
1688
sage: c is b
1689
True
1690
sage: copy(5r) is 5r
1691
True
1692
"""
1693
return self
1694
1695
def _gap_init_(FiniteField_givaroElement self):
1696
"""
1697
Return a string that evaluates to the GAP representation of
1698
this element.
1699
1700
A NotImplementedError is raised if self.parent().modulus() is
1701
not a Conway polynomial, as the isomorphism of finite fields is
1702
not implemented yet.
1703
1704
EXAMPLES:
1705
sage: S.<b> = GF(5^2); S
1706
Finite Field in b of size 5^2
1707
sage: (4*b+3)._gap_init_()
1708
'Z(25)^3'
1709
sage: S(gap('Z(25)^3'))
1710
4*b + 3
1711
"""
1712
#copied from element_ext_pari.py
1713
cdef Cache_givaro cache = self._cache
1714
F = self.parent()
1715
if F.degree() == 1:
1716
# Find the root of unity used by Gap. See _gap_init_ in sage.rings.finite_rings.integer_mod
1717
from sage.interfaces.all import gap # here to reduce dependencies
1718
from sage.rings.finite_rings.integer_mod import mod
1719
g = int(gap.eval('Int(Z(%s))'%cache.order_c()))
1720
n = self.log(mod(g, cache.order_c()))
1721
return 'Z(%s)^%s'%(cache.order_c(), n)
1722
if not F._is_conway:
1723
raise NotImplementedError, "conversion of (Givaro) finite field element to GAP not implemented except for fields defined by Conway polynomials."
1724
if cache.order_c() > 65536:
1725
raise TypeError, "order (=%s) must be at most 65536."%F.order_c()
1726
if self == 0:
1727
return '0*Z(%s)'%cache.order_c()
1728
g = F.multiplicative_generator()
1729
n = self.log(g)
1730
return 'Z(%s)^%s'%(cache.order_c(), n)
1731
1732
def __hash__(FiniteField_givaroElement self):
1733
"""
1734
Return the hash of this finite field element. We hash the parent
1735
and the underlying integer representation of this element.
1736
1737
EXAMPLES:
1738
sage: S.<a> = GF(5^3); S
1739
Finite Field in a of size 5^3
1740
sage: hash(a)
1741
5
1742
"""
1743
return hash(self.log_to_int())
1744
1745
def _vector_(FiniteField_givaroElement self, reverse=False):
1746
"""
1747
Return a vector in self.parent().vector_space() matching
1748
self. The most significant bit is to the right.
1749
1750
INPUT:
1751
reverse -- reverse the order of the bits
1752
from little endian to big endian.
1753
1754
EXAMPLES:
1755
sage: k.<a> = GF(2^4)
1756
sage: e = a^2 + 1
1757
sage: v = vector(e)
1758
sage: v
1759
(1, 0, 1, 0)
1760
sage: k(v)
1761
a^2 + 1
1762
1763
sage: k.<a> = GF(3^4)
1764
sage: e = 2*a^2 + 1
1765
sage: v = vector(e)
1766
sage: v
1767
(1, 0, 2, 0)
1768
sage: k(v)
1769
2*a^2 + 1
1770
1771
You can also compute the vector in the other order:
1772
1773
sage: e._vector_(reverse=True)
1774
(0, 2, 0, 1)
1775
"""
1776
#vector(foo) might pass in ZZ
1777
if PY_TYPE_CHECK(reverse, Parent):
1778
raise TypeError, "Base field is fixed to prime subfield."
1779
cdef Cache_givaro cache = self._cache
1780
k = self.parent()
1781
1782
quo = cache.log_to_int(self.element)
1783
b = int(k.characteristic())
1784
1785
ret = []
1786
for i in range(k.degree()):
1787
coeff = quo%b
1788
ret.append(coeff)
1789
quo = quo/b
1790
if reverse:
1791
ret = list(reversed(ret))
1792
return k.vector_space()(ret)
1793
1794
def __reduce__(FiniteField_givaroElement self):
1795
"""
1796
Used for supporting pickling of finite field elements.
1797
1798
EXAMPLE:
1799
sage: k = GF(2**8, 'a')
1800
sage: e = k.random_element()
1801
sage: TestSuite(e).run() # indirect doctest
1802
"""
1803
return unpickle_FiniteField_givaroElement,(self.parent(),self.element)
1804
1805
def unpickle_FiniteField_givaroElement(parent, int x):
1806
"""
1807
TESTS::
1808
1809
sage: k = GF(3**4, 'a')
1810
sage: e = k.random_element()
1811
sage: TestSuite(e).run() # indirect doctest
1812
"""
1813
return make_FiniteField_givaroElement(parent._cache, x)
1814
1815
from sage.structure.sage_object import register_unpickle_override
1816
register_unpickle_override('sage.rings.finite_field_givaro', 'unpickle_FiniteField_givaroElement', unpickle_FiniteField_givaroElement)
1817
1818
cdef inline FiniteField_givaroElement make_FiniteField_givaroElement(Cache_givaro cache, int x):
1819
cdef FiniteField_givaroElement y
1820
1821
if cache._has_array:
1822
return <FiniteField_givaroElement>cache._array[x]
1823
else:
1824
y = PY_NEW(FiniteField_givaroElement)
1825
y._parent = <Parent> cache.parent
1826
y._cache = cache
1827
y.element = x
1828
return y
1829
1830
1831