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