Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/rings/finite_rings/element_ext_pari.py
4097 views
1
"""
2
Elements of Finite Fields
3
4
EXAMPLES::
5
6
sage: K = FiniteField(2)
7
sage: V = VectorSpace(K,3)
8
sage: w = V([0,1,2])
9
sage: K(1)*w
10
(0, 1, 0)
11
12
We do some arithmetic involving a bigger field and a Conway
13
polynomial, i.e., we verify compatibility condition.
14
15
::
16
17
sage: f = conway_polynomial(2,63)
18
sage: K.<a> = GF(2**63, name='a', modulus=f)
19
sage: n = f.degree()
20
sage: m = 3;
21
sage: e = (2^n - 1) / (2^m - 1)
22
sage: c = a^e
23
sage: conway = conway_polynomial(2,m)
24
sage: conway(c) == 0
25
True
26
"""
27
28
29
import operator
30
31
import sage.structure.element as element
32
import sage.rings.arith as arith
33
import sage.rings.integer_ring as integer_ring
34
from sage.rings.integer import Integer
35
import sage.rings.rational as rational
36
from sage.libs.pari.all import pari, pari_gen
37
from sage.rings.finite_rings.element_base import FinitePolyExtElement
38
import sage.rings.field_element as field_element
39
import sage.rings.finite_rings.integer_mod as integer_mod
40
from element_base import is_FiniteFieldElement
41
from sage.modules.free_module_element import FreeModuleElement
42
from sage.structure.dynamic_class import dynamic_class
43
from sage.categories.finite_fields import FiniteFields
44
45
class FiniteField_ext_pariElement(FinitePolyExtElement):
46
"""
47
An element of a finite field.
48
49
Create elements by first defining the finite field F, then use the
50
notation F(n), for n an integer. or let a = F.gen() and write the
51
element in terms of a.
52
53
EXAMPLES::
54
55
sage: K = FiniteField(10007^10, 'a')
56
sage: a = K.gen(); a
57
a
58
sage: loads(a.dumps()) == a
59
True
60
sage: K = GF(10007)
61
sage: a = K(938); a
62
938
63
sage: loads(a.dumps()) == a
64
True
65
66
TESTS::
67
68
sage: K.<a> = GF(2^16)
69
sage: K(0).is_zero()
70
True
71
sage: (a - a).is_zero()
72
True
73
sage: a - a
74
0
75
sage: a == a
76
True
77
sage: a - a == 0
78
True
79
sage: a - a == K(0)
80
True
81
sage: TestSuite(a).run()
82
"""
83
def __init__(self, parent, value, value_from_pari=False):
84
"""
85
Create element of a finite field.
86
87
INPUT:
88
89
- ``parent``: A finite field, the parent of this element.
90
- ``value``: Anything that can be converted into the PARI
91
interface and can be interpreted as an element of ``parent``.
92
- ``value_from_pari``: optional bool, default False. If it evaluates
93
as true, then ``value`` *must* be an element of the
94
PARI interface, and there will be no conversion.
95
96
NOTE:
97
98
If the given value is a list or an element of the vector space
99
associated with the given parent, then it is interpreted as
100
the list of coefficients of a polynomial over the prime subfield,
101
and that polynomial is interpreted as an element of the given
102
parent. The empty list results in zero.
103
104
If ``value_from_pari==True`` then it is assumed that the given value
105
is a suitable representation of the element in PARI, and there is no
106
conversion. Hence, it is very fast, but must be used with care.
107
108
EXAMPLES::
109
110
sage: from sage.rings.finite_rings.finite_field_ext_pari import FiniteField_ext_pari
111
sage: k = FiniteField_ext_pari(9,'a')
112
sage: a = k(11); a
113
2
114
sage: a.parent()
115
Finite Field in a of size 3^2
116
sage: V = k.vector_space(); v = V((1,2))
117
sage: k(v)
118
2*a + 1
119
120
We create elements using a list and verify that #10486 has been fixed::
121
122
sage: k = FiniteField_ext_pari(3^11, 't')
123
sage: x = k([1,0,2,1]); x
124
t^3 + 2*t^2 + 1
125
sage: x + x + x
126
0
127
sage: pari(x)
128
Mod(Mod(1, 3)*a^3 + Mod(2, 3)*a^2 + Mod(1, 3), Mod(1, 3)*a^11 + Mod(2, 3)*a^2 + Mod(1, 3))
129
130
If the list is longer than the degree, we just get the result
131
modulo the modulus::
132
133
sage: R.<a> = PolynomialRing(GF(5))
134
sage: k = FiniteField_ext_pari(5^2, 't', modulus=a^2-2)
135
sage: x = k([0,0,0,1]); x
136
2*t
137
sage: pari(x)
138
Mod(Mod(2, 5)*a, Mod(1, 5)*a^2 + Mod(3, 5))
139
140
When initializing from a list, the elements are first coerced
141
to the prime field (#11685)::
142
143
sage: k = FiniteField_ext_pari(3^11, 't')
144
sage: k([ 0, 1/2 ])
145
2*t
146
sage: k([ k(0), k(1) ])
147
t
148
sage: k([ GF(3)(2), GF(3^5,'u')(1) ])
149
t + 2
150
sage: R.<x> = PolynomialRing(k)
151
sage: k([ R(-1), x/x ])
152
t + 2
153
154
We demonstrate the creation of an element via polynomials::
155
156
sage: k.polynomial()
157
t^11 + 2*t^2 + 1
158
sage: P = k.polynomial_ring()
159
sage: k(P.0^11)
160
t^2 + 2
161
162
We demonstrate the creation of an element via a vector::
163
164
sage: V = k.vector_space()
165
sage: V
166
Vector space of dimension 11 over Finite Field of size 3
167
sage: v = V([0,1,2,0,1,2,0,1,2,0,1])
168
sage: k(v)
169
t^10 + 2*t^8 + t^7 + 2*t^5 + t^4 + 2*t^2 + t
170
171
TESTS:
172
173
Check that zeros are created correctly (#11685)::
174
175
sage: from sage.rings.finite_rings.finite_field_ext_pari import FiniteField_ext_pari
176
sage: K = FiniteField_ext_pari(3^11, 't'); a = K.0
177
sage: v = 0; pari(K(v)).lift()
178
Mod(0, 3)
179
sage: v = Mod(0,3); pari(K(v)).lift()
180
Mod(0, 3)
181
sage: v = pari(0); pari(K(v)).lift()
182
Mod(0, 3)
183
sage: v = pari("Mod(0,3)"); pari(K(v)).lift()
184
Mod(0, 3)
185
sage: v = []; pari(K(v)).lift()
186
Mod(0, 3)
187
sage: v = [0]; pari(K(v)).lift()
188
Mod(0, 3)
189
sage: v = [0,0]; pari(K(v)).lift()
190
Mod(0, 3)
191
sage: v = pari("Pol(0)"); pari(K(v)).lift()
192
Mod(0, 3)
193
sage: v = pari("Mod(0, %s)"%K._pari_modulus()); pari(K(v)).lift()
194
Mod(0, 3)
195
sage: v = pari("Mod(Pol(0), %s)"%K._pari_modulus()); pari(K(v)).lift()
196
Mod(0, 3)
197
sage: v = K(1) - K(1); pari(K(v)).lift()
198
Mod(0, 3)
199
sage: v = K([1]) - K([1]); pari(K(v)).lift()
200
Mod(0, 3)
201
sage: v = a - a; pari(K(v)).lift()
202
Mod(0, 3)
203
sage: v = K(1)*0; pari(K(v)).lift()
204
Mod(0, 3)
205
sage: v = K([1])*K([0]); pari(K(v)).lift()
206
Mod(0, 3)
207
sage: v = a*0; pari(K(v)).lift()
208
Mod(0, 3)
209
210
The following test documents the optional argument ``value_from_pari``. It is
211
for internal use only and greatly improves the speed in arithmetic
212
operations. However, the example shows why it must only be used
213
carefully::
214
215
sage: from sage.rings.finite_rings.element_ext_pari import FiniteField_ext_pariElement
216
sage: a = FiniteField_ext_pariElement(K,pari(0),value_from_pari=True)
217
sage: a
218
0
219
sage: a == K(0)
220
False
221
222
The reason is that the pari elements representing ``a`` and ``K(0)`` are
223
different::
224
225
sage: pari(a).lift()
226
0
227
sage: pari(K(0)).lift()
228
Mod(0, 3)
229
230
"""
231
field_element.FieldElement.__init__(self, parent)
232
self.__class__ = dynamic_FiniteField_ext_pariElement
233
234
# If value_from_pari is True, directly set self.__value to value.
235
# This assumes that value is a POLMOD with the correct modulus
236
# whose lift is either an INTMOD or a POL with INTMOD
237
# coefficients. In practice, this means that value comes from a
238
# PARI calculation with other elements of this finite field.
239
# This assumption is not checked.
240
if value_from_pari:
241
self.__value = value
242
return
243
244
try:
245
if isinstance(value, pari_gen):
246
try:
247
# In some cases we get two different versions of
248
# the 0 element of a finite field. This has to do
249
# with how PARI's Mod() function works -- it treats
250
# polynomials different from integers.
251
# Also, we need to fix things like ``1/Mod(3,5)`` when
252
# we want ``Mod(2,5)``.
253
# These issues are solved by first simplifying the
254
# given value.
255
value = value.simplify()
256
if value.type() != "t_POLMOD":
257
value = value.Mod(parent._pari_modulus())
258
self.__value = value * parent._pari_one()
259
except RuntimeError:
260
raise TypeError, "no possible coercion implemented"
261
elif isinstance(value, FiniteField_ext_pariElement):
262
if parent != value.parent():
263
raise TypeError, "no coercion implemented"
264
else:
265
self.__value = value.__value
266
elif isinstance(value, FreeModuleElement):
267
if parent.vector_space() != value.parent():
268
raise TypeError, "e.parent must match self.vector_space"
269
self.__value = pari(0).Mod(parent._pari_modulus())*parent._pari_one()
270
for i in range(len(value)):
271
self.__value = self.__value + pari(int(value[i])).Mod(parent._pari_modulus())*pari("a^%s"%i)
272
elif isinstance(value, list):
273
# AUTHOR: Jeroen Demeyer
274
# See Trac #10486 and #11685 for comments about this
275
# implementation
276
277
# We need a special case for the empty list because
278
# PARI's ``Pol([])`` returns an exact 0 while we want
279
# ``Mod(0,3)``.
280
if not value:
281
value = [0]
282
try:
283
# First, try the conversion directly in PARI. This
284
# should cover the most common cases, like converting
285
# from integers or intmods.
286
# Convert the list to PARI, then mod out the
287
# characteristic (PARI can do this directly for lists),
288
# convert to a polynomial with variable "a" and finally
289
# mod out the field modulus.
290
self.__value = pari(value).Mod(parent.characteristic()).Polrev("a").Mod(parent._pari_modulus())
291
except RuntimeError:
292
# That didn't work, do it in a more general but also
293
# slower way: first convert all list elements to the
294
# prime field.
295
GFp = parent.prime_subfield()
296
self.__value = pari([GFp(c) for c in value]).Polrev("a").Mod(parent._pari_modulus())
297
elif isinstance(value, str):
298
raise TypeError, "value must not be a string"
299
else:
300
try:
301
self.__value = pari(value).Mod(parent._pari_modulus())*parent._pari_one()
302
except RuntimeError:
303
raise TypeError, "no coercion implemented"
304
305
except (AttributeError, TypeError):
306
raise TypeError, "unable to coerce"
307
308
def __hash__(self):
309
"""
310
The hash of this element is the hash of the underlying polynomial.
311
312
EXAMPLES::
313
314
sage: k.<a> = GF(3^15)
315
sage: R = GF(3)['a']; aa = R.gen()
316
sage: hash(a^2 + 1) == hash(aa^2 + 1)
317
True
318
"""
319
return hash(self.polynomial())
320
321
def polynomial(self):
322
"""
323
Elements of a finite field are represented as a polynomial modulo a
324
modulus. This function returns the representing polynomial as an
325
element of the polynomial ring over the prime finite field, with
326
the same variable as the finite field.
327
328
EXAMPLES:
329
330
The default variable is a::
331
332
sage: from sage.rings.finite_rings.finite_field_ext_pari import FiniteField_ext_pari
333
sage: k = FiniteField_ext_pari(3**2,'a')
334
sage: k.gen().polynomial()
335
a
336
337
The variable can be any string.
338
339
::
340
341
sage: k = FiniteField(3**4, "alpha")
342
sage: a = k.gen()
343
sage: a.polynomial()
344
alpha
345
sage: (a**2 + 1).polynomial()
346
alpha^2 + 1
347
sage: (a**2 + 1).polynomial().parent()
348
Univariate Polynomial Ring in alpha over Finite Field of size 3
349
"""
350
return self.parent().polynomial_ring()(self.__value.lift())
351
352
def is_square(self):
353
"""
354
Returns True if and only if this element is a perfect square.
355
356
EXAMPLES::
357
358
sage: from sage.rings.finite_rings.finite_field_ext_pari import FiniteField_ext_pari
359
sage: k = FiniteField_ext_pari(3**2, 'a')
360
sage: a = k.gen()
361
sage: a.is_square()
362
False
363
sage: (a**2).is_square()
364
True
365
sage: k = FiniteField_ext_pari(2**2,'a')
366
sage: a = k.gen()
367
sage: (a**2).is_square()
368
True
369
sage: k = FiniteField_ext_pari(17**5,'a'); a = k.gen()
370
sage: (a**2).is_square()
371
True
372
sage: a.is_square()
373
False
374
375
::
376
377
sage: k(0).is_square()
378
True
379
"""
380
K = self.parent()
381
if K.characteristic() == 2:
382
return True
383
n = K.order() - 1
384
a = self**(n // 2)
385
return a == 1 or a == 0
386
387
def square_root(self, extend=False, all=False):
388
"""
389
The square root function.
390
391
INPUT:
392
393
394
- ``extend`` - bool (default: True); if True, return a
395
square root in an extension ring, if necessary. Otherwise, raise a
396
ValueError if the root is not in the base ring. Warning: this
397
option is not implemented!
398
399
- ``all`` - bool (default: False); if True, return all
400
square roots of self, instead of just one.
401
402
403
.. warning::
404
405
The 'extend' option is not implemented (yet).
406
407
EXAMPLES::
408
409
sage: from sage.rings.finite_rings.finite_field_ext_pari import FiniteField_ext_pari
410
sage: F = FiniteField_ext_pari(7^2, 'a')
411
sage: F(2).square_root()
412
4
413
sage: F(3).square_root()
414
5*a + 1
415
sage: F(3).square_root()**2
416
3
417
sage: F(4).square_root()
418
5
419
sage: K = FiniteField_ext_pari(7^3, 'alpha')
420
sage: K(3).square_root()
421
Traceback (most recent call last):
422
...
423
ValueError: must be a perfect square.
424
"""
425
if extend:
426
raise NotImplementedError
427
R = self.parent()['x']
428
f = R([-self, 0, 1])
429
g = f.factor()
430
if len(g) == 2 or g[0][1] == 2:
431
if all:
432
return [-g[0][0][0], g[0][0][0]]
433
else:
434
return -g[0][0][0]
435
if all:
436
return []
437
else:
438
raise ValueError, "must be a perfect square."
439
440
def sqrt(self, extend=False, all = False):
441
"""
442
See :meth:square_root().
443
444
EXAMPLES::
445
446
sage: k.<a> = GF(3^17)
447
sage: (a^3 - a - 1).sqrt()
448
2*a^16 + a^15 + 2*a^13 + a^12 + 2*a^10 + a^9 + a^8 + 2*a^7 + 2*a^6 + a^5 + 2*a^4 + a^2 + a + 1
449
"""
450
return self.square_root(extend=extend, all=all)
451
452
def rational_reconstruction(self):
453
"""
454
If the parent field is a prime field, uses rational reconstruction
455
to try to find a lift of this element to the rational numbers.
456
457
EXAMPLES::
458
459
sage: from sage.rings.finite_rings.finite_field_ext_pari import FiniteField_ext_pari
460
sage: k = GF(97)
461
sage: a = k(RationalField()('2/3'))
462
sage: a
463
33
464
sage: a.rational_reconstruction()
465
2/3
466
"""
467
if self.parent().degree() != 1:
468
raise ArithmeticError, "finite field must be prime"
469
t = arith.rational_reconstruction(int(self), self.parent().characteristic())
470
if t == None or t[1] == 0:
471
raise ZeroDivisionError, "unable to compute rational reconstruction"
472
return rational.Rational((t[0],t[1]))
473
474
def multiplicative_order(self):
475
r"""
476
Returns the *multiplicative* order of this element, which must be
477
nonzero.
478
479
EXAMPLES::
480
481
sage: from sage.rings.finite_rings.finite_field_ext_pari import FiniteField_ext_pari
482
sage: a = FiniteField_ext_pari(5**3, 'a').0
483
sage: a.multiplicative_order()
484
124
485
sage: a**124
486
1
487
"""
488
try:
489
return self.__multiplicative_order
490
except AttributeError:
491
if self.is_zero():
492
raise ArithmeticError("Multiplicative order of 0 not defined.")
493
n = self.parent().order() - 1
494
order = 1
495
for p, e in arith.factor(n):
496
# Determine the power of p that divides the order.
497
a = self**(n//(p**e))
498
while a != 1:
499
order *= p
500
a = a**p
501
self.__multiplicative_order = order
502
return order
503
504
def __copy__(self):
505
"""
506
Return a copy of this element.
507
508
EXAMPLES::
509
510
sage: from sage.rings.finite_rings.finite_field_ext_pari import FiniteField_ext_pari
511
sage: k = FiniteField_ext_pari(3**3,'a')
512
sage: a = k(5)
513
sage: a
514
2
515
sage: copy(a)
516
2
517
sage: b = copy(a)
518
sage: a == b
519
True
520
sage: a is b
521
False
522
sage: a is a
523
True
524
"""
525
return FiniteField_ext_pariElement(self.parent(), self.__value, value_from_pari=True)
526
527
def _pari_(self, var=None):
528
"""
529
Return PARI object corresponding to this finite field element.
530
531
EXAMPLES::
532
533
sage: from sage.rings.finite_rings.finite_field_ext_pari import FiniteField_ext_pari
534
sage: k = FiniteField_ext_pari(3**3, 'a')
535
sage: a = k.gen()
536
sage: b = a**2 + 2*a + 1
537
sage: b._pari_()
538
Mod(Mod(1, 3)*a^2 + Mod(2, 3)*a + Mod(1, 3), Mod(1, 3)*a^3 + Mod(2, 3)*a + Mod(1, 3))
539
540
Looking at the PARI representation of a finite field element, it's
541
no wonder people find PARI difficult to work with directly. Compare
542
our representation::
543
544
sage: b
545
a^2 + 2*a + 1
546
sage: b.parent()
547
Finite Field in a of size 3^3
548
"""
549
if var is None:
550
var = self.parent().variable_name()
551
if var == 'a':
552
return self.__value
553
else:
554
return self.__value.subst('a', var)
555
556
def _pari_init_(self):
557
"""
558
The string producing this finite field element in PARI.
559
560
EXAMPLES::
561
562
sage: k.<a> = GF(3^17)
563
sage: a._pari_init_()
564
'Mod(Mod(1, 3)*a, Mod(1, 3)*a^17 + Mod(2, 3)*a + Mod(1, 3))'
565
"""
566
return str(self.__value)
567
568
def _magma_init_(self, magma):
569
"""
570
Return a string representation of self that Magma can understand.
571
572
EXAMPLES::
573
574
sage: GF(7)(3)._magma_init_(magma) # optional - magma
575
'GF(7)!3'
576
"""
577
km = magma(self.parent())
578
vn = km.gen(1).name()
579
return ("%s"%(self.__value.lift().lift())).replace('a',vn)
580
581
def _gap_init_(self):
582
"""
583
Supports returning corresponding GAP object. This can be slow since
584
non-prime GAP finite field elements are represented as powers of a
585
generator for the multiplicative group, so the discrete log problem
586
must be solved.
587
588
.. note::
589
590
The order of the parent field must be `\leq 65536`.
591
592
EXAMPLES::
593
594
sage: from sage.rings.finite_rings.finite_field_ext_pari import FiniteField_ext_pari
595
sage: F = FiniteField_ext_pari(8,'a')
596
sage: a = F.multiplicative_generator()
597
sage: gap(a) # indirect doctest
598
Z(2^3)
599
sage: b = F.multiplicative_generator()
600
sage: a = b^3
601
sage: gap(a)
602
Z(2^3)^3
603
sage: gap(a^3)
604
Z(2^3)^2
605
606
You can specify the instance of the Gap interpreter that is used::
607
608
sage: F = FiniteField_ext_pari(next_prime(200)^2, 'a')
609
sage: a = F.multiplicative_generator ()
610
sage: a._gap_ (gap)
611
Z(211^2)
612
sage: (a^20)._gap_(gap)
613
Z(211^2)^20
614
615
Gap only supports relatively small finite fields.
616
617
::
618
619
sage: F = FiniteField_ext_pari(next_prime(1000)^2, 'a')
620
sage: a = F.multiplicative_generator ()
621
sage: gap._coerce_(a)
622
Traceback (most recent call last):
623
...
624
TypeError: order must be at most 65536
625
"""
626
F = self.parent()
627
if F.order() > 65536:
628
raise TypeError, "order must be at most 65536"
629
630
if self == 0:
631
return '0*Z(%s)'%F.order()
632
assert F.degree() > 1
633
g = F.multiplicative_generator()
634
n = self.log(g)
635
return 'Z(%s)^%s'%(F.order(), n)
636
637
def _repr_(self):
638
"""
639
String representation of this element.
640
641
EXAMPLES::
642
643
sage: k.<c> = GF(3^17)
644
sage: c^20 # indirect doctest
645
c^4 + 2*c^3
646
"""
647
return ("%s"%(self.__value.lift().lift())).replace('a',self.parent().variable_name())
648
649
def _add_(self, right):
650
"""
651
Addition.
652
653
EXAMPLES::
654
655
sage: k.<a> = GF(3^17)
656
sage: a + a^2 # indirect doctest
657
a^2 + a
658
"""
659
return FiniteField_ext_pariElement(self.parent(), self.__value + right.__value, value_from_pari=True)
660
661
def _sub_(self, right):
662
"""
663
Subtraction.
664
665
EXAMPLES::
666
667
sage: k.<a> = GF(3^17)
668
sage: a - a # indirect doctest
669
0
670
"""
671
return FiniteField_ext_pariElement(self.parent(), self.__value - right.__value, value_from_pari=True)
672
673
def _mul_(self, right):
674
"""
675
Multiplication.
676
677
EXAMPLES::
678
679
sage: k.<a> = GF(3^17)
680
sage: (a^12 + 1)*(a^15 - 1) # indirect doctest
681
a^15 + 2*a^12 + a^11 + 2*a^10 + 2
682
"""
683
return FiniteField_ext_pariElement(self.parent(), self.__value * right.__value, value_from_pari=True)
684
685
def _div_(self, right):
686
"""
687
Division.
688
689
EXAMPLES::
690
691
sage: k.<a> = GF(3^17)
692
sage: (a - 1) / (a + 1) # indirect doctest
693
2*a^16 + a^15 + 2*a^14 + a^13 + 2*a^12 + a^11 + 2*a^10 + a^9 + 2*a^8 + a^7 + 2*a^6 + a^5 + 2*a^4 + a^3 + 2*a^2 + a + 1
694
"""
695
if right.__value == 0:
696
raise ZeroDivisionError
697
return FiniteField_ext_pariElement(self.parent(), self.__value / right.__value, value_from_pari=True)
698
699
def __int__(self):
700
"""
701
Lifting to a python int, if possible.
702
703
EXAMPLES::
704
705
sage: k.<a> = GF(3^17); b = k(2)
706
sage: int(b)
707
2
708
sage: int(a)
709
Traceback (most recent call last):
710
...
711
TypeError: gen must be of PARI type t_INT or t_POL of degree 0
712
"""
713
try:
714
return int(self.__value.lift().lift())
715
except ValueError:
716
raise TypeError, "cannot coerce to int"
717
718
def _integer_(self, ZZ=None):
719
"""
720
Lifting to a sage integer if possible.
721
722
EXAMPLES::
723
724
sage: k.<a> = GF(3^17); b = k(2)
725
sage: b._integer_()
726
2
727
sage: a._integer_()
728
Traceback (most recent call last):
729
...
730
TypeError: Unable to coerce PARI a to an Integer
731
"""
732
return self.lift()
733
734
def __long__(self):
735
"""
736
Lifting to a python long, if possible.
737
738
EXAMPLES::
739
740
sage: k.<a> = GF(3^17); b = k(2)
741
sage: long(b)
742
2L
743
"""
744
try:
745
return long(self.__value.lift().lift())
746
except ValueError:
747
raise TypeError, "cannot coerce to long"
748
749
def __float__(self):
750
"""
751
Lifting to a python float, if possible.
752
753
EXAMPLES::
754
755
sage: k.<a> = GF(3^17); b = k(2)
756
sage: float(b)
757
2.0
758
"""
759
try:
760
return float(self.__value.lift().lift())
761
except ValueError:
762
raise TypeError, "cannot coerce to float"
763
764
def __pow__(self, _right):
765
"""
766
TESTS::
767
768
sage: K.<a> = GF(5^10)
769
sage: n = (2*a)/a
770
771
Naively compute n^-15 in PARI, note that the result is `1/3`.
772
This is mathematically correct (modulo 5), but not what we want.
773
In particular, comparisons will fail::
774
775
sage: pari(n)^-15
776
Mod(1/Mod(3, 5), Mod(1, 5)*a^10 + Mod(3, 5)*a^5 + Mod(3, 5)*a^4 + Mod(2, 5)*a^3 + Mod(4, 5)*a^2 + Mod(1, 5)*a + Mod(2, 5))
777
778
We need to ``simplify()`` the result (which is done in the
779
``FiniteField_ext_pariElement()`` constructor::
780
781
sage: n^-15
782
2
783
784
Large exponents are not a problem::
785
786
sage: e = 3^10000
787
sage: a^e
788
2*a^9 + a^5 + 4*a^4 + 4*a^3 + a^2 + 3*a
789
sage: a^(e % (5^10 - 1))
790
2*a^9 + a^5 + 4*a^4 + 4*a^3 + a^2 + 3*a
791
"""
792
right = int(_right)
793
if right != _right:
794
raise ValueError
795
# It is important to set value_from_pari=False, see doctest above!
796
return FiniteField_ext_pariElement(self.parent(), self.__value**right, value_from_pari=False)
797
798
def __neg__(self):
799
"""
800
Negation.
801
802
EXAMPLES::
803
804
sage: k.<a> = GF(3^17)
805
sage: -a
806
2*a
807
"""
808
return FiniteField_ext_pariElement(self.parent(), -self.__value, value_from_pari=True)
809
810
def __pos__(self):
811
"""
812
Unitary positive operator...
813
814
EXAMPLES::
815
816
sage: k.<a> = GF(3^17)
817
sage: +a
818
a
819
"""
820
return self
821
822
def __abs__(self):
823
"""
824
Absolute value, which is not defined.
825
826
EXAMPLES::
827
828
sage: k.<a> = GF(3^17)
829
sage: abs(a)
830
Traceback (most recent call last):
831
...
832
ArithmeticError: absolute value not defined
833
"""
834
raise ArithmeticError, "absolute value not defined"
835
836
def __invert__(self):
837
"""
838
EXAMPLES::
839
840
sage: from sage.rings.finite_rings.finite_field_ext_pari import FiniteField_ext_pari
841
sage: a = FiniteField_ext_pari(9, 'a').gen()
842
sage: ~a
843
a + 2
844
sage: (a+1)*a
845
2*a + 1
846
sage: ~((2*a)/a)
847
2
848
"""
849
850
if self.__value == 0:
851
raise ZeroDivisionError, "Cannot invert 0"
852
return FiniteField_ext_pariElement(self.parent(), ~self.__value, value_from_pari=True)
853
854
def lift(self):
855
"""
856
If this element lies in a prime finite field, return a lift of this
857
element to an integer.
858
859
EXAMPLES::
860
861
sage: from sage.rings.finite_rings.finite_field_ext_pari import FiniteField_ext_pari
862
sage: k = GF(next_prime(10**10))
863
sage: a = k(17)/k(19)
864
sage: b = a.lift(); b
865
7894736858
866
sage: b.parent()
867
Integer Ring
868
"""
869
return integer_ring.IntegerRing()(self.__value.lift().lift())
870
871
872
def __cmp__(self, other):
873
"""
874
Compare an element of a finite field with other. If other is not an
875
element of a finite field, an attempt is made to coerce it so it is
876
one.
877
878
EXAMPLES::
879
880
sage: from sage.rings.finite_rings.finite_field_ext_pari import FiniteField_ext_pari
881
sage: a = FiniteField_ext_pari(3**3, 'a').gen()
882
sage: a == 1
883
False
884
sage: a**0 == 1
885
True
886
sage: a == a
887
True
888
sage: a < a**2
889
True
890
sage: a > a**2
891
False
892
"""
893
return cmp(self.__value, other.__value)
894
895
def log(self, base):
896
"""
897
Return `x` such that `b^x = a`, where `x`
898
is `a` and `b` is the base.
899
900
INPUT:
901
902
903
- ``self`` - finite field element
904
905
- ``b`` - finite field element that generates the
906
multiplicative group.
907
908
909
OUTPUT: Integer `x` such that `a^x = b`, if it
910
exists. Raises a ValueError exception if no such `x`
911
exists.
912
913
EXAMPLES::
914
915
sage: F = GF(17)
916
sage: F(3^11).log(F(3))
917
11
918
sage: F = GF(113)
919
sage: F(3^19).log(F(3))
920
19
921
sage: F = GF(next_prime(10000))
922
sage: F(23^997).log(F(23))
923
997
924
925
::
926
927
sage: F = FiniteField(2^10, 'a')
928
sage: g = F.gen()
929
sage: b = g; a = g^37
930
sage: a.log(b)
931
37
932
sage: b^37; a
933
a^8 + a^7 + a^4 + a + 1
934
a^8 + a^7 + a^4 + a + 1
935
936
AUTHORS:
937
938
- David Joyner and William Stein (2005-11)
939
"""
940
from sage.groups.generic import discrete_log
941
942
b = self.parent()(base)
943
# TODO: This function is TERRIBLE!
944
return discrete_log(self, b)
945
946
dynamic_FiniteField_ext_pariElement = None
947
def _late_import():
948
"""
949
Used to reset the class of PARI finite field elements in their initialization.
950
951
EXAMPLES::
952
953
sage: from sage.rings.finite_rings.element_ext_pari import FiniteField_ext_pariElement
954
sage: k.<a> = GF(3^17)
955
sage: a.__class__ is FiniteField_ext_pariElement # indirect doctest
956
False
957
"""
958
global dynamic_FiniteField_ext_pariElement
959
dynamic_FiniteField_ext_pariElement = dynamic_class("%s_with_category"%FiniteField_ext_pariElement.__name__, (FiniteField_ext_pariElement, FiniteFields().element_class), doccls=FiniteField_ext_pariElement)
960
961
from sage.structure.sage_object import register_unpickle_override
962
register_unpickle_override('sage.rings.finite_field_element', 'FiniteField_ext_pariElement', FiniteField_ext_pariElement)
963
964